赫夫曼编码--代码实现

实现效果:

输入 树的结点 以及各个结点的权值

输出  将赫夫曼编码输出

输入 

4
A 10
B 20
C 15
D 17

输出

A:00
B:11
C:01
D:10

思路:

第一步:将所有结点的元素,以及所带权值放到一个数组arr里面。这个数组arr的一行包括结点元素,结点权值,结点的双亲,结点的左孩子,结点的右孩子。并将所知结点的的双亲、左孩子,右孩子赋值为-1。

比如实例中有4个结点 啧这四个节点在数组中的值如下

A 10 -1 -1 -1
B 20 -1 -1 -1
C 15 -1 -1 -1
D 17 -1 -1  -1

第二步:通过findMin()函数知道已知所有结点中的最小两个权值的下标,将它们的权值赋给新增的结点(野史他们的双亲)。

(

A 10 -1 -1 -1
B 20 -1 -1 -1
C 15 -1 -1 -1
D 17 -1 -1 -1

 25(10+15) -1 0(A的下标) 2(C的下标)  --(这边注意了那个由于结点的元素是未知的所以这边没给结点但元素赋值
)

第三步:反复执行findMin()函数直到到达根节点

第四步:从第一个数组坐标开始,反复寻找其双亲节点,若是双亲节点的左孩子保存0右孩子保存1(这边默认权值较小的为左孩子,否则为右孩子)

第五步:将结点与赫夫曼编码输出

#include <stdio.h>

#include <stdlib.h>
#define OK 1
#define ERROR 0
#define INF 1000
#define MAX 50
/*
4
A 10
B 20
C 15
D 17
*/
typedef int Status;
typedef char** HuffmanCode;
typedef struct HuffmanNode{
char data;
int weight;
int parent,lchild,rchild;
}HuffmanNode;
typedef struct HuffmanTree{
    HuffmanNode arr[MAX];
    int n;
}HuffmanTree;


Status initTree(HuffmanTree *T){
int i=0;
scanf("%d",&T->n);
for(i = 0; i < T->n; i++){
fflush(stdin);
scanf("%c%d",&T->arr[i].data,&T->arr[i].weight);
T->arr[i].parent=T->arr[i].lchild=T->arr[i].rchild=-1;
}
return OK;
}


Status findMin(HuffmanTree T,int *m1,int *m2,int num){
int i,min1=INF,min2=INF;
for(i = 0; i < num; i++){
if(T.arr[i].parent==-1){
if(T.arr[i].weight < min1){
min2 = min1;*m2 = *m1;
min1 = T.arr[i].weight;*m1 = i;
}else if(T.arr[i].weight < min2){
min2 = T.arr[i].weight;*m2 = i;
}
}
}
printf("AAA:%d-->%d\t%d-->%d\n",min1,*m1,min2,*m2);


if(min1 == INF || min2 == INF) return ERROR;
else return OK;
}


Status createTree(HuffmanTree *T){
    int m1 = 0;
    int m2 = 0;
    int i=T->n;
while(findMin((*T),&m1,&m2,i)){
T->arr[m1].parent = T->arr[m2].parent = i;
T->arr[i].weight = T->arr[m1].weight + T->arr[m2].weight;
T->arr[i].lchild = m1;
T->arr[i].rchild = m2;
T->arr[i].parent = -1;
i++;
}
return OK;
}


void show(HuffmanTree T){
    int i;
    for(i = 0; i < T.n+3; i++){
printf("%c %d\t%d %d %d\n ",T.arr[i].data,T.arr[i].weight,T.arr[i].parent,T.arr[i].lchild,T.arr[i].rchild);
T.arr[i].parent=T.arr[i].lchild=T.arr[i].rchild=-1;
}
}
void createHuffmanCode(HuffmanTree T, HuffmanCode *HC){
    int i,c,p,top,j;
    char s[MAX];
    (*HC) = (char**)malloc(sizeof(char *)*T.n);
    for(i = 0;i<T.n;i++){
        top = 0;
        c = i;
        p = T.arr[i].parent;
        while(p != -1){
            if(T.arr[p].lchild == c) s[top++] = '0';
            else s[top++] = '1';
            c = p; p = T.arr[p].parent;
        }
        (*HC)[i] = (char *)malloc(sizeof(char)*5);
        j = 0;
        (*HC)[i][j++] = T.arr[i].data;
        (*HC)[i][j++] = ':';
        while(top != 0){
            (*HC)[i][j++] = s[--top];
        }
        (*HC)[i][j] = '\0';
    }
}
int main()
{
    HuffmanTree T;
    HuffmanCode g;
    int i;
    initTree(&T);
    createTree(&T);
    createHuffmanCode(T,&g);
    for(i = 0;i<T.n;i++){
        printf("%s\n",g[i]);
    }


    return 0;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值