1. 程式人生 > >堆(優先佇列,最大堆的基本操作,堆的例題)

堆(優先佇列,最大堆的基本操作,堆的例題)

1、堆(優先佇列):是一種特殊的“佇列”,取出元素的順序是
依照元素的優先權(關鍵字)大小,而不是元素進入佇列的先後順序。

2、堆的特性:
(1)結構性:用陣列表示的完全二叉樹(堆一定是完全二叉樹);

(2)有序性:任一結點的關鍵字是其子樹所有結點的最大值(或最小值)

“最大堆(MaxHeap)”,也稱“大頂堆”:任一結點的關鍵字是其子樹所有結點的最大值。
這是一個最大堆
“最小堆(MinHeap)”,也稱“小頂堆” :任一結點的關鍵字是其子樹所有結點的最小值。
這是一個最小堆

3、最大堆的基本操作:

!!!這裡主要講解最大堆,最小堆類似。這裡的所有操作都是建立在以下標為1開始儲存元素,下標為0的地方沒有儲存真實的元素
(1)、建立一個空的堆

#define MAXdata 10000
typedef struct Heap{
    int *a;
    int size;//當前元素個數 
    int maxsize;//最大儲存量 
}heap;
heap* creat_maxheap(int maxdata,heap* h)//建立一個最大容量為maxdata的空堆 
{
    h->a = (int *)malloc((maxdata + 1)*sizeof(int));
    //因為堆中元素是從下標為1的地方開始存放的,所以maxsize+1 
    h->maxsize = maxdata;
    h->size = 0
; h->a[0] = MAXdata;//定義哨兵為大於堆中所有元素的值 return h; }

(2)、判斷一個堆是否滿

int Isfull_maxheap(heap* h)//判斷最大堆是否滿 
{
    return h->maxsize == h->size;//若滿則返回1,未滿則返回0 
}

(3)、插入元素

void insert_maxheap(int x,heap* h)//向堆中插入一個元素 
{
    int i;
    if(Isfull_maxheap(h))
    {
        printf("最大堆已滿!\n");
        return
; } i = ++h->size;//i指向插入後堆中的最後一個元素的位置 for ( ; h->a[i/2] < x; i/=2 ) h->a[i] = h->a[i/2]; //上濾X h->a[i] = x; //將X插入 return ; }

(4)、判斷堆是否為空

int Isempty_maxheap(heap* h)
{
    return h->Size == 0;//若空則返回1,不空則返回0 
}

(5)、刪除堆中最大的元素並返回

int deletemax_heap(heap* h) 
// 從最大堆h中取出鍵值為最大的元素,並刪除一個結點 
{
    int parent,child;
    int maxdata,temp;
    if(Isempty_maxheap(h))
    {
        printf("最大堆以為空!\n");
        return 0;
    } 
    maxdata = h->a[1];//取出根結點最大值 
    //用最大堆中最後一個元素從根結點開始向上過濾下層結點
    temp = h->a[h->size--];
    //最開始用最後一個結點代替根結點,再交換順序使之成為堆 
    for(parent = 1;parent*2 <= h->size;parent = child)
    {
        child = parent*2;
        if((child != h->size) && (h->a[child] < h->a[child+1]))
        {
            child++;//child指向左右子結點的較大者
        }
        if(temp >= h->a[child])
        break;
        else
        h->a[parent] = h->a[child];//移動temp元素到下一層
    }
    h->a[parent] = temp;
    return maxdata;
}

(6)、簡單例題:將陣列存放為最大堆,再遍歷輸出,刪除最大元素後再遍歷刪除後的結果

#include <stdio.h>
#include <stdlib.h> 
#include <math.h>
#define MAXdata 10000
typedef struct Heap{
    int *a;
    int size;//當前元素個數 
    int maxsize;//最大儲存量 
}heap;
heap* creat_maxheap(int maxdata,heap* h)//建立一個最大容量為maxdata的空堆 
{
    h->a = (int *)malloc((maxdata + 1)*sizeof(int));
    //因為堆中元素是從下標為1的地方開始存放的,所以maxsize+1 
    h->maxsize = maxdata;
    h->size = 0 ;
    h->a[0] = MAXdata;//定義哨兵為大於堆中所有元素的值 
    return h; 
}
int Isfull_maxheap(heap* h)//判斷最大堆是否滿 
{
    return h->maxsize == h->size;//若滿則返回1,未滿則返回0 
}
void insert_maxheap(int x,heap* h)//向堆中插入一個元素 
{
    int i;
    if(Isfull_maxheap(h))
    {
        printf("最大堆已滿!\n");
        return ;
    }
    i = ++h->size;//i指向插入後堆中的最後一個元素的位置
    for ( ; h->a[i/2] < x; i/=2 )
        h->a[i] = h->a[i/2]; //上濾X 
    h->a[i] = x; //將X插入 
    return ;
} 
int Isempty_maxheap(heap* h)
{
    return h->size == 0;//若空則返回1,不空則返回0 
}

int deletemax_heap(heap* h) 
// 從最大堆h中取出鍵值為最大的元素,並刪除一個結點 
{
    int parent,child;
    int maxdata,temp;
    if(Isempty_maxheap(h))
    {
        printf("最大堆以為空!\n");
        return 0;
    } 
    maxdata = h->a[1];//取出根結點最大值 
    //用最大堆中最後一個元素從根結點開始向上過濾下層結點
    temp = h->a[h->size--];
    //最開始用最後一個結點代替根結點,再交換順序使之成為堆 
    for(parent = 1;parent*2 <= h->size;parent = child)
    {
        child = parent*2;
        if((child != h->size) && (h->a[child] < h->a[child+1]))
        {
            child++;//child指向左右子結點的較大者
        }
        if(temp >= h->a[child])
        break;
        else
        h->a[parent] = h->a[child];//移動temp元素到下一層
    }
    h->a[parent] = temp;
    return maxdata;
}
void print_maxheap(heap* h)
{
    int i;
    for (i=1; i<h->size+1; i++)
        printf("%d ", h->a[i]);
}
int main()
{
    int a[5] = {50,10,70,90,30};
    int i,len = 5;
    heap* h = (heap*)malloc(sizeof(heap));
    h = creat_maxheap(len,h);
    printf("依次新增:"); 
    for(i = 0;i<len;i++)
    {
        printf("%d ",a[i]);
        insert_maxheap(a[i],h);
    } 
    printf("\n最大堆:"); 
    print_maxheap(h);
    printf("\n刪除的元素:%d",deletemax_heap(h));
    printf("\n刪除元素後的最大推:");
    print_maxheap(h); 
} 

執行結果:
這裡寫圖片描述