数据结构之堆结构

核心:堆树

堆的定义:

1. 堆是一颗完全二叉树

2. 满足每个结点的值总是大于等于(或者小于等于)其左右孩子的数值

3. 堆中的子树都是堆树

简而言之,堆是一颗完全二叉树,且子树都是父节点的值大于等于左右孩子的值。

数组表示的话,因为完全二叉树的特点,下标得到确定父节点的索引为i(i>=1),则左右孩子为2i和2i+1;

又因为子树都是堆树,则array[i] >= max(array[2*i], array[2*i + 1]);这样根据堆的结构我们就确定了堆的数据结构表示

 

 堆的数据结构

struct MaxHeap
{
    EType *heap; //存放数据的空间,下标从1开始存储数据,下标为0的作为存储临时数据。
    int MaxSize; //MaxSize是存放数据元素空间的最大的个数
    int HeapSize; //HeapSize是数据元素的实际个数
};
MaxHeap H;

注意: 在完全二叉树中,若当前节点的下标为 i, 则其父节点的下标为 i/2,其左子节点的下标为 i*2,其右子节点的下标为i*2+1;

1.构建最大堆

基本思想:初始化的序列是不满足堆的特性的,故需要进行调整。

首先将每个叶子结点视为一个堆树,再将每个叶子结点和其父节点一起构成一个包含更多结点的堆。

所以在构造堆的时候,首先需要找到最后一个结点的父节点,从这个节点开始构造最大堆,直到该节点后面的所有分支节点都处理完毕。

从最后的一个叶子结点的父节点开始向上进行遍历,直到根节点结束;每次遍历的时候都要对该结点的整颗子树进行向下遍历,直到直到整棵树到叶子结点。

void MaxHeapInit(MaxHeap &H)
{
    for(int i=H.HeapSize/2;i>=1;i--)//向上进行遍历,直到根节点
    {
        H.heap[0]=H.heap[i];
        int son=i*2;
        while(son<H.HeapSize)
        {
            if(son<H.HeapSize&&H.heap[son]<H.heap[son+1])
                son++;
            if(H.heap[i]>H.heap[son])
                break;
            else if(son<H.heapSize&&H.heap[son]>H.heap[son+1]
                {
                    H.heap[son/2]=H.heap[son];
                    son*=2; //向下遍历,直到叶子节点
                }
        }
        H.heap[son/2]=H.heap[0];
    }
}

 

2.最大堆中插入结点

因为最大堆的结构特性已经确定(即,看做有序的,满足堆的特性),所以插入的结点默认放到最后一个位置,保持完全二叉树的特性,继而是对堆中位置的调整。

自下而上地利用结构特性进行调整。因为和堆树的根节点即这棵树的最大值进行比较,所以交换后不会破坏结构,不用像构造的时候一直进行调整。

void MaxHeapInsert(MaxHeap &H, EType &x)
{
    if(H.HeapSize==H.MaxSize) return false;
    
    int i=++H.HeapSize;
    while(i!=1&&x>H.heap[i/2])
    {
        H.heap[i]=H.heap[i/2];
        i/=2;
    }
    H.heap[i]=x;
    return true;
}

3. 最大堆中删除结点

删除的肯定是最大元素,即根节点。 

将最大堆的最后一个节点放到根节点,然后删除最大值,然后再把新的根节点放到合适的位置。

自上而下地利用结构特性进行调整

void MaxHeapDelete(MaxHeap &H, EType &x)
{
    if(H.HeapSize==0) return false;
    x=H.heap[1];
    H.heap[0]=H.heap[H.HeapSize--];
    int i=1, son=i*2;
     while(son<H.HeapSize)
        {
            if(son<H.HeapSize&&H.heap[son]<H.heap[son+1])
                son++;
            if(H.heap[i]>H.heap[son])
                break;
             H.heao[i]=H.heap[son];
            i=son;
            son*=2;
        }
        H.heap[i]=H.heap[0];
    return true;
    
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值