数据结构期末复习:如何构建概率哈夫曼树

需积分: 30 11 下载量 48 浏览量 更新于2024-08-02 收藏 241KB DOC 举报
"《数据结构(本)》期末复习指导,重点讲解如何根据概率构建哈夫曼树,适用于成人教育本科计算机科学与技术专业。" 哈夫曼树,也称为最优二叉树或最小带权路径长度树,是一种特殊的二叉树,常用于数据压缩和编码。在构建哈夫曼树时,我们通常根据各字符出现的概率来构造树的结构,以达到最小化数据传输或存储的总成本。 构建哈夫曼树的过程通常包括以下几个步骤: 1. **创建初始节点**:为每个字符创建一个哈夫曼节点,该节点包含字符及其出现的概率。这些节点称为叶子节点。 2. **合并最小节点**:选取概率最小的两个节点,合并成一个新的节点,新节点的权值是两个子节点权值之和,即它们的概率之和。这个新节点成为内部节点,并没有对应的字符。 3. **重复合并**:将新节点放入节点集合中,再次选取概率最小的两个节点进行合并。重复此过程,直到只剩下一个节点,这个节点就是哈夫曼树的根节点。 4. **构建编码**:从根节点到每个叶子节点的路径可以形成一个独特的编码,左分支代表0,右分支代表1。每个字符的编码就是从根到对应叶子节点路径上的0和1序列。 哈夫曼编码的优势在于,频繁出现的字符会有较短的编码,而较少出现的字符则有较长的编码,这样可以平均减少编码的平均长度,从而提高数据传输或存储的效率。 在复习《数据结构(本)》时,考生应重点理解逻辑结构和物理结构的概念,以及它们之间的关系。逻辑结构关注数据元素间的抽象关系,如集合、线性结构、树形结构和图。物理结构则是数据在计算机内存或磁盘上的实际存储方式,它受到硬件限制并影响数据的访问效率。 在课程的考核中,可能会遇到如下类型的题目: - 单项选择题:测试对基本概念的理解,如哈夫曼树的定义、特性等。 - 填空题:可能要求填写哈夫曼树的构建步骤或者特定数据结构的特征。 - 程序填空题:可能需要完成一段关于哈夫曼树构建或编码的代码。 - 综合题:可能需要设计算法,根据给定的字符频率表构建哈夫曼树,并给出相应的编码。 考生应充分利用教材、作业和复习资料,尤其是综合练习题,因为历年试题可能来源于其中。对于考试大纲要求的前四章,特别是关于数据结构的基本概念和哈夫曼树的部分,需要深入理解和实践,以应对可能的考核要求。
2013-12-17 上传
//算法5.11 根据赫夫曼树求赫夫曼编码 #include using namespace std; typedef struct { int weight; int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char **HuffmanCode; void Select(HuffmanTree HT,int len,int &s1,int &s2) { int i,min1=0x3f3f3f3f,min2=0x3f3f3f3f;//先赋予最大值 for(i=1;i<=len;i++) { if(HT[i].weight<min1&&HT[i].parent==0) { min1=HT[i].weight; s1=i; } } int temp=HT[s1].weight;//将原值存放起来,然后先赋予最大值,防止s1被重复选择 HT[s1].weight=0x3f3f3f3f; for(i=1;i<=len;i++) { if(HT[i].weight<min2&&HT[i].parent==0) { min2=HT[i].weight; s2=i; } } HT[s1].weight=temp;//恢复原来的值 } //用算法5.10构造赫夫曼树 void CreatHuffmanTree(HuffmanTree &HT,int n) { //构造赫夫曼树HT int m,s1,s2,i; if(n<=1) return; m=2*n-1; HT=new HTNode[m+1]; //0号单元未用,所以需要动态分配m+1个单元,HT[m]表示根结点 for(i=1;i<=m;++i) //将1~m号单元中的双亲、左孩子,右孩子的下标都初始化为0 { HT[i].parent=0; HT[i].lchild=0; HT[i].rchild=0; } cout<<"请输入叶子结点的权值:\n"; for(i=1;i>HT[i].weight; /*――――――――――初始化工作结束,下面开始创建赫夫曼树――――――――――*/ for(i=n+1;i<=m;++i) { //通过n-1次的选择、删除、合并来创建赫夫曼树 Select(HT,i-1,s1,s2); //在HT[k](1≤k≤i-1)中选择两个其双亲域为0且权值最小的结点, // 并返回它们在HT中的序号s1和s2 HT[s1].parent=i; HT[s2].parent=i; //得到新结点i,从森林中删除s1,s2,将s1和s2的双亲域由0改为i HT[i].lchild=s1; HT[i].rchild=s2 ; //s1,s2分别作为i的左右孩子 HT[i].weight=HT[s1].weight+HT[s2].weight; //i 的权值为左右孩子权值之和 } //for } // CreatHuffmanTree void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n) { //从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中 int i,start,c,f; HC=new char*[n+1]; //分配n个字符编码的头指针矢量 char *cd=new char[n]; //分配临时存放编码的动态数组空间 cd[n-1]='\0'; //编码结束符 for(i=1;i<=n;++i) { //逐个字符求赫夫曼编码 start=n-1; //start开始时指向最后,即编码结束符位置 c=i; f=HT[i].parent; //f指向结点c的双亲结点 while(f!=0) { //从叶子结点开始向上回溯,直到根结点 --start; //回