标签:键树 键树的双链表表示法 键树的双链表表示法c语言描述
杂谈; 打败自己的 往往不是敌人,而是自己。坚持不易,且行且珍惜。
键树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高
键树的根节点不包含字符,除根节点外的非叶子节点都只包含一个字符,叶子节点存储具体信息。; 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 每个节点的所有子节点包含的字符都不相同。并且 兄弟节点 按 按 字符大小 排序。
例如:
它的 键树形式如下:
键树的应用:(摘自百度)
键树 有 两种 表示 方法:1. 双链表 表示法 ,就是 树的 孩子链表 表示法 2.多重链表表示法(Trie树)
下面给出 键树的 双链表 表示法的 插入,删除,查找 等功能 代码:
完整源代码网盘地址:http://yun.baidu.com/share/link?shareid=582619924&uk=1208029266
// DSTree.cpp : 定义控制台应用程序的入口点。 //键树的双链树表示法 #include "stdafx.h" #include <cstdlib> #include <cstring> #include "queue.h" #include "stack.h" #define MAX_KEY_LEN 16 #define LEAF_END_CHAR '$'//叶子节点结束符 struct KeyType{ char key[MAX_KEY_LEN]; int len; }; void initKey(KeyType * kt,char * k){ int len = strlen(k); strncpy(kt->key,k,len+1); kt->len = len; } enum E_Kind{ E_Kind_Leaf, E_Kind_Branch, }; typedef struct DLNode{ char data; DLNode * nextSibling;//下一个兄弟节点 E_Kind kind;; union { char * record;//叶子节点的信息 DLNode * firstChild;//第一个孩子节点(分支节点) }; }*DLTree; DLNode * makeNode(E_Kind kind){ DLNode * node = (DLNode *)malloc(sizeof(DLNode)); node->kind = kind; node->nextSibling = NULL; if (node->kind == E_Kind_Branch){ node->firstChild = NULL; } else{ node->record = (char *)malloc(sizeof(char)*MAX_KEY_LEN); node->data = LEAF_END_CHAR; } return node; } void initTree(DLTree * tree){ *tree = NULL; } void destoryTree(DLTree * tree){ DLTree p = *tree; if (p != NULL){ if (p->kind == E_Kind_Leaf){ free(p->record); } else{ destoryTree(&p->firstChild); } destoryTree(&p->nextSibling); free(p); *tree = NULL; } } DLTree search(DLTree t,char * k){ if (t != NULL) { KeyType kt; initKey(&kt,k); int times = 0; t = t->firstChild; while (t && times < kt.len){ while (t && t->data < kt.key[times]) t = t->nextSibling; if (t && t->data == kt.key[times]){ t = t->firstChild; times++; } else{ return NULL; } } if (times == kt.len && t->kind == E_Kind_Leaf){ return t; } } return NULL; } //搜索结果.为插入 关键字 服务 //是第一个孩子节点:tree:返回 父亲节点 ,不是 返回 兄弟节点. struct Result{ bool isFind;//是不是找到了 bool isFirst;//是不是第一个孩子节点 DLTree tree;//插入位置 int index;//需要插入的节点 的位置. }; Result searchForInsert(DLTree tree,KeyType key){ int times = 0; Result result; result.isFirst = false; result.isFind = false; while (tree && times < key.len){ DLTree fatherNode = tree; result.index = times; tree = tree->firstChild; while (tree){ if (tree->data > key.key[times]){ if (fatherNode->firstChild == tree){ result.isFirst = true; result.tree = fatherNode; } return result; } else if(tree->data == key.key[times]){ result.tree = tree; times ++; break; } else{// $ 比 a ~ z 小 result.tree = tree; tree = tree->nextSibling; } } } if ( times == key.len){//全部都相等 if (tree && tree->firstChild && tree->firstChild->kind == E_Kind_Leaf){ result.isFind = true; result.tree = tree->firstChild; } else{ result.isFirst = true; result.index = times; } } return result; } void insert(DLTree t,KeyType kt,int index){ for (int i = index; i < kt.len; i++){ DLNode * node = makeNode(E_Kind_Branch); node->data = kt.key[i]; t->firstChild = node; t = node; } //最后插入叶子节点 DLNode * leaf = makeNode(E_Kind_Leaf); strncpy(leaf->record,kt.key,kt.len+1); t->firstChild = leaf; } void insertTree(DLTree * tree,char * key){ KeyType kt; initKey(&kt,key); if (*tree == NULL){//空树,需要设置一个根节点 *tree = makeNode(E_Kind_Branch); insert(*tree,kt,0); return; } Result result = searchForInsert(*tree,kt); if (result.isFind == false){//没找到,再插入. if (result.isFirst){//插入在头部 DLTree fatherNode = result.tree; DLTree oldFirst = fatherNode->firstChild; insert(fatherNode,kt,result.index); fatherNode->firstChild->nextSibling = oldFirst; } else{ DLTree leftBrother = result.tree; DLNode * node = makeNode(E_Kind_Branch); node->data = kt.key[result.index]; node->nextSibling = leftBrother->nextSibling; leftBrother->nextSibling = node; insert(node,kt,result.index+1); } } } void deleteTree(DLTree * t,char * k){ if (*t != NULL) { KeyType kt; initKey(&kt,k); DLTree p = (*t)->firstChild; int times = 0; linkStack stack; stackInit(&stack); stackPush(&stack,*t); while (p && times < kt.len){ while (p && p->data < kt.key[times]) p = p->nextSibling; if (p && p->data == kt.key[times]){ stackPush(&stack,p); p = p->firstChild; times++; } else{ return;//没找到 } } if (p && p->kind == E_Kind_Leaf){ DLTree f = NULL; while (!stackEmpty(stack)){ stackPop(&stack,&f); if (f->firstChild == p && p->nextSibling == NULL){//父亲只有 一个孩子 free(p); p = f; if (*t == f){//所有关键字都被删除了,空树.. free(*t); *t = NULL; return; } } else{ break; } } if (f->firstChild == p){ f->firstChild = p->nextSibling; } else{ DLTree pre = f->firstChild; while (pre != NULL && pre->nextSibling != p) pre = pre->nextSibling; pre->nextSibling = p->nextSibling; } free(p); } stackDestory(&stack); } } //层序遍历 void levelTraverse(DLTree tree){ if (tree != NULL){ if (tree->firstChild != NULL){ printf("----------------层序遍历----------------\n"); LinkQueue queue; queueInit(&queue); enqueue(&queue,tree->firstChild); int count = 1; int level = 1; int nextCount = 0; while (!queueEmpty(queue)){ printf("%d 层数据:",level); for (int i = 0; i < count; i++){ DLTree t; dequeue(&queue,&t); while (t){ printf("%c ",t->data); if (t->kind == E_Kind_Branch && t->firstChild != NULL){ enqueue(&queue,t->firstChild); nextCount++; } t = t->nextSibling; } } printf("\n"); count = nextCount; nextCount = 0; level++; } queueDestory(&queue); printf("\n"); } } } static char testArray[][MAX_KEY_LEN] = {//18 个 "cao","cai","chang","chao","cha","chen",//6 "wen","wang","wu",//3 "zhao",//1 "li","lan","long","liu",//4 "yun","yang",//2 "zha","l", }; int _tmain(int argc, _TCHAR* argv[]) { DLTree root; initTree(&root); for (int i = 0; i < 16; i++){ insertTree(&root,testArray[i]); } levelTraverse(root); for (int i = 0; i < 18; i++){ char * s = testArray[i]; DLTree t = search(root,s); if (t){ printf("查找 %s后,记录为:%s\n",s,t->record); } else{ printf("查找 %s,没找到\n",s); } } for (int i = 0; i < 18; i++){ char * s = testArray[i]; deleteTree(&root,s); printf("-------------删除%s后--------------\n",s); levelTraverse(root); } destoryTree(&root); return 0; }
标签:键树 键树的双链表表示法 键树的双链表表示法c语言描述
原文地址:http://blog.csdn.net/fuming0210sc/article/details/45343485