二叉堆的插入删除等操作C++实现
来源:互联网 发布:浮云淘宝小号 编辑:程序博客网 时间:2024/05/21 15:43
有几种明显的方法实现优先队列:
1. 使用简单链表在表头以O(1)执行插入操作,遍历该链表需要O(N)。另一方法是始终保持表有序,插入操作代价为O(N),deleteMin花费为O(1)。
2. 使用二叉查找树。插入、删除操作平均时间均为O(logN)。实现优先队列要删除最小元素,那么将会不断在左子树中删除,会损害树的平衡,会使右子树加重。这样,在最坏情况下,左子树为空,则树相当于链表,这样其操作的时间界限就会变为最坏情况。另外,查找树实现有些过分,因为它支持大量并不需要的操作。
二叉堆是实现优先队列的常见方法。它是完全二叉树,有规律可循,因此可用数组实现而不使用链表。如果从数组的下标为1的位置开始存元素(下标0处不存),那么数组中某位置i上的元素,其左孩子在位置2i,右孩子在2i+1位置上。
要快速找到最小值,则使用小根堆,根元素最小。
由于二叉堆是完全二叉树,因此其高度为不大于logN的最大整数。插入操作、删除操作的最坏时间为O(logN),平均时间为O(logN)。
以下代码以vector容器为基本数组实现小根堆,使用泛型编程实现:
这里用到了泛型编程,对于泛型编程有注意的地方,参考《泛型编程注意不能将模板类的成员函数放在独立的实现文件中》。
删除堆的过程就是要下滤的。
而堆排序用到了删除堆的操作,因此,堆排序也是要下滤的。
对任意输入序列建立堆也要下滤,因为该过程就是一系列元素排序的过程。
//6heap.h#ifndef TEST_HEAP_H#define TEST_HEAP_H#include "test.h"/*这里建立的是小根堆,元素存在vector容器中,根从下标为1的元素开始*/template <typename T>class BinaryHeap {public: explicit BinaryHeap(int capacity = 100) :array(capacity + 1), current_size(0) {} explicit BinaryHeap(const vector<T>& items) :array(items.size() + 10), current_size(items.size()) { int i; for (i = 0; i < items.size(); i++) array[i + 1] = items[i]; BuildHeap(); } bool IsEmpty() const { return current_size == 0; } const T& FindMin() const { if (IsEmpty()) cout << "No items in binary heap" << endl; return array[1]; } /* 堆的插入操作是“上滤”的过程。最坏时间为O(logN),平均时间为O(logN)。 先在堆的下一个空闲位置上建立一个空穴,如果这样不破坏堆的性质,那么插入完成。 否则,将空穴父节点的元素移入空穴,这样空穴上升了一层,到达父节点的位置。 继续该过程,直到插入值可以放入空穴为止。 */ void Insert(const T& value) { if (current_size == array.size() - 1) //空间不够,重分配 array.resize(array.size() * 2); int hole = ++current_size; //在堆的下一个空闲位置建立一个空穴 /* 在空穴没上滤到根部并且插入值小于空穴父节点时, 将父节点移入空穴,空穴位置上升一层 */ for ( ; hole > 1 && value < array[hole / 2]; hole /= 2) array[hole] = array[hole / 2]; array[hole] = value; //将值插入到合适位置 } /* 删除操作最坏时间为O(logN),平均时间为O(logN)。 删除最小值时,根成空穴,且堆要少一个元素, 因此原堆的最后一个元素X将要放到堆的某个位置; 如果X可以放到空穴中则完成;否则要将空穴的儿子中较小的元素放入空穴,空穴 下移,重复该过程直到X可以放入空穴。 */ void DeleteMin() { if (IsEmpty()) cout << "No items in binary heap" << endl; array[1] = array[current_size--]; PercolateDown(1); } void DeleteMin(T& min_item) { if (IsEmpty()) cout << "No items in binary heap" << endl; min_item = array[1]; array[1] = array[current_size--]; PercolateDown(1); } void MakeEmpty() { current_size = 0; } void PrintItems() { cout << "Items: "; int i = 1; while (i <= current_size) { cout << array[i++] << " "; } cout << endl; }private: int current_size; vector<T> array; /* 建立堆的操作最坏时间为O(NlogN),平均时间为O(N) 建立堆的过程就是堆排序的过程 */ void BuildHeap() { int i; for (i = current_size / 2; i > 0; i--) PercolateDown(i); } /* 该函数完成“下滤”过程。 删除堆的过程就是要下滤的。 而堆排序用到了删除堆的操作,因此,堆排序也是要下滤的。 对任意输入序列建立堆也要下滤。 该函数的做法是将插入值置入沿着从根开始 包含最小儿子的一条路径上的正确位置 */ void PercolateDown(int hole) { int pos_child; T tmp = array[hole]; //当空穴位置没有到达堆的尾部前,循环向下层找空穴位置 for ( ; hole * 2 <= current_size; hole = pos_child) { pos_child = 2 * hole; /* 下边语句是要将较小孩子的下标移入空穴,将空穴移入下一层。 下边的pos_child != current_size条件是控制当堆的节点为偶数时情况, 当堆节点为偶数时,最后一个非叶节点只有一个左孩子,则此时要找的 较小孩子的下标就是左孩子的下标,即不用执行下边第一个if */ if (pos_child != current_size && array[pos_child + 1] < array[pos_child]) pos_child++; if (array[pos_child] < tmp) //如果较小孩子比父节点小,则空穴下移一层 array[hole] = array[pos_child]; else break; } array[hole] = tmp; }};#endif
//test.cpp#include "6heap.h"int main() { BinaryHeap<int> heap; heap.Insert(22); heap.Insert(12); heap.Insert(7); heap.Insert(1); heap.PrintItems(); vector<double> dvec; int i; for (i = 10; i > 0; --i) dvec.push_back(i); BinaryHeap<double> dheap(dvec); dheap.PrintItems(); heap.DeleteMin(); heap.PrintItems(); dheap.DeleteMin(); dheap.DeleteMin(); dheap.PrintItems(); return 0;}
0 0
- 二叉堆的插入删除等操作C++实现
- 二叉查找树的查找、插入、删除、释放等基本操作的实现(C语言)
- 二叉堆初始化、插入、删去等操作。
- 最大堆的初始化、删除、插入等基本操作
- java实现堆的操作(建堆,插入,删除)
- 二叉搜索树的插入、查找、删除等操作
- 平衡二叉树的 插入 删除 查找 等功能c语言实现 数据结构
- c语言实现单链表的操作:创建,删除,插入,反转, 排序等
- C语言实现顺序表的插入、删除、查找、遍历等基本操作
- 顺序链表的插入删除等操作 C语言
- 二叉平衡树AVL插入删除操作的实现
- c++ 实现结构体单链表的 创建 插入 删除等操作
- 双链表的实现以及插入删除等操作
- 平衡二叉树(遍历,插入,删除)的C实现
- 堆排序及堆的插入,删除等
- c语言:顺序表的实现(一) 创建,插入,删除,查找,输出等基本操作实现
- 二叉堆(插入,删除)
- Treap堆的插入,删除操作
- 利用AsyncHttpClient实现图片的上传与下载
- 一个很多资料的FTP服务器
- Java学习之位运算符
- android 如何修改自定义dialog的宽度
- android onNewIntent
- 二叉堆的插入删除等操作C++实现
- 使用Eclipse远程调试Tomcat
- CSS 基础和高级的指南或资源
- SharePoint安全 - SharePoint网站常用页面URL索引
- Vim简单的查找替换
- Spring容器和被管理的Bean
- not in与not exists的区别
- onCreateOptionsMenu 和onOptionsItemSelectedu
- poj-1703 find them,catch them!