【数据结构与算法分析】第六章 优先队列(堆)

【数据结构与算法分析】第六章 优先队列(堆)

一般来说,短的作业应尽可能快的结束,则已经被运行的作业当中这些短作业应拥有优先权,此外,有些作业虽不短小但也很重要,也应该拥有优先权。

1.模型

优先队列允许下列两种操作:

Insert(插入),等价于入队,即插入内容

DeleteMin(删除最小者),等价于出队,它的工作是找出、返回和删除优先队列中的最小元素。

2.二叉堆

二叉堆,堆的一种特殊的堆,一般用于实现优先队列,此节中将二叉堆称为堆

二叉堆的性质:结构性和堆序性

2.1结构性质

基本概念:

满二叉树:一棵被完全填满的二叉树

【数据结构与算法分析】第六章 优先队列(堆)_第1张图片

完全二叉树:若设二叉树的深度为h,除第h 层外,其它各层(1~h-1) 的结点数都达到最大个数,第h 层所有的结点都连续集中在最左边,这就是完全二叉树

【数据结构与算法分析】第六章 优先队列(堆)_第2张图片

注意:满二叉树是特殊的完全二叉树,二叉堆为满二叉树或完全二叉树

此完全二叉树的数组实现为:

  A B C D E F G H I J      
0 1 2 3 4 5 6 7 8 9 10 11 12 13

对于数组中任一位置i上的元素,其左儿子在位置2i上,右儿子在(2i+1)上,父亲在i/2上

优先队列的声明:

#ifndef _BinHeap_H
struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;
PriorityQueue Initialize(int MaxElements);
void Destroy(PriorityQueue H);
void MakeEmpty(PriorityQueue H);
void Insert(ElementType X,PriorityQueue H);
ElementType DeleteMin(PriorityQueue H);
ElementType FindMin(PriorityQueue H);
int IsEmpty(PriorityQueue H);
int Isfull(PriorityQueue H);
#endif
struct HeapStruct
{
    int Capacity;//最大值的整数
    int Size;//当前堆的大小
    ElementType *Elements;//一个数组
}

堆数据结构组成:

一个数组(不管关键字是什么类型),一个代表最大值的整数和当前堆的大小

2.2堆序性质

使操作被快速执行的性质是堆序性。

堆序性:在一个堆中,对于每一个节点X,X的父节点的关键字小于或等于X的关键字,根节点除外(无父节点),即父节点均小于或等于子节点

如图,只有左边为堆

【数据结构与算法分析】第六章 优先队列(堆)_第3张图片

创建一个优先队列:

PriorityQueue Inialize(int MaxElements)
{
    PriorityQueue H;
    if(MaxElements < MinPQSize)
        Error("queue size is too small");
    H=malloc(sizeof(struct HeapStruct));//分配堆的空间
    if(H==NULL)
        FatalError("out of space");
    H->Elements=malloc((MaxElements + 1)*sizeof(ElementType));//分配数组的空间,加1是设置哨兵防止出界
    if(H->Elements==NULL)
        FatalError("out of space");
    H->Capacity=MaxElements;
    H->Size=0;
    H->Elements[0]=MinData;
    return H;
}

2.3基本的堆操作

2.3.1 Insert插入

为将一个元素X插入到堆中,在下一个空闲位置创建一个空穴,否则该堆将不是完全树。如果X可以放在空穴中而并不破坏堆的序,那么插入成功。否则,我们把空穴的父节点上的元素移入该空穴,这样空穴就朝根的方向行一步

【数据结构与算法分析】第六章 优先队列(堆)_第4张图片

继续该过程直到X能被放入空穴中为止

【数据结构与算法分析】第六章 优先队列(堆)_第5张图片

插入到一个二叉堆的过程:

void Insert(ElementType X,PriorityQueue H)
{
    int i;
    if(IsFull(H))
    {
        Error("Priority queue is full");
        return;
    }
    for(i=++H->Size;H->Elements[i/2]>X;i/=2)
        H->Elements[i]=H->Elements[i/2];
    H->Elements[i]=X;
}

2.3.2DeleteMin(删除最小元)

(1)最小元在跟节点,删除后在根节点会产生一个空穴,由于现在堆少了一个元素,则堆最后一个元素X必须移到堆中的某个位置,如图

【数据结构与算法分析】第六章 优先队列(堆)_第6张图片

(2)将空穴的两子节点中较小者移入空穴,这样就把空穴向下推了一层,如图

【数据结构与算法分析】第六章 优先队列(堆)_第7张图片

(3)重复第二步,直到X能被放入空穴中

【数据结构与算法分析】第六章 优先队列(堆)_第8张图片

在二叉堆中执行DeleteMin的函数:

ElementType DeleteMin(PriorityQueue H)
{
    int i,child;
    ElementType MinElement,LastElement;
    if(IsEmpty(H))
    {
        Error("Priority queue is empty");
        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]Elements[child])
            child++;
        if(LastElement>H->Elements[child])
            H->Elements[i]=H->Elements[child];
        else
            break;
    }
    H->Elements[i]=LastElement;
    return MinElement;
}

 

 

 

 

 

 

 

 

 

 

 

 

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