【数据结构】堆结构小根堆,大根堆,插入,删除等操作的实现

一、堆的基本概念

【含义】:如果有一个关键码的集合K={k0,k1,k2, … ,k(n-1)},把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足:ki <= k2*i+1 且 ki <= k2*i+2(ki >= k2*i+1 且 ki >= k2*i+2 )i=0,1,2 … ,则称这个堆为最小堆(或最大堆)。

这里写图片描述

【最小堆】:任一节点的关键码均小于等于它的左右孩子的关键码,位于堆顶节点的关键码最小。

【最大堆】:任一节点的关键码均大小于等于它的左右孩子的关键码,位于堆顶节点的关键码最大。

【堆序】:在堆中,所有的记录具有称之为堆序的关系。

【堆的规律】:

  • 具有最小堆序的节点(除没有孩子的节点)之间存在小于或等于关系,从根节点到每个节点的路径上数组元素组成的序列都是递增的。
  • 具有最大堆序的节点(除没有孩子的节点)之间存在大于或等于关系,从根节点到每个节点的路径上数组元素组成的序列都是递减的。

堆存储在下标为0开始计数的数组中,因此在堆中给定下标为i的节点时:

  1. 如果i=0,节点i是根节点,没有双亲节点;否则节点i的双亲节点为节点(i-1)/2;
  2. 如果2*i+1 > n-1,则节点i无左孩子,否则节点i的左孩子为节点2*i+1;
  3. 如果2*i+2 > n-1,则节点i无右孩子,否则节点i的右孩子为节点2*i+2;

二、堆的创建&插入&删除

源码:

Heap.h

#pragma once
#ifndef __HEAP_H__
#define __HEAP_H__
#include<iostream>
#include<vector>


using namespace std;

template<class T>
class Less
{
public:
    bool operator()(T& left, T& right){
        return left < right;
    }
};

template<class T>
class Greater
{
public:
    bool operator()(T& left, T& right){
        return left>right;
    }
};

template<class T,class Compare = Greater<T>>
class Heap
{
public:
    //无参构造
    Heap()
    {}
    //带参构造
    Heap(T* arr, const T size){
        _v.reserve(size);
        for (int i = 0; i < size; ++i){
            _v.push_back(arr[i]);
        }
        //建堆
        for (int j = (_v.size() - 2) >> 1; j >= 0; --j){
            //向下调整
            _AdjustDown(j);
        }
    }

    void Push(const T& data){
        _v.push_back(data);
        _AdjustUp(_v.size() - 1);
    }

    void Pop(){
        //交换堆顶元素与堆底元素
        size_t size = _v.size();
        swap(_v[0], _v[size - 1]);
        //删除堆底元素
        _v.pop_back();
        //向下调整
        _AdjustDown(0);
    }

    size_t Size(){
        return _v.size();
    }

    bool Empty(){
        return _v.empty();
    }

    //打印堆
    void Print(){
        for (size_t i = 0; i < _v.size(); ++i){
            cout << _v[i] << "  ";
        }
        cout << endl;
    }

    T Top()const
    {
        return _v.front();
    }

    T Back()const
    {
        return _v.back();
    }

    //析构
    ~Heap(){
        _v.~vector();
    }

protected:
    //向下调整
    void _AdjustDown(size_t root){
        size_t parent = root;
        size_t min_child = parent * 2 + 1;
        while (min_child < _v.size()){
            if ((min_child + 1 < _v.size()) && (Compare()(_v[min_child + 1],_v[min_child])))
                min_child += 1;
            if (Compare()(_v[min_child],_v[parent])){
                swap(_v[parent], _v[min_child]);
                parent = min_child;
                min_child = parent * 2 + 1;
            }
            else{
                break;
            }
        }
    }

    //向上调整
    void _AdjustUp(size_t index){
        size_t child = index;
        size_t parent = (child - 1) >> 1;
        while (child){
            if (Compare()(_v[parent],_v[child])){
                break;
            }
            else{
                swap(_v[parent], _v[child]);
                child = parent;
                parent = (child - 1) >> 1;
            }
        }
    }

private:
    vector<T> _v;
};


#endif //__HEAP_H__

test.cpp

#include"Heap.h"
#include<iostream>
#include<stdio.h>
#include<Windows.h>
using namespace std;

void test(){
    int arr[] = { 53, 17, 78, 9, 45, 65, 87, 23 };
    Heap<int,Less<int>> hp(arr, sizeof(arr) / sizeof(arr[0]));
    //此处传的是小堆Less<int>,若要大堆可传Greater<int>
    hp.Push(80);
    hp.Pop();
    cout << hp.Size() << endl;
    cout << hp.Front() << endl;
    cout << hp.Back() << endl;
}

int main(){
    test();
    system("pause");
    return 0;
}

程序运行结果:

【说明】:测试例子用的是小堆,大堆同理。

建堆:

这里写图片描述

插入元素:

这里写图片描述

删除元素:

这里写图片描述

堆元素的个数&堆头元素&堆尾元素

这里写图片描述


三、堆的应用:

优先级队列:

优先级队列实现源码

topK(海量数据处理):

topK 实现源码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值