大根堆和小根堆

1 篇文章 0 订阅

        在很多语言中,都有优先队列或者堆的的容器可以直接使用去创建大根堆或小根堆。但是在面试中,面试官更倾向于让更面试者自己实现一个堆。所以建议大家掌握堆的实现方法,尤其要搞懂「建堆」、「调整」和「删除」的过程。

优先队列

//less 表示按照递减插入元素
priority_queue<int, vector<int>, less<int>> s;

//greater 表示按照递增插入元素
priority_queue<int, vector<int>, greater<int>> s;

实现堆的方法:

ps:在看代码之前,要确保自己能演算大根堆和小根堆的实现过程。这样才好理解代码

大根堆

// i 为第一个非叶子节点的下标
void MaxHeapify(vector<int> &a,int i, int heapsize)
{
    //l为i的左孩子 r为i的右孩子 largest是中间变量与左右孩子进行比较
    int l = i*2+1, r = i*2+2, largest = i;
    if(l < heapsize && a[l] > a[largest])
        largest = l;
    if(r < heapsize && a[r] > a[largest])
        largest = r;
    //如果largest与原来i相比发生了变化,则进行调整
    if(largest != i)
    {
        swap(a[i], a[largest]);
        MaxHeapify(a,largest,heapsize);
    }
}

//构建大根堆 从最后一个非叶子节点向上
void buildMaxHeap(vector<int>& a, int heapsize)
{
    for(int i = heapsize/2;i >= 0;--i)
        MaxHeapify(a,i,heapsize);

    //这下面是根据题目的需求添加或省略
    for(int i = heapsize-1; i >= 1;i--)
    {
        //将当前最大的放置到数组末尾
        swap(a[0],a[i]);
        //将未完成的排序部分继续进行堆排序
        MaxHeapify(a,0,i);
    }
}

int main()
{   
    vector<int> a = {输入一组序列};
    buildMaxHeap(a,a.size());
    for(int i=0;i < a.size();i++)
    {
        cout<<a[i]<<'  ';
    }
    return 0;
}

小根堆

    void MinHeapify(vector<int>&a,int i,int heapsize)
    {
        //找到当前节点的左孩子
        int l = 2*i+1;
        int temp = a[i];
        while(l < heapsize)
        {
            //确保与父节点交换的是最大的孩子
            if(l+1<heapsize && a[l] < a[l+1]) ++l;
            if(temp > a[l]) break;
            else{
                a[i] = a[l];
                i = l;
                l = 2*i+1;
            }
        }
        a[i] = temp;
    }

    void buildMaxHeap(vector<int>& a, int heapsize)
    {
        for(int i = heapsize/2-1;i >= 0;--i)
            MinHeapify(a,i,heapsize);

        for(int i = n-1; i>= 1; --i)
        {
            swap(a[0], a[i]);
            MinHeapify(a,0,i);
        }
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值