赫夫曼树(最优二叉树)-数据结构(16)

一、例子引出问题

参考书上P144-P149 。在我们计算成绩排名的时候,我们大部分人的成绩都在中等的,还有一小部分在极优和极差中,服从正态分布。因此出现了让有权重的树,为了将经常用到的判断放在前面,因此建立了最优二叉树。

二、存储结构

//赫夫曼树
typedef struct {
	unsigned int weight;
	unsigned int parent, lchild, rchild;
}HTNode,*HuffmanTree;
typedef char** HuffmanCode;//赫夫曼编码保存

、操作

//赫夫曼树
typedef struct {
	unsigned int weight;
	unsigned int parent, lchild, rchild;
}HTNode,*HuffmanTree;
typedef char** HuffmanCode;//赫夫曼编码保存

void Select(HuffmanTree HT,int n,int &s1,int &s2){
	//在赫夫曼数组中的[1,n]数组中寻找parent = 0&&权重最小的两个结点,返回到s1和s2
	int min1 = 99998,indexMin1 = -1;
	int min2 = 99999,indexMin2 = -1;
	for (int i = 1; i <= n  ; i++)
	{
		if (!HT[i].parent == 0)
		{
			continue;
		}
		
		if (HT[i].weight < min2)
		{
			if (HT[i].weight < min1)
			{
				//新到的值比两个最小值都要小
				min2 = min1;
				indexMin2 = indexMin1;
				min1 = HT[i].weight;
				indexMin1 = i;
			}
			else
			{
				//介于最小值和倒数第二小值之间
				min2 = HT[i].weight;
				indexMin2 = i;
			}
		}
	}
	s1 = indexMin1;
	s2 = indexMin2;
}
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w ,int n){
	//w存放的是n个字符对应的权重
	//初始话赫夫曼树
	int m = 2 * n - 1;//生成的赫夫曼树的总结点个数
	HT = (HuffmanTree)malloc(sizeof(HTNode)* (m+1));//不使用0号单元
	//为前n个数组赋值
	for (int i = 1; i <= n; i++){
		HT[i] = { w[i-1],0,0,0 };
	}
	//为剩下的n-1个结点赋值
	for (int i = n+1; i <= m; i++)
	{
		HT[i] = { 0, 0, 0, 0 };
	}

	//建赫夫曼树
	for (int i = n+1; i <= m; i++)
	{
		//选择parent为0的的两个权重最小的F集合中的点
		int s1, s2;
		Select(HT, i - 1, s1, s2);
		HT[s1].parent = i;
		HT[s2].parent = i;
		HT[i].weight = HT[s1].weight + HT[s2].weight;
		HT[i].lchild = s1;
		HT[i].rchild = s2;
	}

	//生成赫夫曼编码 从叶子结点到根上面编写赫夫曼编码 左0右1 这里的编码可以用栈的形式打印保存出来
	for (int i = 1; i <= n; i++)
	{
		int parent_i = HT[i].parent;
		int cur = i;//当前循环到的结点
		do
		{
			if (HT[parent_i].lchild == cur)
			{
				//cur为parent_i的左孩子
				printf("0");
			}
			else
			{
				//cur为parent_i的右孩子
				printf("1");
			}
			//当父结点不为空的情况下
			//继续寻找父亲结点 直到根为止
			cur = parent_i;
			parent_i = HT[cur].parent;
		} while (parent_i != 0);

		printf("\n");
	}
}

void PrintHuffmanTree(HuffmanTree HT,int n){
	//打印赫夫曼树
	printf("权重\t父亲\t左孩子\t右孩子\n");
	for (int i = 1; i <= 2*n-1; i++)
	{
		printf("%d\t%d\t%d\t%d\n", HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
	}
}

四、执行

	//赫夫曼树
	int weight[4] = { 7, 5, 2, 4 };
	HuffmanTree tree;
	HuffmanCode Hc;
	HuffmanCoding(tree, Hc, weight, 4);
	PrintHuffmanTree(tree, 4);
输出:

0
01
011
111
权重    父亲    左孩子  右孩子
7       7       0       0
5       6       0       0
2       5       0       0
4       5       0       0
6       6       3       4
11      7       2       5
18      0       1       6
请按任意键继续. . .



你可能感兴趣的:(数据结构,数据结构,c)