堆的实现及其初始化 c++支持循环更新

代码说明

实现基于数组,这里使用的不定长数组。
编号从1开始,当然从数组0位开始也可以。
为了验证代码的可靠性,在main方法上方编写了测试器

支持操作

(基于模版类)
插入
得到最小值
删除(根)
层序输出
theta(n)复杂度的建树操作:
循环更新堆
删除指定节点

循环更新堆
说明

这里其实就是把插入和删除操作合并在一起了。
作为最小堆,如果更新的数值比之前小只需要与父亲们比较即可->不断上浮
如果更新的数值比之前大,只需要与大孩子不断比较->不断下沉。

template 
void minheap::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::initialize(vector 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];
    }
}
测试器代码
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"<else{
            cout <<"算法存在错误!"<break;
        }
        con.pop();
    }
}
完整代码
#include 
#include 
#include 
#include 
#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  v);
    bool empty() {
        return size == 0;
    }
    void level_show();
    vector con;      //从1开始使用不用0

private:                //直接使用T本身作为优先级
    int size;
    void swap(T &a , T &b);
};
template<class T>
minheap::minheap() {
    con.clear();
    size = 0;
}
template <class T>
void minheap::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:: top() {
    if (size == 0)
        return 0;
    else
        return con[1];
}
template <class T>
void minheap::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::~minheap() {
    con.clear();
    size = 0;
}
template <class T>
void minheap::initialize(vector 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::swap(T& a , T &b) {
    T c = a;
    a = b;
    b = c;
}
template <class T>
void minheap::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::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;
}

你可能感兴趣的:(acm)