数据结构与算法---复习:最优二叉树 哈夫曼算法

数据结构与算法—复习:最优二叉树 哈夫曼算法

手画很简单,代码则需要多考虑

/**
 * 程序说明:复习 最优二叉树(哈夫曼树) 哈夫曼算法
 */

#include <stdio.h>
#include <malloc.h>

/**
 * 定义一个非常大的整数
 */
int MAXINT = 999999999;

/**
 * 哈夫曼树 结点结构
 */
struct HtNode{
    int ww; //该点到带权外部路径长度的值
    int parent,llink,rlink; //父结点、左子树、右子树
};

/**
 * 哈夫曼树 结构
 */
struct HtTree{
    int m;  //外部节点个数
    int root;   //哈夫曼树根在数组中的下标
    struct HtNode* ht;  //存放 2m - 1个 结点的数组
};
typedef struct HtTree* PHtTree;

PHtTree huffman(int m,int* w){
    PHtTree pht = (PHtTree)malloc(sizeof(struct HtTree));
    int i,  // i,j 为循环所用
        j,
        x1, // x1 存储 最小权无父结点的结点下标
        x2, // x2 存储 次最小权无父结点的结点下标
        m1, // m1 存储 最小权无父结点的结点的带权外部路径权值
        m2; // m2 存储 次最小权无父结点的结点的带权外部路径权值
    if(pht == NULL){
        printf("哈夫曼树分配空间超出范围\n");
        return pht;
    }
    pht->ht = (struct HtNode*)malloc(sizeof(struct HtNode) * (2*m - 1));
    if(pht->ht == NULL){
        printf("哈夫曼树结点分配空间超出范围\n");
        return pht;
    }
    //对整个哈夫曼数组初始化
    for (i = 0; i < 2*m - 1; ++i) {
        //所给权值都是扩充结点,一开始的左右子树和父结点都是不存在的
        pht->ht[i].llink = -1; pht->ht[i].rlink = -1; pht->ht[i].parent = -1;
        //当在m个权值结点以内时,此时的权值,就是所给的权值
        if(i < m){
            pht->ht[i].ww = w[i];
        }else{  //在m个结点以外的空间,是还没有生成的父结点,他们的权值不确定,置为空
            pht->ht[i].ww = -1;
        }
    }
    //每循环一次,构造一个内部结点
    for (i = 0; i < m-1; ++i) {
        m1 = m2 = MAXINT;
        x1 = -1; x2 = -1;
        //找两个最小权的无父结点的结点
        for (j = 0; j < m + i; j++){
            if(pht->ht[j].ww < m1 && pht->ht[j].parent == -1){
                //用x1 存放最小权无父结点的结点下标
                //下面的前两句话的作用是,如果发现了更小的结点,则把当前的第一结点记作次小结点
                m2 = m1; x2 = x1; m1 = pht->ht[j].ww; x1 = j;
            }
            else if(pht->ht[j].ww < m2 && pht->ht[j].parent == -1){
                //用x2 存放次最小权无父结点的结点下标
                m2 = pht->ht[j].ww; x2 = j;
            }
            //构造内部结点
            pht->ht[x1].parent = m + i; pht->ht[x2].parent = m + i;
            pht->ht[m+i].ww = m1 + m2; pht->ht[m+i].llink = x1; pht->ht[m+i].rlink = x2;
        }
        pht->root = 2*m-2;
        return pht;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值