数据结构-哈夫曼树

哈夫曼树

  给定N个权值作为N个叶子结点 ,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

定义
  哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数}。树的路径长度是从树根到每一结点的路径长度之和,记为WPL = (W1*L1+W2*L2+W3*L3+…+Wn*Ln),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。可以证明哈夫曼树的WPL是最小的。

 

 

代码实现

首先定义一个哈夫曼树的结构体,其中包含四个int域和一个char域,分别为节点自身权值、双亲及左右孩子的下标和数据域。

创建哈夫曼树:

​
typedef struct{
    char data;				//数据域
    int weight;				//结点的权值
    int parent, lChild, rChild;	//双亲与孩子的下标
}htNode,*HuffmanTree;

int initHuffmanTree(HuffmanTree& HT){
    HT = (htNode*)malloc(sizeof(htNode) * (2 * 10));//给HT分配2 * 10个htNOde大小的htNode类型的数组
    for (int i = 1; i <= 2 * 10 - 1; i++){
        HT[i].parent = HT[i].lChild = HT[i].rChild = -1;//双亲和孩子的值都置为-1
    }
    printf("请输入数据:\n");
    for (int i = 1; i <= 10; i++){
        //scanf("%c ",&HT[i].data);
        char a = getchar();
        if(a == '\n')	//遇到回车就结束
            break;
        else
            HT[i].data = a;	//给每个结点赋予数据
    }
    printf("请输入权值:\n");
    for (int i = 1; i <= 10; i++){
        scanf("%d",&HT[i].weight);//给每个结点赋予权值
    }
    char c = getchar();//这个来接收上面的回车
    return 1;
}
void createHuffmanTree(HuffmanTree& HT, int n){
    if (n <= 1)	//如果结点数小于等于1,不创建
        return;
    int min1, min2;	//定义两个数,来存储每次选取最小两个结点的权值
    int rnode, lnode;
    for (int i = n + 1; i <= 2 * n -1; i++){
        int min1 = INT_MAX; int lnode = -1;
        int min2 = INT_MAX; int rnode = -1;
        for (int j = 1; j <= i - 1; j++){
            if (HT[j].weight < min1 && HT[j].parent == -1){
                min2 = min1;	
                rnode = lnode;//碰到比min1小的,那min1的值就给第二小的min2,下标也给它
                min1 = HT[j].weight; lnode = j;	//然后最小的给min1,下标同理
            }else if (HT[j].weight < min2 && HT[j].parent == -1){
                min2 = HT[j].weight;
                rnode = j;
            }
        }
        HT[lnode].parent = HT[rnode].parent = i;
        HT[i].lChild = lnode;
        HT[i].rChild = rnode;
        HT[i].weight = HT[lnode].weight + HT[rnode].weight;
    }
}

​

 

代码实现:

void createHuffmanCode(HuffmanTree HT, HuffmanCode & HC, int n){
    HC = (HuffmanCode)malloc(sizeof(HuffmanCode) * n + 1);//申请n + 1个HuffmanCode大小HuffmanCode类型的临时空间
    //因为下标是从一开始,和哈夫曼树的结构对应
    char* array = (char*)malloc(sizeof(char) * n);//申请n个char大小char类型的临时空间,这个临时数组记录每次遍历出来的编码
    int start = 0,child = 0,parent = 0;		//start为array数组记录下标,child初始为叶子结点下标,而后就是孩子结点的下标,parent记录双亲结点的下标
    array[n - 1] = '\0';
    for (int i = 1; i <= n; i++){//只要叶子结点的编码
        start = n - 1;
        child = i;
        parent = HT[child].parent;
        while (parent != -1){//根节点没有双亲
            start--;
            if (HT[parent].lChild == child)	//左孩子就是0,右孩子就为1
                array[start] = '0';
            else
                array[start] = '1';
            child = parent; parent = HT[child].parent;	//向根结点接近
        }
        HC[i] = (char*)malloc(sizeof(char) * (n - start));	//给数组里的数组申请n - start个char大小的char*类型的临时空间
        strcpy(HC[i], &array[start]);	//array里记录的编码给HC的第i个数组
    }
    free(array);	//释放临时空间
}

测试结果:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值