您的位置:首页 > 编程语言 > C语言/C++

堆的实现及其初始化 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: