C++实现优先队列——最小堆,d路堆及配对堆
来源:互联网 发布:淘宝助理报告错误 编辑:程序博客网 时间:2024/05/17 02:27
优先队列实现,此处的优先队列是用于Huffman树实现的(具体参考上一篇文章)。所以用于比较的都是huffman树的node的频率,希望读者见谅。
最小堆(二叉):
template <typename T>class MinHeap{public:MinHeap(int cap );~MinHeap();public:bool insert(pTree val);bool remove(pTree data);void print();int size;T getTop();bool createMinHeap(pTree a[], int length);private:int capacity;T * heap;private:void filterUp(int index);void filterDown(int begin, int end);};template <typename T>MinHeap<T>::MinHeap(int cap ):capacity(cap), size(0), heap(nullptr){heap = new pTree[capacity];};template<typename T>MinHeap<T>::~MinHeap(){delete[]heap;};template <typename T>void MinHeap<T>::print(){for (int i = 0; i < size; i++)cout << heap[i]->freq << " ";};template <typename T>T MinHeap<T>::getTop()//返回最小值{if (size != 0)return heap[0];};template <typename T>bool MinHeap<T>::insert(pTree val)//插入函数{if (size == capacity)return false;heap[size] = val;filterUp(size);size++;return true;};template <typename T>void MinHeap<T>::filterUp(int index)//由上至下进行调整{pTree value = heap[index];while (index > 0){int indexParent = (index-1) / 2;if (value->freq >= heap[indexParent]->freq)break;else{heap[index] = heap[indexParent];index = indexParent;}}heap[index] = value;};template<typename T>bool MinHeap<T>::createMinHeap(pTree a[], int length){if (length > capacity)return false;for (int i = 0; i < length; i++){insert(a[i]);}return true;};template<typename T>bool MinHeap<T>::remove(pTree data)//删除元素{if (size == 0)return false;int index;for (index = 0; index < size; index++){if (heap[index]== data)break;}if (index == size)return false;heap[index] = heap[size - 1];size--;filterDown(index, size);return true;};template<typename T>void MinHeap<T>::filterDown(int current, int end)//由下至上进行调整{int child = current * 2 + 1;pTree value = heap[current];while (child <= end){if (child < end && heap[child]->freq > heap[child + 1]->freq)child++;if (value->freq<heap[child]->freq)break;else{heap[current] = heap[child];current = child;child = child * 2 + 1;}}heap[current] = value;};
配对堆:
class PairNode{ public: pTree element; PairNode *leftChild; PairNode *nextSibling; PairNode *prev; PairNode(pTree element) { this->element = element; leftChild = NULL; nextSibling = NULL; prev = NULL; }};class PairingHeap{ private: PairNode *root; void reclaimMemory(PairNode *t); void compareAndLink(PairNode * &first, PairNode *second); PairNode *combineSiblings(PairNode *firstSibling); PairNode *clone(PairNode *t); public: PairingHeap(); PairingHeap(PairingHeap &rhs); ~PairingHeap(); bool isEmpty(); bool isFull(); pTree &findMin(); PairNode *Insert(pTree &x); void deleteMin(); void deleteMin(pTree &minItem); void makeEmpty(); void decreaseKey(PairNode *p, pTree &newVal ); PairingHeap &operator=(PairingHeap &rhs);};PairingHeap::PairingHeap(){ root = NULL;}PairingHeap::PairingHeap(PairingHeap & rhs){ root = NULL; *this = rhs;}/* * Destroy the leftist heap. */PairingHeap::~PairingHeap(){ makeEmpty();}/* * Insert item x into the priority queue, maintaining heap order. * Return a pointer to the node containing the new item. */PairNode *PairingHeap::Insert(pTree &x){ PairNode *newNode = new PairNode(x); if (root == NULL) root = newNode; else compareAndLink(root, newNode); return newNode;}/* * Find the smallest item in the priority queue. * Return the smallest item, or throw Underflow if empty. */pTree &PairingHeap::findMin(){ return root->element;}/* * Remove the smallest item from the priority queue. * Throws Underflow if empty. */void PairingHeap::deleteMin(){ PairNode *oldRoot = root; if (root->leftChild == NULL) root = NULL; else root = combineSiblings(root->leftChild); delete oldRoot;}/* * Remove the smallest item from the priority queue. * Pass back the smallest item, or throw Underflow if empty. */void PairingHeap::deleteMin(pTree &minItem){ if (isEmpty()) { cout<<"The Heap is Empty"<<endl; return; } minItem = findMin(); deleteMin(); cout<<"Minimum Element: "<<minItem<<" deleted"<<endl;}/* * Test if the priority queue is logically empty. * Returns true if empty, false otherwise. */bool PairingHeap::isEmpty(){ return root == NULL;}/* * Test if the priority queue is logically full. * Returns false in this implementation. */bool PairingHeap::isFull(){ return false;}/* * Make the priority queue logically empty. */void PairingHeap::makeEmpty(){ reclaimMemory(root); root = NULL;}/* * Deep copy.*/PairingHeap &PairingHeap::operator=(PairingHeap & rhs){ if (this != &rhs) { makeEmpty( ); root = clone(rhs.root); } return *this;}/* * Internal method to make the tree empty. */void PairingHeap::reclaimMemory(PairNode * t){ if (t != NULL) { reclaimMemory(t->leftChild); reclaimMemory(t->nextSibling); delete t; }}/* * Change the value of the item stored in the pairing heap. * Does nothing if newVal is larger than currently stored value. * p points to a node returned by insert. * newVal is the new value, which must be smaller * than the currently stored value. */void PairingHeap::decreaseKey(PairNode *p, pTree &newVal){ if (p->element->freq < newVal->freq) return; p->element = newVal; if (p != root) { if (p->nextSibling != NULL) p->nextSibling->prev = p->prev; if (p->prev->leftChild == p) p->prev->leftChild = p->nextSibling; else p->prev->nextSibling = p->nextSibling; p->nextSibling = NULL; compareAndLink(root, p); }}/* * Internal method that is the basic operation to maintain order. * Links first and second together to satisfy heap order. * first is root of tree 1, which may not be NULL. * first->nextSibling MUST be NULL on entry. * second is root of tree 2, which may be NULL. * first becomes the result of the tree merge. */void PairingHeap::compareAndLink(PairNode * &first, PairNode *second){ if (second == NULL) return; if (second->element->freq < first->element->freq) { second->prev = first->prev; first->prev = second; first->nextSibling = second->leftChild; if (first->nextSibling != NULL) first->nextSibling->prev = first; second->leftChild = first; first = second; } else { second->prev = first; first->nextSibling = second->nextSibling; if (first->nextSibling != NULL) first->nextSibling->prev = first; second->nextSibling = first->leftChild; if (second->nextSibling != NULL) second->nextSibling->prev = second; first->leftChild = second; }}/* * Internal method that implements two-pass merging. * firstSibling the root of the conglomerate; * assumed not NULL. */PairNode *PairingHeap::combineSiblings(PairNode *firstSibling){ if (firstSibling->nextSibling == NULL) return firstSibling; static vector<PairNode *> treeArray(5); int numSiblings = 0; for (; firstSibling != NULL; numSiblings++) { if (numSiblings == treeArray.size()) treeArray.resize(numSiblings * 2); treeArray[numSiblings] = firstSibling; firstSibling->prev->nextSibling = NULL; firstSibling = firstSibling->nextSibling; } if (numSiblings == treeArray.size()) treeArray.resize(numSiblings + 1); treeArray[numSiblings] = NULL; int i = 0; for (; i + 1 < numSiblings; i += 2) compareAndLink(treeArray[i], treeArray[i + 1]); int j = i - 2; if (j == numSiblings - 3) compareAndLink (treeArray[j], treeArray[j + 2]); for (; j >= 2; j -= 2) compareAndLink(treeArray[j - 2], treeArray[j] ); return treeArray[0];}/* * Internal method to clone subtree. */PairNode *PairingHeap::clone(PairNode * t){ if (t == NULL) return NULL; else { PairNode *p = new PairNode(t->element); if ((p->leftChild = clone( t->leftChild)) != NULL) p->leftChild->prev = p; if ((p->nextSibling = clone( t->nextSibling)) != NULL) p->nextSibling->prev = p; return p; }}
class DaryHeap{ private: int d; int currentSize; int size; pTree *array; public: /* * Constructor */ DaryHeap(int capacity, int numKids) { currentSize = 1; d = numKids; size = capacity + 1+1; array=new pTree[capacity + 1+1]; } /* * Constructor , filling up heap with a given array */ /* * Function to check if heap is empty */ bool isEmpty() { return currentSize == 1; } /* * Check if heap is full */ bool isFull() { return currentSize == size; } /* * Clear heap */ void makeEmpty( ) { currentSize = 1; } /* * Function to get index parent of i */ int parent(int i) { return (i - 1) / d+1; } /* * Function to get index of k th child of i */ int kthChild(int i, int k) { return d * i + k+1; } /* * Function to inset element */ void Insert(pTree x) { if (isFull()) { cout<<"Array Out of Bounds"<<endl; return; } int hole = currentSize; currentSize++; array[hole] = x; percolateUp(hole); } /* * Function to find least element */ pTree findMin() { if (isEmpty()) { cout<<"Array Underflow"<<endl; return 0; } return array[1]; } /* * Function to delete element at an index */ pTree Delete(int hole) { if (isEmpty()) { cout<<"Array Underflow"<<endl; return 0; } pTree keyItem = array[hole]; array[hole] = array[currentSize - 1]; currentSize--; percolateDown( hole ); return keyItem; } /* * Function to build heap */ void buildHeap() { for (int i = currentSize - 1 ; i >=1; i--) percolateDown(i); } /* * Function percolateDown */ void percolateDown(int hole) { int child; pTree tmp = array[hole]; for ( ; kthChild(hole, 1) < currentSize; hole = child) { child = smallestChild( hole ); if (array[child]->freq < tmp->freq) array[hole] = array[child]; else break; } array[hole] = tmp; } /* * Function to get smallest child from all valid indices */ int smallestChild(int hole) { int bestChildYet = kthChild(hole, 1); int k = 2; int candidateChild = kthChild(hole, k); while ((k <= d) && (candidateChild < currentSize)) { if (array[candidateChild]->freq < array[bestChildYet]->freq) bestChildYet = candidateChild; k++; candidateChild = kthChild(hole, k); } return bestChildYet; } /* * Function percolateUp */ void percolateUp(int hole) { pTree tmp = array[hole]; for (; hole > 1 && tmp->freq < array[parent(hole)]->freq; hole = parent(hole)) array[hole] = array[ parent(hole) ]; array[hole] = tmp; }};
在这里面,速度最慢的是配对堆,因为配对堆调整的算法需要进行一系列合并,相当于重建了一个堆。
这里是应用3种优先队列进行10次构建1000000个数据的huffman树所需的时间,总体而言,d路堆和最小堆的时间其实相差并不会特别多,因为都是在数组上进行操作。
这次的体会是,静态数组的速度远比动态数据结构要快很多,虽然会造成空间的浪费,但是时间相当客观
0 0
- C++实现优先队列——最小堆,d路堆及配对堆
- 优先队列及最小堆最大堆
- 优先队列及最大堆最小堆
- 优先队列及最小堆最大堆
- 优先队列及最小堆最大堆
- 优先队列及最小堆最大堆
- 最小优先队列--堆实现
- 最小堆及基于最小堆的最小优先队列
- 最小堆实现优先队列解决修理牧场(c/c++)
- 最小堆 / 优先队列(C语言实现)
- c语言最小堆的实现-优先队列
- 最小堆优先队列C++实现
- 用最小堆实现优先队列
- 简单优先队列实现-基于最小堆
- 优先队列(堆)——二叉堆的实现
- 堆与堆排序—优先队列
- 堆排序和优先队列【最小堆】
- 优先队列&&最小堆&&最大堆
- CPU卡程序设计实例(一)电路
- ubuntu 17.04 install openssl
- 揭秘Kafka高性能架构之道-Kafka设计解析(六)
- CPU卡程序设计实例(二)软件设计
- 记录自已学习之单链表(头插)
- C++实现优先队列——最小堆,d路堆及配对堆
- 记录自已学习之单链表(尾插)
- Currency Translation in Bex Query Variable 2
- Linux压缩与解压缩
- Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/cxf/frontend/ClientPro
- VI编辑器常用命令总结
- springmvc
- Tomcat启动 Unable to process Jar entry [javassist/XXXXXX.class]
- [BZOJ1079][SCOI2008]着色方案(记搜)