优先队列--堆
当你只需要找到最大最小值而不需要查找其他元素时,可以用二叉堆,不需要用用叉查找树。
Java版
java中的PriorityQueue就是个小顶堆(重写元素的compareTo方法可以轻易地改为大顶堆),但是它不能设置堆的最大容量,所以我自己实现了一个MinHeap。
import java.util.ArrayList; import java.util.List; /** * 小根堆。可用于取topK、排序等。<br> * MinHeap相对于PriorityQueue的优势在于:PriorityQueue是不能设置容量上限的;MinHeap可设置容量上限带来两个好处, * 一是内存占用可控 * ,二是提高添加和删除元素的速度(PriorityQueue和MinHeap增删元素时间复杂度都是logN,但是MinHeap中的N是有上限的 * ,所以达到上限后MinHeap更快一些) * * @Author:orisun * @Since:2016-5-25 * @Version:1.0 */ @SuppressWarnings("rawtypes") public class MinHeap<T extends Comparable> { private List<T> data; private int maxSize; /** * * @param maxSize * 指定堆的最大容量 */ public MinHeap(int maxSize) { data = new ArrayList<T>(maxSize); if (maxSize > 0) { this.maxSize = maxSize; } } public int size() { return data.size(); } public boolean isEmpty() { return data.size() == 0; } /** * 取出堆中存储的元素(不保证顺序)<br> * 时间复杂度O(1) * * @return */ public List<T> getTopK() { return data; } public void clear() { data.clear(); } private void swap(int i, int j) { T tmp = data.get(j); data.set(j, data.get(i)); data.set(i, tmp); } @SuppressWarnings("unchecked") private void heapDown(int i) { int l = (i + 1) * 2 - 1;// 左孩子的index int r = (i + 1) * 2;// 右孩子的index int smallest = i;// 父节点、左、右孩子中的最小者 // 如果左孩子存在,且左孩子小于smallest if (l < data.size() && data.get(l).compareTo(data.get(smallest)) < 0) { smallest = l; } // 如果右孩子存在,且左孩子小于smallest if (r < data.size() && data.get(r).compareTo(data.get(smallest)) < 0) { smallest = r; } // 如果父节点本来就比左右孩子小,则直接返回 if (i == smallest) { return; } // 父节点跟较小的那个子节点交换 swap(i, smallest); // 交换后影响到了子树,所以对子树递归进行heapify heapDown(smallest); } @SuppressWarnings({ "unchecked" }) private void heapUp(int i) { while (i > 0) { T ele = data.get(i); int p = (i - 1) / 2;// 父节点的index if (ele.compareTo(data.get(p)) < 0) {// 如果比父节点小,则跟父节点交换 swap(i, p); i = p; } else { // 否则停止 break; } } } /** * 获取堆顶元素(即堆中最小的元素)<br> * 时间复杂度O(1) * * @return */ public T getRoot() { return data.get(0); } /** * 向堆中添加一个元素<br> * 时间复杂度O(logN) * * @param ele */ @SuppressWarnings("unchecked") public void add(T ele) { int size = data.size(); if (size == 0) {// 如果容器为空,则直接插入即可 data.add(ele); return; } if (size < maxSize) {// 未达容量上限 data.add(ele);// 直接插到末位置上 heapUp(size);// 然后从末位置开始向上调整 } else {// 如果已达容量上限 if (ele.compareTo(data.get(0)) > 0) {// 如果不能比根节点大,则直接丢弃 data.set(0, ele); // 替换根节点 heapDown(0); // 然后从根节点开始向下调整 } } } /** * 删除堆顶元素<br> * 时间复杂度O(logN) */ public void delRoot() { int size = data.size(); if (size > 0) { T lastEle = data.get(size - 1); if (size > 1) { // 用末元素替换根节点 data.set(0, lastEle); data.remove(size - 1); // 然后从根节点开始向下调整 heapDown(0); } else { data.remove(size - 1); } } } /** * 删除并返回堆顶元素。通过不断地poll,可以有序地取出堆中的所有元素<br> * 时间复杂度O(logN) * * @return */ public T poll() { T rect = null; int size = data.size(); if (size > 0) { rect = getRoot(); delRoot(); } return rect; } }
C++版
2 #include<iostream>
3 using std::cin;
4 using std::cout;
5 using std::vector;
6 using std::endl;
7
8 template <typename Comparable>
9 class BinaryHeap{
10 public:
11 explicit BinaryHeap(int capacity=100);
12 explicit BinaryHeap(const vector<Comparable>& items)
13 :array(items.size()+10),currentSize(items.size()){
14 for(int i=0;i<items.size();i++)
15 array[i+1]=items[i];
16 buildHeap();
17 }
18
19 bool isEmpty() const;
20 const Comparable & findMin() const;
21
22 void insert(const Comparable & x);
23 void deleteMin();
24 void deleteMin(Comparable & minItem);
25 void makeEmpty();
26
27
28 int currentSize;
29 vector<Comparable> array;
30 private:
31 void buildHeap();
32 void percolateDown(int hole);
33 };
34
35 template <typename Comparable>
36 bool BinaryHeap<Comparable>::isEmpty() const{
37 return currentSize==0;
38 }
39
40 template <typename Comparable>
41 void BinaryHeap<Comparable>::insert(const Comparable & x){
42 if(currentSize==array.size()-1)
43 array.resize(array.size()*2);
44 int hole=++currentSize;
45 for(;hole>1&&x<array[hole/2];hole/=2)
46 array[hole]=array[hole/2];
47 array[hole]=x;
48 }
49
50 template <typename Comparable>
51 void BinaryHeap<Comparable>::deleteMin(){
52 if(isEmpty())
53 throw;// UnderflowException();
54 array[1]=array[currentSize--];
55 percolateDown(1);
56 }
57
58 template <typename Comparable>
59 void BinaryHeap<Comparable>::deleteMin(Comparable & minItem){
60 if(isEmpty())
61 throw;// UnderflowException();
62 minItem=array[1];
63 array[1]=array[currentSize--];
64 percolateDown(1);
65 }
66
67 template <typename Comparable>
68 void BinaryHeap<Comparable>::percolateDown(int hole){
69 int child;
70 Comparable tmp=array[hole];
71 for(;hole*2<=currentSize;hole=child){
72 child=hole*2;
73 if(child!=currentSize&&array[child+1]<array[child])
74 child++;
75 if(array[child]<tmp)
76 array[hole]=array[child];
77 else
78 break;
79 }
80 array[hole]=tmp;
81 }
82
83 template <typename Comparable>
84 void BinaryHeap<Comparable>::buildHeap(){
85 for(int i=currentSize/2;i>0;i--)
86 percolateDown(i);
87 }
88
89 int main(){
90 vector<int> array;
91 for(int num=150;num>10;num-=10)
92 array.push_back(num);
93 BinaryHeap<int> heap(array);
94 for(int i=1;i<=heap.currentSize;i++)
95 cout<<heap.array[i]<<"";
96 cout<<endl;
97
98 int min=0;
99 heap.deleteMin(min);
100 cout<<"The minimun value of heap:"<<min<<endl;
101
102 for(int i=1;i<=heap.currentSize;i++)
103 cout<<heap.array[i]<<"";
104 cout<<endl;
105
106 return0;
107 }
108
D:\C++>g++ BinaryHeap.cpp -o BinaryHeap
D:\C++>BinaryHeap.exe
20 50 30 70 60 40 90 80 120 140 110 150 100 130
The minimun value of heap:20
30 50 40 70 60 100 90 80 120 140 110 150 130
STL中的priority_queue
函数配接器Function Adapter
能够将仿函数和另一个仿函数结合起来的仿函数。函数配接器声明于<functional>中。
Priority Queue定义于文件<queue>中,其声明如下:
template<typename _Tp,
typename _Sequence = vector<_Tp>,
typename _Compare = less<typename _Sequence::value_type> >
class priority_queue
3 #include<queue>
4 #include<functional>
5 #include<string>
6
7 usingnamespace std;
8
9 template <typename PriorityQueue>
10 void dumpContents(conststring& msg,PriorityQueue & pq){
11 cout<<msg<<":"<<endl;
12 while(!pq.empty()){
13 cout<<pq.top()<<endl;
14 pq.pop();
15 }
16 }
17
18 int main(){
19 priority_queue<int> maxPQ;
20 priority_queue<int,vector<int>,greater<int>> minPQ; //默认情况下用的是less<int>
21
22 minPQ.push(150);minPQ.push(140);minPQ.push(130);minPQ.push(120);minPQ.push(110);minPQ.push(100);minPQ.push(90);
23 maxPQ.push(150);maxPQ.push(140);maxPQ.push(130);maxPQ.push(120);maxPQ.push(110);maxPQ.push(100);maxPQ.push(90);
24
25 dumpContents("minPQ",minPQ);
26 dumpContents("maxPQ",maxPQ);
27
28 return0;
29 }
D:\C++>priority_queue.exe
minPQ:
90
100
110
120
130
140
150
maxPQ:
150
140
130
120
110
100
90
自定义比较方法:
有两种策略可供选择:
(1)自定义比较器
class CMP{ public: bool operator() (const Comparable & a,const Comparable &b)const{ return a.value<b.value; } };
只需要重载operator()就可以了。
(2)在自已的类中重载operator<,因为在priority_queue中使用的默认比较器就是less<object>
class Comparable{ public: int value; bool operator< (const Comparable &b) const{ return value<b.value; } };
本文来自博客园,作者:高性能golang,转载请注明原文链接:https://www.cnblogs.com/zhangchaoyang/articles/1809519.html