堆的实现及其初始化 c++支持循环更新
2018-01-06 15:34
288 查看
代码说明
实现基于数组,这里使用的不定长数组。编号从1开始,当然从数组0位开始也可以。
为了验证代码的可靠性,在main方法上方编写了测试器
支持操作
(基于模版类)
插入
得到最小值
删除(根)
层序输出
theta(n)复杂度的建树操作:
循环更新堆
删除指定节点
循环更新堆
说明
这里其实就是把插入和删除操作合并在一起了。
作为最小堆,如果更新的数值比之前小只需要与父亲们比较即可->不断上浮
如果更新的数值比之前大,只需要与大孩子不断比较->不断下沉。
template <class T> void minheap<T>::fresh(T target, T changer) { if (size == 0) return; for (int i = size; i >= 1; --i) { if (con[i] == target) { con[i] = con[i] + changer; if (changer < 0) //如果变小一定往上移动 { int lastnode = i; T lastelement = con[i]; while (lastnode > 1 && con[lastnode / 2] > lastelement) { //注意不能取1 con[lastnode] = con[lastnode / 2]; lastnode /= 2; } con[lastnode] = lastelement; } if (changer > 0) //如果变大就与孩子交换 { T lastelement = con[i]; int temp = i; int child = i * 2; while (child <= size) { if (child + 1 <= size && con[child + 1] < con[child]) child++; if (con[child] >= con[temp]) break; con[temp] = con[child]; temp = child; child *= 2; } con[temp] = lastelement; } } } }
复杂度O(n)的堆初始化方法
template <class T> void minheap<T>::initialize(vector<T> v) { if (v.size() == 0) return; for (int i = 0; i < v.size(); ++i) { if (i == 0) con.push_back(v[i]); con.push_back(v[i]); } this->size = v.size(); //下面进行调整 int tem = siz e93b e / 2; T lastelement = con[tem]; int child = tem * 2; while (tem >= 1) { while (child <= size) { if (child + 1 <= size && con[child + 1] < con[child]) child++; if (lastelement < con[child]) break; con[child / 2] = con[child]; child *= 2; } con[child / 2] = lastelement; tem--; child = tem * 2; lastelement = con[tem]; } }
测试器代码
void tester(minheap<int> & con,int num) { srand((int)time(0)); vector<int> vec; for (int x = 0; x < num; x++) { int a = random(100); con.push(a); vec.push_back(a); sort(vec.begin(), vec.end()); printf("data:%d\n", a); } for (int i = 0; i < num; ++i) cout << "quickly sort: " << vec[i] << endl; cout << "--" << endl; int counter = 0; while (!con.empty()) { if (con.top() == vec[counter]) cout << con.top() << "--" << vec[counter++]<<" yes"<<endl; else{ cout <<"算法存在错误!"<<endl; break; } con.pop(); } }
完整代码
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#define random(x) (rand()%x) //测试用代码
using namespace std;
template <class T>
class minheap
{
public:
minheap();
~minheap();
void pop();
T top();
void push(T element);
int getsize() {
return this->size;
}
void fresh(T target, T changer);
void initialize(vector <T> v);
bool empty() {
return size == 0;
}
void level_show();
vector<T> con; //从1开始使用不用0
private: //直接使用T本身作为优先级
int size;
void swap(T &a , T &b);
};
template<class T>
minheap<T>::minheap() {
con.clear();
size = 0;
}
template <class T> void minheap<T>::fresh(T target, T changer) { if (size == 0) return; for (int i = size; i >= 1; --i) { if (con[i] == target) { con[i] = con[i] + changer; if (changer < 0) //如果变小一定往上移动 { int lastnode = i; T lastelement = con[i]; while (lastnode > 1 && con[lastnode / 2] > lastelement) { //注意不能取1 con[lastnode] = con[lastnode / 2]; lastnode /= 2; } con[lastnode] = lastelement; } if (changer > 0) //如果变大就与孩子交换 { T lastelement = con[i]; int temp = i; int child = i * 2; while (child <= size) { if (child + 1 <= size && con[child + 1] < con[child]) child++; if (con[child] >= con[temp]) break; con[temp] = con[child]; temp = child; child *= 2; } con[temp] = lastelement; } } } }
template <class T>
T minheap<T>:: top() {
if (size == 0)
return 0;
else
return con[1];
}
template <class T>
void minheap<T>::pop() {
if (size == 0)
return;
if (size == 1)
{
size = 0;
return;
}
T lastelement = con[size];
size--;
int currentnode = 1;
int child = 2;
while (child <= size) {
if (child + 1 <= size && con[child] > con[child + 1])
child++; //首先找到大孩子
if (lastelement <= con[child])
break;
con[currentnode] = con[child];
currentnode = child;
child *= 2;
}
con[child / 2] = lastelement;
}
template<class T>
minheap<T>::~minheap() {
con.clear();
size = 0;
}
template <class T>
void minheap<T>::initialize(vector<T> v) {
if (v.size() == 0)
return;
for (int i = 0; i < v.size(); ++i)
{
if (i == 0)
con.push_back(v[i]);
con.push_back(v[i]);
}
this->size = v.size();
//下面进行调整
int tem = size / 2;
T lastelement = con[tem];
int child = tem * 2;
while (tem >= 1) {
while (child <= size) {
if (child + 1 <= size && con[child + 1] < con[child])
child++;
if (lastelement < con[child])
break;
con[child / 2] = con[child];
child *= 2;
}
con[child / 2] = lastelement;
tem--;
child = tem * 2;
lastelement = con[tem];
}
}
template <class T>
void minheap<T>::swap(T& a , T &b) {
T c = a;
a = b;
b = c;
}
template <class T>
void minheap<T>::push(T element) {
if (size == 0)
{
size = 1;
con.push_back(element);//因为我们不使用0位,我们从1位开始使用
con.push_back(element);//当然从0开始也是可以的
return;
}
con.push_back(element);
int pos = ++size;
while (pos > 1) {
if (element < con[pos / 2] )
swap(con[pos], con[pos / 2]);
pos /= 2;
}
}
template <class T>
void minheap<T>::level_show() {
if (con.empty())
return;
if (size == 1)
{
cout << con[1] << endl;
return;
}
queue<int> t;
t.push(1);
int temp;
while (!t.empty())
{
temp = t.front();
cout << con[temp] << " " ;
t.pop();
if (2 * temp <= size) //看左孩子
t.push(2 * temp);
if (2 * temp + 1 <= size) //看右孩子
t.push(2 * temp + 1);
}
cout << endl;
}
void tester(minheap<int> & con, int num) {
srand((int)time(0));
vector<int> vec;
for (int x = 0; x < num; x++) {
int a = x;
// con.push(a);
vec.push_back(a);
printf("data:%d\n", a);
}
con.initialize(vec); //使用初始化进行排序
cout << con.getsize() << endl;
sort(vec.begin(), vec.end());
for (int i = 0; i < num; ++i)
cout << "quickly sort: " << vec[i] << endl;
cout << "--" << endl;
int counter = 0;
while (!con.empty())
{
if (con.top() == vec[counter])
cout << con.top() << "--" << vec[counter++] << " yes" << endl;
else {
cout << "算法存在错误!" << endl;
break;
}
con.pop();
}
}
int main(int argc, char const * argv[])
{
minheap<int> mmp;
tester(mmp,10);
return 0;
}
相关文章推荐
- C++实现大正整数及其相关运算(长期更新)
- C++实现普通队列,循环队列的基本操作(初始化,入队,出队,获取队列首元素等)
- 循环顺序队列介绍及其C++实现
- 伪多态的循环链表C++实现【多类型支持】
- 双向循环链表插入算法的C++程序实现
- C++ 初始化函数的实现 - Ling Xu 的 C++ 技术随笔 - C++博客
- c++单循环实现二叉树的前,中,后序,层次遍历
- C/C++_atoi,itoa功能及其实现原理
- [置顶] bp神经网络原理及其c++实现
- C++实现堆排序并记录编程中遇到的一个bug(不要对无符号整形数在--的循环中采用>=0作为结束条件)
- 内存管理:算法及其c/c++实现 翻译六
- 详解C++中StringBuilder类的实现及其性能优化
- 在C++中实现foreach循环,比for_each更简洁!
- 双向循环链表的头插、中插、尾插、删除、逆序顺序显示(C++实现)
- 字符串左旋--循环移位法(c++实现)
- AVL树及其C++实现
- 基于http live streaming视频直播在android上的实现(版本更新,支持高清AAC视频)
- 单例模式(Singleton)及其C++实现
- JSPatch库, 一个Apple官方支持的实现在线更新iOS应用的库
- c++实现双向循环链表