双堆DEAP

记录一道遇到的考研真题

特性分析

DEAP为一颗完全二叉树,左子树小堆,右子树大堆,故左右子树分别可以用l[]、r[]数组存储,用m和n分别表示当前两完全二叉树的结点,左右子树高度差为1,且左子树的高度始终大于等于右子树的高度。

插入情况

当均为空二叉树或者满二叉树(m=2k-1)应该插入到小堆;小堆满后,插入到大堆。即在小堆插入要满足:

否则就要插入到大堆。

调堆情况

在小堆m处插入节点x后,若x的值不大于大堆的m/2节点的值,则在小堆调整。否则,节点x与大堆的m/2结点交换,然后进行大堆调堆。在大堆n处插入结点x后,若x不小于小堆的n结点,则在大堆调整。否则,结点x与小堆的n结点交换,然后进行小堆调堆。

(1)插入4后

4先插入大堆,4<小堆中对应的19,和19交换。之后开始调整小堆即可。大堆显然无需调整。

(2)插入代码(有点乱,建议文字屡清楚思路)

//l[]为小堆,r[]为大堆,m、n分别为两个堆的元素个数,x为待插入元素
void insertDEPA(int l[],int r[],m,n,x)
{
  if(m>=n && m!=2^k-1 && [log2m]-[log2n]<=1) //[]这里暂时代表向下取整,k为二叉树高度
  {
      m++;
      if(x>r[m/2]) //交换
      {
          l[m]=r[m/2];
          c=m/2;
          f=c/2;
          while(f>0 && r[f]<x) //调大堆
          {
              r[c]=r[f];
              c=f;
              f=c/2;
          }
          r[c]=x;
      }
      else //调小堆
      {
        c=m;
        f=c/2;
        while(f>0 && l[f]>x)
        {
            l[c]=l[f];
            c=f;
            f=c/2;
        }
        l[c]=x;
      }
      else //调大堆
      {
            c=n;
            f=c/2;
            while(f>0 && r[f]<x)
            {
              r[c]=r[f];
              c=f;
              f=c/2;
            }
            r[c]=x;
      }
  }
}
原文地址:https://www.cnblogs.com/wangzheming35/p/13629233.html