DFS 1253 解题报告
来源:互联网 发布:微信斗图软件 编辑:程序博客网 时间:2024/06/04 00:39
题目的大致意思是,对于类似 xml 或者 json 格式的数据,进行增、删、改、输出。可见需要用到的算法便是 DFS。
大致思路如下:
- 对初始数据利用 DFS 建立一颗树,方便后续进行增、删、修改、输出。
- 利用哈希算法对其降低运算维度。
- 操作完成后,对步骤 1 进行反向 DFS,输出答案。
建树
根据题意,我们要建的树如下图:
很显然,我们需要利用 DFS 来建立它。每个节点都包含左孩子,右兄弟,当然,每个节点必须有一个父节点。指向父节点的指针没有画出来,自己脑补。
我在建立这颗树的时候,浪费了太多的时间,以致于后面没有时间进行调试。所以,必须熟练的写这个建树过程,达到能够快速码代码。
建立哈希表
一开始我只用了哈希函数,把字符串转化成一个对应的哈希值,然后单单用来进行判断而已。代码如下:
int getHashCode(char s[]){ ULL ret = 1; rint i = 0; while(s[i] != '\0') { ret += ((ret << 7) + s[i++] + 3); //(左移7 并且 +2 = 131) } return (ret % MAX_NODE_NUM);}
恩,没错,我只做到这一步。那么每次我去找节点的时候,都得把所有的节点寻找一遍。如下代码:
int findNode(ULL code){ for(rint i = 0; i < cnt; i++)//遍历一遍,code为计算出来的哈希值 { if(node[i].isDelete) continue; if(code == node[i].keyCode) { return i; } } return -1;}
实际上,可以利用哈希值创建一个哈希表,根据 key 直接取出结果,而不必遍历,更加优化。每次取值只需调用get()便可,建立哈希表如下:
NODE* hashMap[MAX_NODE_NUM];//添加节点,key - valuevoid put(char str[], NODE* node){ int key = getHashCode(str); if(hashMap[key] == 0) { hashMap[key] = node; } else//哈希冲突链表 { node->next = hashMap[key]; hashMap[key] = node; }}//获取节点NODE* get(char str[]){ int key = getHashCode(str); NODE* cur = hashMap[key]; if(cur && cur->next == 0) return cur; while(cur)//解决哈希冲突 { if(isSameStr(cur->keyStr, str) == true)//直接比较字符串是否相等 break; else cur=cur->next; } return cur;}
增加,删除节点
这一部分,看似没什么好讲,实际上删除节点这部分,我还是踩坑了。一开始我没有采用哈希表的方法,所以删除一个节点后,没有把他的子节点全部标识为删除状态。那么在
findNode(ULL code)
的时候,会去遍历到已经删除的子节点,会导致错误。这需要递归去把他的子节点标识为删除状态。代码如下:
void markForDelete(NODE* tar){ if(tar == 0) return; tar->isDelete = true; if(tar->leftChind)//递归遍历这颗子树 { NODE* rb = tar->leftChind; markForDelete(rb); while(rb->rightBro) { rb = rb->rightBro; markForDelete(rb); } }}
当然,改用哈希表的方法不需要这么处理。
总结和完整源码
这到题目的感觉就是,有思路可以做出来啊,但是就是码出不来。原因还是不熟,功力不够,针对这类型的题目还得多写代码。
1)整个核心就是建树过程,添加节点过程,删除过程。这个是最重要的。
2)一定先读懂题意,比如这道题就明确说了最多节点也就400个,要先知道题目确切的意思。确切的数据量大小。
3)先整理思路(要清晰)和搭好框架,然后填代码。
//////////////////////////////user code////////////////////////////#define STRINGTYPE 0x01#define SETTYPE 0x02#define MAX_KEY_LENGTH 15#define MAX_VALUE_LENGTH 127#define MAX_MESSAGE_LENGTH 81920#define MAX_NODE_NUM (401)#define ULL unsigned long long#define rint unsigned registertypedef struct NODE_{ int type; char keyStr[MAX_KEY_LENGTH]; int keyLen; int keyOne; int keySec; char valueStr[MAX_VALUE_LENGTH]; int valueLen; int valueOne; int valueSec; NODE_ *parent; NODE_ *leftChind; NODE_ *leftBro; NODE_ *rightBro; NODE_ *next;}NODE;NODE* hashMap[MAX_NODE_NUM];NODE node[MAX_NODE_NUM];int cnt=0;int start = 0;int target = 0;NODE *Root;//tool functionint getHashCode(char s[]);void ztrDecodecpy(char dest[], const char src[], const int offset, const int length);void ztrEncodeCpy(char dest[], const char src[], const int offset, const int length);int ztrlen(const char str[]) ;void init();void put(char str[], NODE* node);NODE* get(char str[]);bool isSameStr(char s1[], char s2[]);//build tree and revert treevoid buildSetTree(NODE *par, char in[]);void revertSetTree(NODE* tar, char out[MAX_MESSAGE_LENGTH]);//add & del & find node operationvoid addChild(NODE* par, NODE* node, bool flag = false);void delChild(NODE* cur);void markForDelete(NODE* tar);//int findNode(ULL code);bool isSameStr(char s1[], char s2[]){ bool ret = false; int len1 = ztrlen(s1); int len2 = ztrlen(s2); if(len1 == len2) { ret = true; while(len1--) { if(s1[len1] != s2[len1]) { ret = false; break; } } } return ret;}void put(char str[], NODE* node){ int key = getHashCode(str); if(hashMap[key] == 0) { hashMap[key] = node; } else//哈希冲突链表 { node->next = hashMap[key]; hashMap[key] = node; }}NODE* get(char str[]){ int key = getHashCode(str); NODE* cur = hashMap[key]; if(cur && cur->next == 0) return cur; while(cur) { if(isSameStr(cur->keyStr, str) == true) break; else cur=cur->next; } return cur;}int getHashCode(char s[]){ ULL ret = 1; rint i = 0; while(s[i] != '\0') { ret += ((ret << 7) + s[i++] + 3); } return (ret % MAX_NODE_NUM);}void init(){ for(rint i = 0; i < MAX_NODE_NUM; i++) { hashMap[i] = 0; node[i].type = 0; node[i].keyOne = 0; node[i].keyLen = 0; node[i].keySec = 0; node[i].valueLen = 0; node[i].valueOne = 0; node[i].valueSec = 0; for(rint j = 0; j < MAX_KEY_LENGTH; j++) { node[i].keyStr[j] = 0; } for(rint j = 0; j < MAX_VALUE_LENGTH; j++) { node[i].valueStr[j] = 0; } node[i].leftChind = 0; node[i].rightBro = 0; node[i].parent = 0; node[i].leftBro = 0; node[i].next = 0; } cnt = 0; start = 0; target = 0; Root = &node[cnt++];}void ztrDecodecpy(char dest[], const char src[], const int offset, const int length) { int pos = 0; while (pos < length && src[pos + offset] != '\0') { dest[pos] = src[pos + offset]; ++pos; } dest[pos] = '\0';}void ztrEncodeCpy(char dest[], const char src[], const int offset, const int length) { int pos = 0; while (pos < length && src[pos] != '\0') { dest[offset + pos] = src[pos]; ++pos; }}int ztrlen(const char str[]) { int pos = 0; while(str[pos] != '\0') ++pos; return pos;}void addChild(NODE* par, NODE* node, bool flag){ if(par == 0 || node == 0) return; put(node->keyStr, node); node->parent = par; if(!par->leftChind) { par->leftChind = node; } else { NODE* rb = par->leftChind; while(rb->rightBro) { rb = rb->rightBro; } rb->rightBro = node; } if(flag == true) { par->valueLen++; par->valueSec = (par->valueLen & 0xff); par->valueOne = (par->valueLen >> 8); }}void delChild(NODE* cur){ if(!cur) return; NODE* par = cur->parent; if(!par) return; NODE* rb = par->leftChind; bool isFind = false; if(rb == cur) { par->leftChind = rb->rightBro; rb->leftBro = 0; isFind = true; } else { while(rb->rightBro) { if(rb->rightBro == cur) { isFind = true; break; } else { rb = rb->rightBro; } } } if(isFind) { rb->rightBro = cur->rightBro; par->valueLen--; par->valueOne = par->valueLen >> 8; par->valueSec = par->valueLen & 0xff; }}void buildSetTree(NODE *par, char in[]){ int type = in[start]; start++; NODE* cur = &node[cnt++]; cur->type = type; //key cur->keyOne = in[start++]; cur->keySec = in[start++]; cur->keyLen = (cur->keyOne >> 8) + cur->keySec; ztrDecodecpy(cur->keyStr, in, start, cur->keyLen); //value start += cur->keyLen; cur->valueOne = in[start++]; cur->valueSec = in[start++]; cur->valueLen = (cur->valueOne >> 8) + cur->valueSec; if(type == STRINGTYPE) { ztrDecodecpy(cur->valueStr, in, start, cur->valueLen); start += cur->valueLen; } else { //build child for(rint i = 0; i < cur->valueLen; i++) { buildSetTree(cur, in); } } addChild(par, cur);}void revertSetTree(NODE* tar, char out[MAX_MESSAGE_LENGTH]){ int type = tar->type; out[target++] = type; out[target++] = tar->keyOne; out[target++] = tar->keySec; ztrEncodeCpy(out, tar->keyStr, target, tar->keyLen); target += tar->keyLen; out[target++] = tar->valueOne; out[target++] = tar->valueSec; if(type == STRINGTYPE) { ztrEncodeCpy(out, tar->valueStr, target, tar->valueLen); target += tar->valueLen; } else { if(tar->leftChind) { NODE* rb = tar->leftChind; revertSetTree(rb, out); while(rb->rightBro) { rb=rb->rightBro; revertSetTree(rb, out); } } }}void parse(char in[MAX_MESSAGE_LENGTH], int size){ init(); buildSetTree(Root, in);}void set(char targetkey[MAX_KEY_LENGTH + 1], char newvalue[MAX_VALUE_LENGTH + 1]){ int len = ztrlen(newvalue); NODE* cur = get(targetkey); if(cur == 0) return; cur->valueLen = len; cur->valueOne = len >> 8; cur->valueSec = len & 0xff; ztrDecodecpy(cur->valueStr, newvalue, 0, len);}void add(char parentkey[MAX_KEY_LENGTH + 1], char childkey[MAX_KEY_LENGTH + 1], char childvalue[MAX_VALUE_LENGTH + 1]){ int keyLen = ztrlen(childkey); int valueLen = ztrlen(childvalue); NODE* par = get(parentkey); NODE* cur = &node[cnt++]; cur->type = STRINGTYPE; cur->keyOne = keyLen >> 8; cur->keySec = keyLen & 0xff; cur->keyLen = keyLen; ztrDecodecpy(cur->keyStr, childkey, 0, cur->keyLen); cur->valueOne = valueLen >> 8; cur->valueSec = valueLen & 0xff; cur->valueLen = valueLen; ztrDecodecpy(cur->valueStr, childvalue, 0, cur->valueLen); addChild(par, cur, true);}void erase(char targetkey[MAX_KEY_LENGTH + 1]){ NODE* cur = get(targetkey); if(cur == 0) return; delChild(cur);}int generate(char targetkey[MAX_KEY_LENGTH + 1], char out[MAX_MESSAGE_LENGTH]){ target = 0; NODE* tar = get(targetkey); if(tar == 0) return target; revertSetTree(tar, out); out[target] = '\0'; return target;}
阅读全文
0 0
- DFS 1253 解题报告
- MCS_ACM DFS解题报告
- hdu1198解题报告(dfs)
- hdu1224解题报告(dfs)
- poj1154解题报告(dfs)
- poj 1011 Sticks解题报告【DFS+剪枝】
- Oil Deposits之DFS解题报告
- Fire net 之DFS解题报告
- poj2488 DFS马棋环游 解题报告
- HDU1241 Oil Deposits 解题报告--dfs
- HDU1016 Prime Ring Problem 解题报告--dfs
- HDU1181 变形课 解题报告--dfs
- HDU 1111 Secret Code DFS 解题报告
- poj1753解题报告(1):DFS算法
- UVALive 6957 Hyacinth (DFS) -- 解题报告
- HDU3768 Shopping 解题报告【SPFA预处理+dfs】
- pku 1691 painting a board dfs+回溯 解题报告
- poj 2488 A Knight's Journey 解题报告 DFS
- jfinal利用form表单同时上传图片和text
- JDBC:找回密码
- if exists用法
- 二周五次课
- jna笔记备份
- DFS 1253 解题报告
- GNU C语言 宏定义 #args ##args
- (继)pytorch中的pretrain模型网络结构修改
- 用UglifyJS2合并压缩混淆JS代码
- 那些年,React 踩过的坑
- android studio
- android_万能适配器
- Adobe Photoshop Lightroom CC 2017 Mac(LR CC)附激活工具 V1.0中文破解版
- Qt之HTTPS登录