堆的实现(优先级队列的基础)

1.概览

  • 由于堆是一棵完全二叉树,所以可以使用vector存储数据
  • (0位置不放数据) 任意节点i,其左儿子为2i,其右儿子为2i+1,其父亲为i/2(下取整)
  • 堆算法主要包含三个:插入(上滤操作)、删除(下滤操作)、建堆(循环下滤操作)

2.上滤即插入的过程

  • 主要思想:当要插入元素x时,在最后的位置建立一个空穴,判断该空穴是否能放下x,若不能,则上滤空穴(即将父亲的值填入空穴,而将父亲作为新的空穴)持续上述过程,直到找到合适位置
void insert(ElementType& x,priorityQueue H)
{
    int i;
    //处理heap空间不足的情况
    for(int i=++H->size;H->Elements[i/2]>x;i/=2)
        H->Elements[i]=H->Elements[i/2];
    H->Elements[i]=x;
}

3.下滤,即删除过程

  • 主要思想:heap值允许删顶部的元素,删除过程为,将根节点设为空穴,现在的目的是要给最底层最右侧(最后一个元素)找到一个合适的位置。将最后一个值与空穴的儿子中较大/小的一个(视最大堆、最小堆情况而定)比较,若能放下最后一个元素,则结束;否则,将空穴下滤,直至找到合适位置
ElementType DeleteMin(PriorityQueue H)
{
    int i,child;
    ElementType MinElement,LastElement;
    if(IsEmpty(H))
    {
        return H->Elements[0];
    }
    MinElement=H->Elements[1];
    LastElement=H->Elements[H->size--];
    
    //下滤过程
    for(i=1;i*2<=H->size;i=child)
    {
        child=i*2;
        if(child!=H->size && H->Elements[child+1]<H->Elements[child])
            child++;
        if(LastElement>H->Elements[child])
            H->Elements[i]=H->Elements[child];
        else
            break;
    }
    H->Elements[i]=LastElements;
    return MinElements;
}

4. 建堆

  • 主要思想:先将所有数据填入vector中,从size/2的位置开始,将自身视为空穴,开始下滤操作
...
ElementType copy;
for(int i=H->size/2;i>0;--i)
{
    //空穴位置为i ,待放入的值为copy
    copy=H->Elements[i];
     //下滤过程
     int j;
    for(j=i;j*2<=H->size;j=child)
    {
        child=j*2;
        if(child!=H->size && H->Elements[child+1]<H->Elements[child])
            child++;
        if(LastElement>H->Elements[child])
            H->Elements[j]=H->Elements[child];
        else
            break;
    }
    H->Elements[j]=copy;
}

4.堆排序

  • 先将待排序序列放入vector中
  • 使用建堆算法,建立一个最小/大堆
  • 依次删除根节点元素,并非真的删除,而是将其放在当前队列的最末端,并堆的大小减一,之后调整堆的结构,继续执行此步骤
  • 直至堆的大小为0,排序完成

你可能感兴趣的:(算法)