⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bo8-6.cpp

📁 数据结构相关代码
💻 CPP
字号:
 // bo8-6.cpp Trie树的基本操作,包括算法9.16
 void InitDSTable(TrieTree &T)
 { // 操作结果:构造一个空的Trie树T
   T=NULL;
 }

 void DestroyDSTable(TrieTree &T)
 { // 初始条件:Trie树T存在。操作结果:销毁T
   int i,j=0; // 已处理的结点数
   if(T) // 非空树
   { for(i=0;j<T->bh.num&&i<LENGTH;i++)
       if(T->kind==BRANCH&&T->bh.ptr[i]) // T是分支结点且第i个结点不空
       { if(T->bh.ptr[i]->kind==BRANCH) // 第i个结点是分支结点
           DestroyDSTable(T->bh.ptr[i]); // 递归销毁第i个结点子树
         else // 第i个结点是叶子结点
           free(T->bh.ptr[i]); // 释放叶子结点
         j++; // 已处理的结点数+1
       }
     free(T); // 释放根结点
     T=NULL; // 空指针赋0
   }
 }

 Record* SearchTrie(TrieTree T,KeyType K)
 { // 在Trie树T中查找关键字等于K的记录。修改算法9.16
   TrieTree p=T;
   int i;
   for(i=0;p&&p->kind==BRANCH&&i<=K.num;p=p->bh.ptr[ord(K.ch[i++])]);
   // 对K的每个字符逐个查找,*p为分支结点,ord()求字符在字母表中序号
   if(p&&p->kind==LEAF&&EQ(p->lf.K.ch,K.ch)) // 查找成功
     return p->lf.infoptr; // 返回关键字等于K的记录的地址
   else // 查找不成功
     return NULL; // 返回空
 }

 void InsertTrie(TrieTree &T,Record* r)
 { // 初始条件:Trie树T存在,r为待插入的数据元素的指针
   // 操作结果:若T中不存在其关键字等于r->key.ch的数据元素,则按关键字顺序插r到T中
   TrieTree p=T,q,ap;
   int i,j,k,n;
   if(!T) // 空树
   { T=(TrieTree)malloc(sizeof(TrieNode)); // 动态生成Trie树结点
     T->kind=BRANCH; // 结点类型为分支
     for(i=0;i<LENGTH;i++) // 指针数组赋初值NULL
       T->bh.ptr[i]=NULL;
     T->bh.num=1; // 分支结点的孩子数赋值1
     p=T->bh.ptr[ord(r->key.ch[0])]=(TrieTree)malloc(sizeof(TrieNode));
     // 在关键字首字符对应的指针处动态生成叶子结点
     p->kind=LEAF; // 结点类型为叶子
     p->lf.K=r->key; // 结点关键字为数据元素的关键字
     p->lf.infoptr=r; // 结点指针指向数据元素的地址
   }
   else // 非空树
   { for(i=0;p&&p->kind==BRANCH&&i<=r->key.num;++i) // 在分支结点中查找插入位置
     { q=p; // q指向p所指结点
       p=p->bh.ptr[ord(r->key.ch[i])]; // p指向第i个关键字所在的结点
     }
     if(!p) // 分支空
     { p=q->bh.ptr[ord(r->key.ch[i-1])]=(TrieTree)malloc(sizeof(TrieNode));
       // 动态生成Trie树结点
       q->bh.num++; // 结点的双亲的孩子数+1
       p->kind=LEAF; // 结点类型为叶子
       p->lf.K=r->key; // 结点关键字为数据元素的关键字
       p->lf.infoptr=r; // 结点指针指向数据元素的地址
     }
     else // p->kind!=BRANCH
     { if(EQ(p->lf.K.ch,r->key.ch)) // T中存在该关键字
         return; // 不插入返回
       else // 有关键字部分相同的叶子
       { for(n=0;r->key.ch[n]==p->lf.K.ch[n];n++); // n为相同的关键字符数
         n=n-i;
         for(k=0;k<=n;k++)
         { ap=q=q->bh.ptr[ord(r->key.ch[i++-1])]=(TrieTree)malloc(sizeof
           (TrieNode)); // 动态生成Trie树结点
           ap->kind=BRANCH; // 结点类型为分支
           for(j=0;j<LENGTH;j++)
             ap->bh.ptr[j]=NULL; // 指针数组赋初值NULL
           ap->bh.num=1; // 分支结点的孩子数赋值1
         }
         ap->bh.num++; // 分支结点的孩子数加1
         ap->bh.ptr[ord(p->lf.K.ch[i-1])]=p; // 将*p接入Trie树中
         q=ap->bh.ptr[ord(r->key.ch[i-1])]=(TrieTree)malloc(sizeof(TrieNode));
         // 动态生成Trie树结点
         q->kind=LEAF; // 结点类型为叶子
         q->lf.K=r->key; // 结点关键字为数据元素的关键字
         q->lf.infoptr=r; // 结点指针指向数据元素的地址
       }
     }
   }
 }

 void TraverseDSTable(TrieTree T,void(*Visit)(Record*))
 { // 初始条件:Trie树T存在,Visit是对记录指针操作的应用函数
   // 操作结果:按关键字的顺序输出关键字及其对应的记录
   TrieTree p;
   int i,n=9; // 输出n个元素后换行
   if(T) // 树T不空
     for(i=0;i<LENGTH;i++) // 对T的所有的孩子
     { p=T->bh.ptr[i]; // p指向T的第i个孩子
       if(p&&p->kind==LEAF) // T的第i个孩子是叶子
       { Visit(p->lf.infoptr); // 访问该结点所指的记录
         count++;
         if(count%n==0)
           printf("\n"); // 输出n个元素后换行
       }
       else if(p&&p->kind==BRANCH) // T的第i个孩子是分支
         TraverseDSTable(p,Visit); // 对T的第i个孩子递归调用TraverseDSTable()
     }
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -