小顶堆_优先队列 ,实现哈夫曼树的WPL求值
2016-06-01 15:14
288 查看
优先队列内部一般是用堆来实现的。我们知道堆的插入、删除操作的时间复杂度都是 O(logN)O(logN),自然优先队列的插入、删除操作的时间复杂度也都是 O(logN)O(logN)。堆中的堆顶元素就是优先队列的队首元素。
对于大根堆实现的优先队列,总是优先级高的元素先被删除;相对的,对于小根堆实现的优先队列,总是优先级低的元素先被删除。对于后者,我们也称之为优先队列。
优先队列可以用于解决哈夫曼编码问题。这个问题我们在二叉树一章最后给大家介绍过噢,后面的课程中我们会为大家讲解如何用优先队列来解决它。此外,优先队列还能解决任务调度问题,例如操作系统的进程调度问题。
在 C++ 的 STL 里,有封装好的优先队列 priority_queue,它包含在头文件 里噢。优先级可以自己定义,默认优先级是权值大的元素优先级高。优先队列是一种用途广泛的数据结构,它能巧妙高效的解决很多其他数据结构不容易解决的问题
《树和二叉树》最后有介绍哈夫曼编码问题,对于一个已知的字符串,我们要计算字符串进行哈夫曼编码后的长度,即哈夫曼树的带权路径长度 WPL(Weighted Path Length),也就是每个叶子结点到根结点的距离乘以叶子结点权值结果之和。
当哈夫曼树上结点总个数大于 1 时,哈夫曼树的 WPL,等于树上除根结点之外的所有结点的权值之和。如果结点总个数为 1,则哈夫曼树的 WPL 即为根结点权值。例如上面的例子里:
WPL=16+10+9+7+5+5+4+5+3+4+2+3+2+2+2+1+1+1=82
对于大根堆实现的优先队列,总是优先级高的元素先被删除;相对的,对于小根堆实现的优先队列,总是优先级低的元素先被删除。对于后者,我们也称之为优先队列。
优先队列可以用于解决哈夫曼编码问题。这个问题我们在二叉树一章最后给大家介绍过噢,后面的课程中我们会为大家讲解如何用优先队列来解决它。此外,优先队列还能解决任务调度问题,例如操作系统的进程调度问题。
在 C++ 的 STL 里,有封装好的优先队列 priority_queue,它包含在头文件 里噢。优先级可以自己定义,默认优先级是权值大的元素优先级高。优先队列是一种用途广泛的数据结构,它能巧妙高效的解决很多其他数据结构不容易解决的问题
《树和二叉树》最后有介绍哈夫曼编码问题,对于一个已知的字符串,我们要计算字符串进行哈夫曼编码后的长度,即哈夫曼树的带权路径长度 WPL(Weighted Path Length),也就是每个叶子结点到根结点的距离乘以叶子结点权值结果之和。
当哈夫曼树上结点总个数大于 1 时,哈夫曼树的 WPL,等于树上除根结点之外的所有结点的权值之和。如果结点总个数为 1,则哈夫曼树的 WPL 即为根结点权值。例如上面的例子里:
WPL=16+10+9+7+5+5+4+5+3+4+2+3+2+2+2+1+1+1=82
利用小顶堆_优先队列 ,实现哈夫曼树的WPL求值
#include<iostream> using namespace std; //从优先队列中选出权值最小的两个pop,将权值相加得到新节点,权值和累加 //插入队列中,直至队列中只有一个元素,WPL求出 class Heap { private: int *data, size; public: Heap(int length_input) { data = new int[length_input]; size = 0; } ~Heap() { delete[] data; } void push(int value) { data[size] = value; int current = size; int father = (current - 1) / 2; while (data[current] < data[father]) { swap(data[current], data[father]); current = father; father = (current - 1) / 2; } size++; } int top() { return data[0]; } void update(int pos, int n) { int lchild = 2 * pos + 1, rchild = 2 * pos + 2; int max_value = pos; if (lchild < n && data[lchild] < data[max_value]) { max_value = lchild; } if (rchild < n && data[rchild] < data[max_value]) { max_value = rchild; } if (max_value != pos) { swap(data[pos], data[max_value]); update(max_value, n); } } void pop() { swap(data[0], data[size - 1]); size--; update(0, size); } int heap_size() { return size; } }; int main() { //n个数;value权值; int n,value,ans=0; cin>>n; Heap heap(n); for(int i=1;i<=n;i++){ cin>>value; heap.push(value); } if(n==1){ ans=ans+heap.top(); } while(heap.heap_size()>1){ int a=heap.top(); heap.pop(); int b=heap.top(); heap.pop(); ans=ans+a+b; heap.push(a+b); } cout<<ans<<endl; return 0; }
相关文章推荐
- XMLHTTP使用详解
- Hibernate配置文件和映射元素解释
- POCO系列之——延迟加载
- checkstyle相关
- 感谢传智播客+C#.Net学习之旅
- 聚集索引和非聚集索引的区别有哪些
- windows服务器和linux服务器ftp取数shell脚本
- java之序列化Serialization 机制
- 21.JVM中G1收集器解密
- ios UILabel 添加删除线或者下滑线
- POCO系列之——什么是POCO
- iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一)
- 【微信开发之问题集锦】redirect_uri 参数错误
- 转 Python爬虫入门四之Urllib库的高级用法
- Leetcode 之Flatten Binary Tree to Linked List(50)
- vim基本配置
- Start application automatically during controller boot-up
- js匿名函数作为函数参数详解
- C++ STL
- 笔记二:关于在Windows环境下mysql数据库乱码的问题