二叉堆 筆記

二叉堆是一個完全二叉樹,他的父節點永遠小於子節點。

操作:

1. 查詢集合內的最小值

2. 刪除集合內的最小值

3. 插入一個元素

4. 減小集合中已經存在的元素的值

出了查詢操作是O(1), 其他都是O(logn)

二叉堆是隱式數據結構,他可以利用數組實現。

我們可以利用二叉樹的特性來實現,假設 i 為父節點的下標,那麼左兒子的下標就在i * 2,右兒子則是i * 2 + 1,那麼如果我想找一個節點的父親,就把該節點的下標除2。

代碼:

constexpr int N = 1000010;
int heap[N], top = 1;

插入元素:

void upMaintain(int now){
    while(now > 1){
        int parent = now / 2; //find father node
        if(heap[now] < heap[parent]){
            swap(heap[now], heap[parent];
            now = parent;
        }else break;
    }
}
void push(int x){
    ++top;
    heap[top - 1] = x;
    upMaintain(top - 1);
}

刪除元素:

void pop(){
    --top;
    swap(heap[1], heap[top]); // swap root and leaf
    downMaintain(1);
}
void downMaintain(int now){
    while(true){
        int leftChild = now * 2;
        int rightChild = leftChild + 1;
        int minNode = now;
        if(leftChild < top && heap[leftChild] < heap[minNode]){
            minNode = leftChild;
        }
        if(rightChild < top && heap[rightChild] < heap[minNode]){
            minNode = rightChild;
        }
        if(minNode == now)break;
        swap(heap[now], heap[minNode]);
        now = minNode;
    }
}

修改元素:

void update(int pos, int x){
    bool decrease = x < heap[pos];
    heap[pos] = x;
    if(decrease){
        upMaintain(pos);
    }
    else downMaintain(pos);
}

利用struct 實現:

#include<iostream>
using namespace std;
struct binaryHeap{
    const int N = 1000010;
    int heap[N], top = 1;
    
    //insert element
    void push(int x){
        ++top;
        heap[top - 1] = x;
        upMaintain(top - 1);
    }
    void upMaintain(int now){
        while(now > 1){
            int parent = now / 2;
            if(heap[parent] > heap[now]){
                swap(heap[parent], heap[now]);
                now = parent;
            }else break;
        }
    }
    //void delete element
    void pop(int x){
        --top;
        swap(heap[1], heap[top + 1]);
        downMaintain(1);
    }
    void downMaintain(int now){
        while(true){
            int leftChild = now * 2;
            int rightChild = leftChild + 1;
            int minNode = now;
            if(leftChild < top && heap[leftChild] < heap[minNode]){
                minNode = leftChild;
            }
            if(rightChild < top && heap[rightChild] < heap[minNode]){
                minNode = rightChild;
            }
            if(minNode == now)break;
            swap(heap[now], heap[minNode]);
            now = minNode;
        }
    }
    // update
    void update(int pos, int x){
        bool decrease = x < heap[pos];
        heap[pos] = x;
        if(decrease)upMaintain(pos);
        else downMaintain(pos);
    }
    //get minimum element
    int getMin(){
        return heap[1];
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值