zoukankan      html  css  js  c++  java
  • 哈夫曼树与哈夫曼编码

    哈夫曼树

    哈夫曼树是一种二叉树,其带权路径(叶子结点的权重与其到根节点的路径长度之积)和最小。

    通俗一点说,哈夫曼树的每个叶子结点都有一个权重,而每个叶子结点的带权路径,就是其权重与到根节点的距离的乘积。哈夫曼树要求所有叶子结点的带权路径和最小。

    怎么构造?虽说哈夫曼树是一个二叉树,但是可以根据二叉树的原理扩展为k叉树,下面先介绍二叉树的构造方法,k叉树就显而易见了。

    运用贪心的思想,肯定是权重越大的节点越靠近根节点是最优的。我们可以先将权重排序,由小到大、由下及上构造。每次选取权重最小的两个节点,将其连接到一个父节点上,父节点的权重为子节点权重之和,然后将父节点放回到数组中,重复这个过程,直到构造出树。

    考虑k叉树,显然每次选取k个最小的连接到一个父节点上。但是k叉会有一个问题:每一个节点的子节点并不是满k叉的(读者可自证为什么二叉树不会有这个问题),但是反观我们的构造方法,是优先构造底层,而显然越靠近根节点的层越满越优,所以之前的构造方法就会有问题。这里就需要将不够的地方补齐,手动添加一下叶子结点,至于其权重,弄成0就好啦。

    哈夫曼编码

    考虑一个k叉树,根据每一层选择的节点不一样,可以表示出k进制数,哈夫曼编码便是运用这个道理。将每一个需要编码的元素以其出现次数为权重,构建哈夫曼树,自然编码也就出来了。

    代码网上比较多,这里就不放了,放一道哈夫曼意识流的题qwq

    [[NOI2015] 荷马史诗]([P2168 NOI2015] 荷马史诗 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))

    #include <iostream>
    #include <cstdio>
    #include <queue>
    using namespace std;
    long long read() {
    	long long x = 0; int f = 0; char c = getchar();
    	while (c < '0' || c > '9') f |= c == '-', c = getchar();
    	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c - '0'), c = getchar();
    	return f ? -x : x;
    }
    int n, k;
    struct szh {
    	int h;
    	long long w;
    	szh(long long x, int y){
    		w = x; h = y;
    	}
    	bool operator < (const szh b) const {
    		if (w != b.w) return w > b.w;
    		return h > b.h;
    	}
    };
    long long ans;
    priority_queue<szh> q;
    int main() {
    	n = read(); k = read();
    	for (int i = 1; i <= n; ++i) {
    		long long x = read();
    		q.push(szh(x, 1));
    	}
    	int cnt = 0;
    	if ((n - 1) % (k - 1)) cnt = k - 1 - (n - 1) % (k - 1);
    	for (int i = 1; i <= cnt; ++i) q.push(szh(0, 1));
    	cnt += n;
    	while (cnt > 1) {
    		long long sum = 0;int height = 0;
    		for (int i = 1; i <= k; ++i) {
    			sum += q.top().w;
    			height = max(height, q.top().h);
    			q.pop();
    		}
    		q.push(szh(sum, height + 1));
    		ans += sum;
    		cnt -= k - 1;
    	}
    	cout << ans << endl << q.top().h - 1;
    }
    
  • 相关阅读:
    深入理解memcached
    如何查看你的 memcached 的状态
    转: Linux 技巧:让进程在后台可靠运行的几种方法
    centos 如何用 rsyslog 搭建本地日志服务(续1: omprog模块与php deamon的配合使用)
    转: 解决MSYS2下的中文乱码问题
    解决windows下vim方向键变成 ABCD 的问题
    centos 如何用 rsyslog 搭建本地日志服务
    转:理解 Linux 的硬链接与软链接
    php include include_once require require_once 的区别与联系
    让块级元素水平垂直居中
  • 原文地址:https://www.cnblogs.com/kylinbalck/p/15059082.html
Copyright © 2011-2022 走看看