哈夫曼编码C代码实现--数据结构

哈夫曼编码的实现过程

请读者结合上一篇哈夫曼树的博客,便于理解该篇文章。简单来说,哈夫曼编码是将构造的哈夫曼树按照左孩子都标记为0 右孩子都标记为1的原则。通过此种标记的手段标记的哈弗曼树能够将编码的长度压缩到最小。本程序中默认将权值较小置为左孩子。
代码实现如下 可能不是主流思路,只是看了原理自己手写的。望指正!
文末附有测试过程
#include 
#include 
#define MAXLEAVES 5  //初始叶子结点数
#define MAXNODE 2*MAXLEAVES - 1 //哈弗曼树的结点总数

/** 规定权值小的为左孩子,权值大的为右孩子*/
typedef struct
{
	int weight; //结点权值
	int parent, left, right;//父节点下标  左右孩子下标
	int flag;//记录该节点是否已经判断过 没有判断过标记为0 判断过标记为1
	int HuffmanCode;
}HuffNode;

void Init_HuffmanTree(HuffNode HuffArray[], int n);//初始化所有节点
void Create_HuffmanTree(HuffNode HuffArray[]);//根据下标对应权值相加 得到新的权值 并且找到双亲节点
void Show_HuffmanTree(HuffNode HuffArray[], int n);//输出哈夫曼数组
int Select_Sort(HuffNode HuffArray[], int num);//选出权值最小的两个下标
void Create_HuffmanTreeCode(HuffNode HuffArray[]); //哈弗曼编码值赋值
void Show_HuffmanTreeCode(HuffNode HuffArray[]);//输出哈弗曼编码
void Huffman_Sercet(HuffNode HuffArray[]);//任意给定权值  输出该权值的哈夫曼编码

int main()
{
	//分配2n - 1 个结点内存数组
	HuffNode HuffArray[MAXNODE];
	printf("初始化完成的哈夫曼数组:\n");
	Init_HuffmanTree(HuffArray, MAXNODE);
	Show_HuffmanTree(HuffArray, MAXLEAVES);
	printf("构造哈夫曼数组,并输出:\n");
	Create_HuffmanTree(HuffArray);
	Show_HuffmanTree(HuffArray, MAXNODE);
	printf("(规定左孩子为0 右孩子为1)哈弗曼编码赋值:");
	Create_HuffmanTreeCode(HuffArray);
	printf("输出哈夫曼编码:\n");
	Huffman_Sercet(HuffArray);

	return 0;
}

/** 初始化哈夫曼数组*/
void Init_HuffmanTree(HuffNode HuffArray[], int n)
{
	int i = 0;
	srand(time(NULL));
	for (i; i < MAXNODE; i++)//初始化
	{
		HuffArray[i].parent = -1;
		HuffArray[i].left = -1;
		HuffArray[i].right = -1;
		HuffArray[i].flag = 0;
	}
	/*//为了方便直接给定权值
	HuffArray[0].weight = 28;
	HuffArray[1].weight = 10;
	HuffArray[2].weight = 20;
	HuffArray[3].weight = 7;
	HuffArray[4].weight = 35;*/

	//写完程序之后为了验证普遍性   采用随机生成的方式进行了测试
	for (i = 0;i < MAXLEAVES;i++)
	{
		HuffArray[i].weight = rand() % 100;
	}

	//经过测试没有问题
}

/** 创建哈夫曼树*/
void Create_HuffmanTree(HuffNode HuffArray[])
{
	int i = MAXLEAVES;
	int minindex1, minindex2;
	for (i; i < MAXNODE; i++)//确定需要几次大循环
	{
		minindex1 = Select_Sort(HuffArray, i);
		minindex2 = Select_Sort(HuffArray, i);
		HuffArray[i].weight = HuffArray[minindex1].weight + HuffArray[minindex2].weight;
		HuffArray[i].left = minindex1;
		HuffArray[i].right = minindex2;
		HuffArray[minindex1].parent = HuffArray[minindex2].parent = i;
	}
}

void Show_HuffmanTree(HuffNode HuffArray[], int n)
{
	int i = 0;
	printf("下标  权值  双亲下标    左孩子     右孩子		flag\n");
	for (i;i < n;i++)
	{
		printf("%d     %d      %d          %d         %d			%d\n", i, HuffArray[i].weight,
			HuffArray[i].parent,
			HuffArray[i].left,
			HuffArray[i].right,
			HuffArray[i].flag);
	}
}

/** 输出哈弗曼编码*/
void Show_HuffmanTreeCode(HuffNode HuffArray[])
{
	int i = 0;
	printf("\n输出哈弗曼编码:\n");
	printf("权值      哈弗曼编码\n");
	for (i;i < MAXNODE;i++)
	{
		printf("%d             %d\n", HuffArray[i].weight, HuffArray[i].HuffmanCode);
	}
}

/** */
int Select_Sort(HuffNode HuffArray[], int num)
{
	int m;
	int minIndex;
	for (m = 0;m < num;m++)
	{
		if (HuffArray[m].flag != 1)  // 找的应该是第一个flag不为1的作为最小值
													// 因为一旦第一个在某次循环中被选中  下一次也就意味着不可再被认为是minindex
		{
			minIndex = m;
			break;
		}
	}
	for (m = 0;m < num;m++)
	{
		if (HuffArray[m].flag != 1)
		{
			if (HuffArray[minIndex].weight > HuffArray[m].weight)
			{
				minIndex = m;
			}
		}
	}
	HuffArray[minIndex].flag = 1;
	return minIndex;
}

/** 构造哈弗曼编码值*/
void Create_HuffmanTreeCode(HuffNode HuffArray[])
{
	//从哈弗曼树数组来看 left中对应的下表其实全是左孩子  所以直接标志为0
	//其次总根节点  也标记为0
	//所以初始化将所有的标记为0
	int i = 0, j;
	for (i;i < MAXNODE;i++)
	{
		HuffArray[i].HuffmanCode = 0;
		for (j = MAXLEAVES;j < MAXNODE;j++)
		{
			if (HuffArray[j].right == i)
			{
				HuffArray[i].HuffmanCode = 1;
			}
		}
	}

	Show_HuffmanTreeCode(HuffArray);
}

/** 任意选择权值 输出哈弗曼编码*/
void Huffman_Sercet(HuffNode HuffArray[])
{
	int w = 0;
	int i = 0,j = 0;
	int index = 0;
	int huffman[80];//哈夫曼编码的输出是反序的 用数组存一下 再倒序输出
	printf("请输入选择的权值:\n");
	scanf("%d", &w);
	//找到权值对应的下标
	for (i;i < MAXLEAVES;i++)
	{
		if (HuffArray[i].weight == w)
		{
			index = i;
			break;
		}
	}
	printf("Huffman编码:");
	while (HuffArray[index].parent != -1)
	{
		huffman[j++] = HuffArray[index].HuffmanCode;
		index = HuffArray[index].parent;
	}
	huffman[j] = HuffArray[index].HuffmanCode;
	while (j >= 0)
	{
		printf("%d",huffman[j]);
		j--;
	}
}

哈夫曼编码C代码实现--数据结构_第1张图片
哈夫曼编码C代码实现--数据结构_第2张图片

因为是随机生成的,每次的哈弗曼树都不一样 所以就给大家测试一次就好了 大家可以多测几次。

你可能感兴趣的:(数据结构-C,随笔)