数据结构 堆树(最大堆、最小堆)

一、堆树的定义

(1)堆树是一颗完全二叉树
(2)堆树中某个节点的值总是不大于或不小于其孩子节点的值
(3)堆树中每个节点的子树都是堆树
当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆,也称大根堆
当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆,也称小根堆
如下图所示,上边为最大堆,下边为最小堆。
数据结构 堆树(最大堆、最小堆)_第1张图片
数据结构 堆树(最大堆、最小堆)_第2张图片

二、堆树的操作

下面以最大堆为例进行讲解,最小堆同理。

2.1 堆树的存储

数据结构 堆树(最大堆、最小堆)_第3张图片

对上面的堆树采用顺序存储方式,对应的堆树数组为heap[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7}

由于是按堆树顺序存储的所以在数组中父节点跟子节点的关系是两倍的关系:

heap[father*2]=heap[leftChild];
heap[father*2+1]=heap[rightChild]

2.2 构造最大堆

在构造堆的基本思想就是:首先将每个叶子节点视为一个堆,再将每个叶子节点与其父节点一起构造成一个包含更多节点的堆。
所以,在构造堆的时候,首先需要找到最后一个节点的父节点,从这个节点开始构造最大堆;直到该节点前面所有分支节点都处理完毕,这样最大堆就构造完毕了。
假设树的节点个数为n,以1为下标开始编号,直到n结束。对于节点i,其父节点为i/2;左孩子节点为i2,右孩子节点为i2+1。最后一个节点的下标为n,其父节点的下标为n/2。

如下图所示,最后一个节点为7,其父节点为16,从16这个节点开始构造最大堆;构造完毕之后,转移到下一个父节点2,直到所有父节点都构造完毕。
数据结构 堆树(最大堆、最小堆)_第4张图片

构造最大堆的C/C++代码如下:

void Swap(int arr[], int i, int j)
{
    int temp=arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

/**
* 将父节点为aar[i]的子树调整为最大堆
* @param arr 堆数组
* @param size 堆数组长度
* @param i 节点索引
*/
void AdjustHeap(int arr[],int size,int i)
{
    int left_child = 2*i+1;    //左子节点索引
    int right_child = 2*i+2;   //右子节点索引
    int max = i;               //选出当前结点与其左右孩子三者之中的最大值
    if (left_child < size && arr[left_child] > arr[max]) {
        max = left_child;
    }

    if (right_child < size && arr[right_child] > arr[max]) {
        max = right_child;
    }

    if (max != i) {
        Swap(arr, i, max);    //将最大值节点与父节点互换
        AdjustHeap(arr, size, max); //递归调用,继续从当前节点向下进行堆调整
    }
}

/**
* 根据输入的数组构建一个最大堆
* @param arr 堆数组
* @param size 堆数组长度
* @return 堆数组长度
*/
int BuildMaxHeap(int arr[], int size) {
    //对每一个非叶节点开始向下进行最大堆调整
    for (int i = size / 2 - 1; i >= 0; i--)
    {
        AdjustHeap(arr, size, i);
    }
    return size;
}

2.3 最大堆中插入节点

首先在堆的最后添加一个节点,然后沿着堆树上升,直到堆树再次调整为最大堆。

/**
* 向指定的最大堆中插入节点
* @param arr
* @param size
* @param data
* @return
*/
int MaxHeapInsert(int arr[], int size,int data)
{
    int index=size;
    while (index>0 && data>arr[(index-1)/2])
    {
        arr[index]=arr[(index-1)/2];
        index=(index-1)/2;
    }
    arr[index]=data;
    return (size+1);
}

2.4 最大堆中任意节点的删除

将堆树中待删除的节点A与堆树中的最后一个节点B互换,然后调整节点B到合适的位置,最后从堆树中删除排在堆数组最后的节点A。

/**
* 最大堆堆顶节点的删除
* @param arr 最大堆数组
* @param size 堆数组长度
* @param index 待删除的节点
* @return 删除后的堆数组长度
*/
int MaxHeapDelete(int arr[], int size)
{
    if(size<=0)return -1;
    Swap(arr, 0, size - 1);
    AdjustHeap(arr,size-1,0);//调整堆为最大堆
    return size-1;
}

参考:https://blog.csdn.net/chengde6896383/article/details/81121113


你可能感兴趣的:(数据结构)