C语言——创建哈夫曼树和求解哈夫曼编码

**哈夫曼树:**给定一组具有确定权值的叶子结点,带权路径长度最小的二叉树。

哈夫曼树(n个结点构造哈夫曼树,总共需要2n-1大小的数组存储)
huffTree数组[权值weight、双亲parent、左孩子lchild、右孩子rchild]
1.数组HuffNode初始化,所有元素结点的双亲、左右孩子都置为-1;
2.数组HuffNode的前n个元素的权值置给定值w[n];
3.进行n-1次合并.在二叉树集合中选取两个权值最小的根结点,其下标分别为x1,x2; 将二叉树x1,x2合并为一棵新的二叉树k
(1)赋新权;
(2)x1、x2的双亲结点为k;
(3)更新该结点的左孩子为x1,右孩子为x2;
(4)将i1和i2删去;

*键盘输入n,定义动态数组的方法:int a=new int[n]
代码如下:

#include
#include 
using namespace std;
#define MAXVALUE 2147483647  //最大权值

/*哈夫曼树的数据结构*/
typedef struct{
	int weight; //权值
	int parent; //父节点下标
	int lchild; //左孩子节点的下标
	int rchild; //右孩子节点的下标
} HTNodeType;

//函数声明 
void HuffmanTree(HTNodeType HuffNode[],int n);                     //1 创建哈夫曼树
void HuffmanCode(HTNodeType HuffNode[],char *huffCode[], int n);                        //2 求哈夫曼编码

int main(){	
	int n;//结点个数
	cout<<"输入结点个数:";
	cin>>n;
	HTNodeType *HuffNode=new HTNodeType[2*n-1];//哈夫曼树结点数组
	int *weight=new int[n];//权值数组
	char **huffCode=new char*[n];//指针数组,指向n个哈夫曼编码字符串
	HuffmanTree(HuffNode,n);
	HuffmanCode(HuffNode,huffCode,n);
	cout<<"哈夫曼编码:"<<endl; 
	for(int i=0;i<=n;i++){
		cout<<huffCode[i]<<endl;
	}
	return 0;
}

//创建哈夫曼树
void HuffmanTree(HTNodeType HuffNode[],int n)
{
	int i = 0, j = 0;
	for (i = 0; i < 2 * n - 1; i++){//初始化所有结点的项目为-1 
		HuffNode[i].weight = 0;
		HuffNode[i].parent = -1;
		HuffNode[i].lchild = -1;
		HuffNode[i].rchild = -1;
	}
	cout<<"输入"<<n<<"个权值:";
	for(i=0;i<n;i++){//输入权值 
		cin>>HuffNode[i].weight;
	}
	for (i = 0; i < n - 1; i++){  //找到parent为-1的最小和次小的结点 
		int m1 = MAXVALUE, m2 = MAXVALUE, x1 = -1, x2 = -1;
		for (j = 0; j < n + i; j++){
			if (HuffNode[j].weight < m1 && HuffNode[j].parent == -1){
				m2 = m1;
				x2 = x1;
				m1 = HuffNode[j].weight;
				x1 = j;
			}
			else if (HuffNode[j].weight < m2 && HuffNode[j].parent == -1){
				m2 = HuffNode[j].weight;
				x2 = j;
			}
		}
		//选中x1,x2合并,更新结点 
		HuffNode[n + i].weight = m1 + m2;//新的结点权值为x1和x2的权值之和
		HuffNode[x1].parent = n + i;//x1的双亲结点为新结点 
		HuffNode[x2].parent = n + i;//x2的双亲结点为新结点 
		HuffNode[n + i].lchild = x1;//左孩子为x1 
		HuffNode[n + i].rchild = x2;//右孩子为x1 
	}
}

//从叶子到根逆向求每个字符的哈夫曼编码
void HuffmanCode(HTNodeType HuffNode[], char *huffCode[],int n)
{
	char *temp=new char[n];//定义工作空间,存储临时产生的编码串
	temp[n-1] ='\0';
	int start,pos;
	for (int i = 0; i < n; i++){//遍历哈夫曼树数组,生成哈夫曼编码 
		start=n-1;
		pos=i;//pos记录正在处理的当前位置,也就是孩子结点
		int f=HuffNode[pos].parent;
		while(f!=-1){
			if(HuffNode[f].lchild==pos){ 
				temp[--start]='0';  //是左孩子编码0
			}
			else{
				temp[--start]='1';  //是右孩子编码1
			}
			pos=f;//更新pos结点,移动到它的父亲 
			f=HuffNode[pos].parent;//更新父结点 
		}
		huffCode[i]=new char[n-start];//建立哈夫曼编码实际需要的内存空间
		strcpy(huffCode[i],&temp[start]);//将哈夫曼编码存储到huffCode中 
	}
	delete temp;//释放存储空间 
}

运行结果如下:
C语言——创建哈夫曼树和求解哈夫曼编码_第1张图片
这个代码经过试验,可以完整运行,至于算法的详细讲解,可以去B站看“懒猫老师”的视频哦,视频中的图解可帮助快速理解算法原理。
【懒猫老师-数据结构-(34)哈夫曼树(Huffman Tree,霍夫曼树,赫夫曼树)-哔哩哔哩】
【懒猫老师-数据结构-(35)哈夫曼编码1(Huffman coding,霍夫曼编码,赫夫曼编码)-哔哩哔哩】

你可能感兴趣的:(数据结构,c/c++基础,c语言,算法,数据结构)