哈夫曼编码C语言实现



#include "stdafx.h"
#include
#include
#define debug 0
typedef struct HuffNode {
int parent;
int lchild;
int rchild;
int wet;
}*HuffTree, HNode;//树的节点
/**/
int Weight_min(HuffTree HT, int k);
int SelectTwoMinNode(HuffTree HT, int k, int &min1, int &min2);
HuffTree CreatHuffmanTree(HuffTree HT, int *wet, int amount);
void Test(HuffTree HT, int amount);
void ReverseRight(HuffTree HT, HuffTree Head);
void HuffManEncode(HuffTree HT, int amount);


int main()
{
printf("请输入创建的节点个数:");/*创建的节点在哈夫曼编码中都是叶子节点*/
int amount;
scanf_s("%d", &amount);
int *wet = (int*)malloc(amount * sizeof(int));
//对权赋值;可以自己手动输入特定权值
for (int i = 0; i < amount; i++) {
*(wet + i) = i+10;
}
HuffTree HT = NULL;//对于指针一定要赋初值
HT = CreatHuffmanTree(HT,wet,amount);
Test(HT, amount);


HuffTree Head = &HT[2 * amount - 2];
ReverseRight(HT, Head);
printf("线序遍历之后的:\n");
Test(HT, amount);
HuffManEncode(HT, amount);
printf("here");
system("Pause");
    return 0;
}
//在前k个节点找到权值最小的节点
int Weight_min(HuffTree HT,int k) {
int min,min_wei;
int i = 0;
while (HT[i].parent != -1) i++;//跳过树中的节点;
min_wei = HT[i].wet;//初始值一定不能为树中的节点;
min = i;
//若直接把HT[0].wet赋值给min_wei,恰好HT[0].wet为最小值,后面循环出问题;
while (HT[i].wet < min_wei&&HT[i].parent == -1&&i min_wei = HT[i].wet;
min = i;
i++;
}
HT[min].parent = 1;//parent域赋值,否则节点会重复;
return min;
}


int SelectTwoMinNode(HuffTree HT,int k, int &min1, int &min2) {
min1 = Weight_min(HT, k);
min2 = Weight_min(HT, k);
return 1;
}


HuffTree CreatHuffmanTree(HuffTree HT,int *wet,int amount) {
int n = amount * 2 - 1;//哈夫曼树的节点个数是原来的(amount*2-1)个
HT = (HuffTree)malloc(n * sizeof(HNode));//建立树;
int i;
//前amount个节点为原来的节点,初始化(原来的节点都是叶子节点)
for (i = 0; i < amount; i++) {
HT[i].parent = -1;
HT[i].lchild= -1;
HT[i].rchild= -1;
HT[i].wet= *wet;//将权值赋值给树中的节点
wet++;
}
//i在这里为amount-1;从amount开始为哈夫曼树增加的节点
//后面节点初始化;
int min1, min2;
for (i; i < n; i++) {
HT[i].parent = -1;
HT[i].lchild = -1;
HT[i].rchild = -1;
HT[i].wet = 0;
SelectTwoMinNode(HT, i, min1, min2);//选出权值最小的节点
//#if debug
// printf("#最小的两个权值:%d  %d#", min1, min2);
//#endif
HT[min1].parent = i;//
HT[min2].parent = i;
HT[i].lchild = min1;
HT[i].rchild = min2;
HT[i].wet = HT[min1].wet + HT[min2].wet;//该节点权值=两个权值想加
#if debug
printf("第%d个节点权值为:%d\n", i, HT[i].wet);
#endif
}
return HT;
}




void Test(HuffTree HT,int amount) {
int n = amount * 2 - 1;
for (int i = 0; i < n; i++) {
printf("%d %d %d ", i, HT[i].wet, HT[i].parent);
printf("\n");
}
}
//先序遍历将左子树权值变为0,右子树值变为1;
void ReverseRight(HuffTree HT, HuffTree Head) {//改变权值,为哈夫曼编码做准备;
if (1) {
HT[Head->lchild].wet = 0;
// printf("1");
HT[Head->rchild].wet = 1;
if (Head->lchild == -1 && Head->rchild == -1)
return;
}
ReverseRight(HT, &HT[Head->lchild]);
ReverseRight(HT, &HT[Head->rchild]);
}
/*权值重新更改之后,在根据根节点到叶子节点所经过的路径来编码*/
void HuffManEncode(HuffTree HT,int amount) {
//从根节点开始遍历。
int i;
for (i = 0; i < amount; i++) {//从数组第一个元素开始寻找父节点
int father = HT[i].parent;
int j = i;//用j记录当前节点
int *Code = (int*)malloc(amount * sizeof(int));//动态数组,根据amount大小来
int k = amount - 1;
while (father != -1) {//其双亲节点不为根节点
*(Code + k) = HT[j].wet;
k--;
j = father;
father = HT[father].parent;
}
for (int j = k + 1; j < amount; j++) {
printf("%d", *(Code + j));
}
printf("\n");
free(Code);
}


}

你可能感兴趣的:(哈夫曼编码C语言实现)