堆(优先队列)求huffman WPL

huffman编码中WPL等于没个结点到根结点的距离乘结点权值的总和,但我们也可以用另一种方法求WPL:如果huffman树只有一个结点,则WPL为根结点权值,否则WPL等于除了根结点以外的所有结点的权值之和。

我们可以用优先队列/堆实现这个过程:

 1 //用优先队列求huffman编码中的WPL
 2 #include <iostream>
 3 using std::cin;
 4 using std::cout;
 5 using std::endl;
 6 using std::swap;
 7
 8 template <typename Type> class Heap {
 9 private:
10     Type *data;
11     int size;
12     void update(int pos, int n) {
13         int lchild = 2 * pos + 1, rchild = 2 * pos + 2;
14         int max_value = pos;
15         if (lchild < n && data[lchild] < data[max_value]) {
16             max_value = lchild;
17         }
18         if (rchild < n && data[rchild] < data[max_value]) {
19             max_value = rchild;
20         }
21         if (max_value != pos) {
22             swap(data[pos], data[max_value]);
23             update(max_value, n);
24         }
25     }
26 public:
27     Heap(int length_input) {
28         data = new Type[length_input];
29         size = 0;
30     }
31     ~Heap() {
32         delete[] data;
33     }
34     void push(Type value) {
35         data[size] = value;
36         int current = size;
37         int father = (current - 1) / 2;
38         while (data[current] < data[father]) {
39             swap(data[current], data[father]);
40             current = father;
41             father = (current - 1) / 2;
42         }
43         size++;
44     }
45     Type top() {
46         return data[0];
47     }
48     void pop() {
49         swap(data[0], data[size - 1]);
50         size--;
51         update(0, size);
52     }
53     int heap_size() {
54         return size;
55     }
56 };
57 int main() {
58     int n,value,ans=0;
59     cin>>n;
60     Heap<int> heap(n);
61     for(int i=1;i<=n;i++){
62         cin>>value;
63         heap.push(value);
64     }
65     if(n==1){
66         ans+=heap.top();
67     }
68     while(heap.heap_size()>1){
69         int a=heap.top();
70         heap.pop();
71         int b=heap.top();
72         heap.pop();
73         //将小根堆最前面的两个元素,即最小的两个元素合并
74         //并把合成的树押回队列中
75         ans=ans+a+b;
76         heap.push(a+b);
77     }
78     cout<<ans<<endl;
79     return 0;
80 }
时间: 2024-11-05 21:57:49

堆(优先队列)求huffman WPL的相关文章

堆 (优先队列)举例

*/--> pre.src {background-color: Black; color: White;} 堆 (优先队列)举例 题目: 你需要驾驶一辆卡车行驶 l 单位距离.最开始的时候,卡车上有 p 单位的汽油.卡车每开 1 单位距离需要消费 1 单位的汽油.如果在途中汽车上的汽油耗尽,卡车就无法继续前行,因而无法到达终点.在途中一共有 n 个加油站.第 i 个加油站在距离起点 ai 单位距离的地方,最多可以给卡车加 bi 单位汽油.假设卡车的燃料箱的容量是无限大的,无论加多少油都没有问题

纯数据结构Java实现(6/11)(二叉堆&amp;优先队列)

堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). 但是二叉堆,需要满足一些特殊性质: 其一.二叉堆一定是一棵完全二叉树 (完全二叉树可以用数组表示,见下面) 完全二叉树缺失的部分一定是在右下方.(每层一定是从左到右的顺序优先存放) 完全二叉树的结构,可以简单理解成按层安放元素的.(所以数组是不错的底层实现) 其二.父节点一定比子节点大 (针对大顶堆

堆-优先队列

堆-优先队列 前置知识:二叉树. 参考资料 暂无 堆就是优先队列,可以用来解决动态区间查询最值问题. 堆就是一个完全二叉树,可以插入节点,删除根节点(也可以删除特定节点). 为了方便,普通的堆节点 \(i\) 的父亲就是 \([i\div2]\) (\([x]\) 表示不超过 \(x\) 的最大整数). 节点 \(i\) 的左儿子是 \(i\times2\),右儿子是 \(i\times2+1\). 对于一个大顶堆: 每次插入节点的时候,就把节点插在完全二叉树的最后,如果它比它的父亲节点大,就把

Running Median POJ - 3784 (对顶堆/优先队列)

For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output the median (middle value) of the elements received so far. Input The first line of input contains a single int

算法导论学习之线性时间求第k小元素+堆思想求前k大元素

对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思路例如以下: 1.分解:将A[p,r]分解成A[p,q-1]和A[q+1,r]两部分.使得A[p,q-1]都小于A[q],A[q+1,r]都不小于A[q]; 2.求解:假设A[q]恰好是第k小元素直接返回,假设第k小元素落在前半区间就到A[p,q-1]递归查找.否则到A[q+1,r]中递归查找. 3

【优先队列-求第Ki大的数】Black Box

Black Box Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8637   Accepted: 3542 Description Our Black Box represents a primitive database. It can save an integer array and has a special i variable. At the initial moment Black Box is empt

【bzoj2151】种树(堆/优先队列+双向链表)

题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2151 这道题因为优先队列不怎么会用,而且手写堆的代码也不长,也想复习一下手写堆的写法……结果……WAWAWAWAW……看来我对堆的认识还是太浅薄了…… 这道题,如果没有限制不能选相邻的两个位置,那就肯定是贪心地选择m个美观度最大的位置种树.然而这里加了限制,那么我们可以注意到,如果一个美观度比较大的位置不被选上,一定是因为它两边的位置都被选了. 于是我们可以把n个美观度压进一个堆里,每

P1168 中位数[堆 优先队列]

题目描述 给出一个长度为NNN的非负整数序列AiA_iAi?,对于所有1≤k≤(N+1)/21 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2,输出A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1?,A3?,…,A2k−1?的中位数.即前1,3,5,…1,3,5,…1,3,5,…个数的中位数. 输入输出格式 输入格式: 第1行为一个正整数N,表示了序列长度. 第2行包含N个非负整数Ai?(Ai?≤109). 输出格式: 共2(N+1)/2行,第iii行为A1

升序堆和降序堆(优先队列) 洛谷1801

1 // 洛谷1801 2 // 一个升序堆,一个降序堆 3 // 降序堆维护序列的前i个最小值 4 // 插如元素的时候,如果x小于降序堆最大值,则替换,并将最大值插入升序堆:否则,直接插入升序堆 5 // 每次输出升序堆的最小值即可 6 7 8 #include <bits/stdc++.h> 9 using namespace std; 10 #define LL long long 11 typedef pair<int,int> pii; 12 const int inf