HuffmanTree 的 C 实现

5 篇文章 0 订阅
5 篇文章 0 订阅

哈夫曼树(最优二叉树)

提前复习数据结构课的知识

哈夫曼树的建立有四个步骤,总结成口诀就是(来源:王卓老师的数据结构视频):

  1. 建立森林全是根
  2. 选择两小新树
  3. 删除两小添新人
  4. 重复 2、3 剩单根

简单的解释:

  1. 首先输入 N 个值作为根建立的森林
  2. 在森林中选择两个权值最小的根(注意这里只是选根,有没有子树无所谓,到时候会合并)
  3. 删除这两个根(通常是把 parent 标记为非 0 值以在第 2 步中标记删除),将他们作为左右子树且将他们的权值的和作为新树的根,加入到森林
  4. 重复 2、3 步直到森林里只有一个树

思想

根据权值分配叶子节点的位置,权值越大/小离根的位置也就越近,否则就越远。

简单实现

这里选两个最小数用到了 STL 里的优先队列,C 实现可以参考我之前的文章。
没有实现解码,编码功能只是使用递归简单地输出结果。

// 最后完全忘了的是输出编码...
// 输出编码的思路是:
// 从叶节点开始往上找父节点,直到到到达根,然后判断是根的左右分支来输出编码,是一个递归的过程
// 这里规定左小右大
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

struct Tree {
    double weight;
    int parent;
    int lch, rch;
};

void huffman_code(Tree *tree, int cur, int parent);

/*
    问题:
    1. 定义 priority_queue 时单词拼写忘了
    2. 对 priority_queue 的元素比较还不熟
    3. 对优先队列的弹出元素大小判断错误(原先是 size() > 2)
    4. 用 top() 时代码写成了这样:
        fir = pq.top().first;
        sec = pq.top().second;
        pq.pop();
        pq.pop();

        导致结果出问题。这里 frist 是权,second 是下标,实际只会用到 second,而且用了一次 top 后如果
        还想找第二小的元素要先 pop 出队最小元素
    5. 最后忘了把新树 push 到队列中
*/
void create_tree(Tree *tree, int size){
    priority_queue<pair<double, int>, vector<pair<double, int> >, greater<pair<double, int> > > pq;
    
    for(int i=1; i<2*size; i++){
        tree[i].lch = tree[i].rch = 0;
        tree[i].parent = 0;
        tree[i].weight = -1;
    }
    
    for(int i=1; i<size+1; i++){
        scanf("%lf", &tree[i].weight);
        pq.push(make_pair(tree[i].weight, i));
    }
    
    for(int i=size+1; i<2*size; i++){
        int fir, sec;
        if(pq.size() >= 2){
            fir = pq.top().second;
            pq.pop();
            sec = pq.top().second;
            pq.pop();
            
            tree[i].lch = fir;
            tree[i].rch = sec;
            tree[i].weight = tree[fir].weight + tree[sec].weight;
            tree[fir].parent = tree[sec].parent = i;
            pq.push(make_pair(tree[i].weight, i));
        }
    }
    
    for(int i=1; i<size+1; i++){
        huffman_code(tree, i, tree[i].parent);
        puts("");
    }
    
    /*
        printf("lch: %d rch: %d parent: %d weight: %f\n",
        tree[i].lch,
        tree[i].rch,
        tree[i].parent,
        tree[i].weight);
    */
}

void huffman_code(Tree *tree, int cur, int parent){
    if(parent){
        huffman_code(tree, parent, tree[parent].parent);
        printf("%d", tree[parent].rch==cur);
    }
}

int main(){
    int size = 3;
    Tree tree[2*3];
    
    create_tree(tree, size);
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值