ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

最小堆建立哈夫曼树及各种操作

2020-04-18 09:56:08  阅读:493  来源: 互联网

标签:结点 Weight 哈夫曼 最小 child HuffmanTree MinHeap 树及 Data


数据结构与算法实验报告               姓名:孙瑞霜 

 

一、实验目的

1、复习Huffman树及其创建等基本操作; 

2、掌握最小堆的定义及其建立、插入删除等操作的实现。

3、掌握Huffman编码的方法。

二、实验要求

1. 认真阅读和掌握教材上和本实验相关的内容和算法。

2. 上机将相关算法实现。

3. 实现上面实验目的要求的功能,并能进行简单的验证。

、实验内容

1、 必做内容:Huffman树的创建

按照课本上最小堆(代码4.26,改成最小堆)及建立Huffman树的算法(代码4.27),编程实现Huffman树的建立。要求能够进行简单的输入输出验证,输出建好后的Huffman树的形态,比如输出其先序和中序遍历序列。 

typedef struct TreeNode *HuffmanTree;

struct TreeNode{

int Weight;

HuffmanTree Left;

HuffmanTree Right;

};

2、 选做内容:实现Huffman编码,并进行简单输入输出验证,比如输入一些字符及其权值,输出每种字符的Huffman编码。可以查阅资料,结合程序进行分析,其存储结构及其操作上和建立Huffman树有何异同。 

三、算法描述

        首先我们应明确什么是哈夫曼树,假设有n个权值,构造有n个叶子结点的二叉树,每个叶子结点的权值是n个权值之一,其中带权路径长度最小的一棵就是哈夫曼树。在哈夫曼树的构造过程中,选取两棵根结点权值最小的树作为左、右子树,每次将权值最小的两棵树进行合并,构造成一棵新的二叉树,置新二叉树根结点的权值等于左、右子树根结点的权值之和。从集合中删除作为左、右子树的两棵二叉树,并将新构造的二叉树加入到集合中;重复操作,直到集合中只含一棵二叉树为止,这棵二叉树便是要建立的哈夫曼树。

四、详细设计

 

五、程序代码

#include<stdio.h>

#include<stdlib.h>

#define MinData -1

typedef struct TreeNode *HuffmanTree;//哈夫曼树类型

struct TreeNode{

int Weight;  //结点权值

HuffmanTree Left;//指向左子树

HuffmanTree Right;//指向右子树

}HuffmanNode;//定义新的结构变量

  

typedef struct HeapStruct *MinHeap;

struct HeapStruct{

HuffmanTree *Data;  //存储堆元素的数组  存储时从下标1开始

int Size;  //堆的当前元素的个数

int Capacity;  //堆的最大容量

};

 

HuffmanTree NewHuffmanNode();

//构造新的哈夫曼树

MinHeap CreateMinHeap(int MaxSize);

//创建容量为MaxSize的最小堆

bool Insert(MinHeap H,HuffmanTree item);

//将元素item插入到最小堆H中

HuffmanTree DeleteMin(MinHeap H);

//从最小堆H中取出权值为最小的元素,并删除一个结点

MinHeap BuildMinHeap(MinHeap H);

//将H->data[]按权值调整为最小堆

HuffmanTree Huffman(MinHeap H);

//最小堆构造哈夫曼树

void PreOrderTraversal(HuffmanTree BST);

//先序遍历哈夫曼树

 

int main()

{

int i,N;

MinHeap h;

HuffmanTree T,BT = NULL;

 

printf("输入叶子结点的个数:\n");

scanf("%d",&N);

h = CreateMinHeap(2*N);  //创建最小堆

printf("输入%d个叶子结点对应的权值:\n",N);

for(i=1; i<=N; i++){/*最小堆元素赋值*/

T = NewHuffmanNode();

scanf("%d",&(T->Weight));

h->Data[++(h->Size)] = T;

}

BT = Huffman(h);  //构造哈夫曼树

printf("先序遍历此哈夫曼树:\n");

PreOrderTraversal(BT);  //先序遍历哈夫曼树

 

return 0;

 }

  /*哈夫曼树构造算法*/

 HuffmanTree Huffman(MinHeap H)

 {/*假设H->Size个权值已经存在H->data[]->Weight里*/

  int i,n;

HuffmanTree T;

 

BuildMinHeap( H );  //将H->data[]按权值调整为最小堆

/*此处必须将H->Size的值交给num,因为后面做DeleteMin()和 Insert()函数会改变H->Size的值*/

n = H->Size;     

for(i=1; i<n; i++){  //做 H->Size-1次合并

T = NewHuffmanNode();  //建立一个新的根结点

T->Left = DeleteMin(H);  //从最小堆中删除一个节点,作为新T的左子结点

T->Right = DeleteMin(H);  //从最小堆中删除一个节点,作为新T的右子结点

T->Weight = T->Left->Weight+T->Right->Weight;  //计算新权值

Insert(H,T);  //将新T插入到最小堆

}

T = DeleteMin(H);

 

return T;

  }

  

//先序遍历哈夫曼树

void PreOrderTraversal(HuffmanTree BST)

{

if( BST ){

printf("%d ",BST->Weight);     //先访问根节点

PreOrderTraversal(BST->Left);  //再访问左子树

PreOrderTraversal(BST->Right); //最后访问右子树

}

}

 

HuffmanTree NewHuffmanNode()

{

HuffmanTree BST = (HuffmanTree)malloc(sizeof(HuffmanNode));

BST->Weight = 0;

BST->Left = BST->Right = NULL;

 

return BST;

 }  

  

MinHeap CreateMinHeap(int MaxSize)

{  /*创建容量为MaxSize的最小堆*/

MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct));

H->Data = (HuffmanTree *)malloc((MaxSize+1) * sizeof(HuffmanTree));

H->Size = 0;

H->Capacity = MaxSize;

HuffmanTree T = NewHuffmanNode();

T->Weight = MinData;  /*定义哨兵-为小于堆中所有可能元素权值的值,便于以后更快操作*/

H->Data[0] = T;

 

return H;

}

 //插入新增节点

bool  IsFull(MinHeap H)

{

return (H->Size == H->Capacity);

}

 

bool IsEmpty(MinHeap H)

{

return (H->Size == 0);

}

 

 

bool Insert(MinHeap H,HuffmanTree item)

{        //将元素item插入到最小堆H中

int i;

if( IsFull(H) ){

printf("最小堆已满\n");

return false;

}

i = ++H->Size;  //i指向插入后堆中的最后一个元素的位置

for(; H->Data[i/2]->Weight > item->Weight; i/=2)  //无哨兵,则增加判决条件 i>1

    H->Data[i] = H->Data[i/2];  //向下过滤结点

H->Data[i] = item;   //将item插入

 

return true;

 }

 

HuffmanTree DeleteMin(MinHeap H)

{/*从最小堆H中取出权值为最小的元素,并删除一个结点*/

int parent,child;

HuffmanTree MinItem,temp = NULL;

if( IsEmpty(H) ){

printf("最小堆为空\n");

return NULL;

}

MinItem = H->Data[1];  //取出根结点-最小的元素-记录下来

//用最小堆中的最后一个元素从根结点开始向上过滤下层结点

temp = H->Data[H->Size--];  //最小堆中最后一个元素,暂时将其视为放在了根结点

for(parent=1; parent*2<=H->Size; parent=child){

child = parent*2;

if((child != H->Size) && (H->Data[child]->Weight > H->Data[child+1]->Weight)){

/*有右儿子,并且左儿子权值大于右儿子*/

child++; //child指向左右儿子中较小者

}

if(temp->Weight > H->Data[child]->Weight){

H->Data[parent] = H->Data[child];  //向上过滤结点-temp存放位置下移到child位置

}else{

break;  //找到了合适的位置

}

}

H->Data[parent] = temp;  //temp存放到此处

 

return MinItem;

}

 

MinHeap BuildMinHeap(MinHeap H)

{

int i,parent,child;

HuffmanTree temp;

for(i=H->Size/2;i>0;i--){  //从最后一个父结点开始,直到根结点

temp = H->Data[i];

for(parent=i; parent*2<=H->Size; parent=child){

    /*向下过滤*/

child = parent*2;

    if((child != H->Size) && (H->Data[child]->Weight > H->Data[child+1]->Weight)){/*有右儿子,并且左儿子权值大于右儿子*/

    child++; //child指向左右儿子中较小者

    }

    if(temp->Weight > H->Data[child]->Weight){

    H->Data[parent] = H->Data[child];  //向上过滤结点-temp存放位置下移到child位置

    }else{

    break;  //找到了合适的位置

    }

    }/*结束内部for循环对以H->data[i]为根的子树的调整*/

 

H->Data[parent] = temp;  //temp存放到此处  

}

return H;

}

 

六、测试和结果

测试用例:课本154页哈夫曼树的生成过程

七、用户手册

打开devC++,新建一个源程序,拷贝5部分的代码进去,点击运行,在出现的界面中按照提示输入数据一步步按下回车键即可运行该程序,最后测试完毕,关闭界面

标签:结点,Weight,哈夫曼,最小,child,HuffmanTree,MinHeap,树及,Data
来源: https://www.cnblogs.com/srs7665/p/12701467.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有