數據結構 二叉堆 數組實現

堆還是比較常用的數據結構

二叉堆也就是以二叉樹形式構造的堆

我們知道二叉樹可以用數組很方便的實現

所以用數組實現二叉堆也不是很難的事情

首先我們來了解一下二叉堆的性質:非葉子節點的值均不大於(或不小於)其左右孩子的值

如果用二叉堆用數組來實現就是n個元素{k1,k2,k3,...,kn}

ki<=k(2*i)&&ki<=k(2*i+1)  或者 ki>=k(2*i)&&ki>=k(2*i+1)    其中(i=1,2,...,n/2);

如此我們就能很方便的在數組上實現根節點和孩子節點的比較

堆中插入元素,插入元素之後還需要保持堆的性質

堆中取元素的時候一般都是取得堆中最大或者最小的元素

這時我們就可以使用大頂堆來維護取最大值,小頂堆來維護取最小值

堆中取出元素時也需要繼續維護堆的性質


以小頂堆的數組 實現爲例

插入元素:

1.從堆末尾插入元素

2.比較和其父節點元素的大小

    2.1.比父節點小,對元素和父節點的元素執行交換操作,

    2.2.比父節點大,結束

3.重複2直到根節點


取出最小元素:

1.取出堆的根節點

2.取出堆的最後一個元素插入到根節點

3.比較根節點和左右孩子的大小

   3.1.比左右孩子都大,結束

   3.2.只比一個大,交換根節點元素和孩子節點元素

   3.3.比兩個都大,和最小的那個孩子節點交換

4.重複3直到結束,返回1取出的根節點


下面實現一個小頂堆來維護取最小值。

#include<stdlib.h>
#include<stdio.h>
int heap[1000];//定義堆的大小
int end=0;//指向堆中的最後一個元素並且標記元素的個數

void insert(int a){
    int e,p,tmp;//e最後一個元素在數組的位置,p爲e的父節點。
    heap[++end]=a;//從尾部插入元素
    e=end;
    //對插入的元素進行上升操作
    while(e>1){
        p=e>>1;
        if(heap[e]<heap[p]){//如果比父節點小就上升
            tmp=heap[e];
            heap[e]=heap[p];
            heap[p]=tmp;
        }else break;//比父節點大直接break,小頂堆的性質決定
        e=p;
    }
}
int getMin(){

    int ls,rs,rt=1;            //rt指向堆的根節點,ls指向根節點的左孩子,rs指向根節點的右孩子
    int res,last,tmp;       //res堆中的最小值,也就是堆的根節點,last爲堆中的最後一個元素
    res=heap[rt];           //取出根節點,所以堆的元素個數需要減一
    last=heap[end--];    //得到堆的最後一個元素
    heap[rt]=last;          //把最後一個元素從根節點插入

    //對根節點進行下降操作
    while(1){
        ls=rt<<1;rs=rt<<1|1;

        if(ls>end||rs>end){//如果左孩子或者右孩子指向超出元素的總數,也就是指向空
            if(ls<=end&&heap[rt]>heap[ls]){//左孩子沒有超出,並且需要交換
                tmp=heap[rt];
                heap[rt]=heap[ls];
                heap[ls]=tmp;
            }
            break;
        }

        if(heap[rt]<=heap[ls]&&heap[rt]<=heap[rs])break;//左孩子右孩子都比根節點大,不需要交換

        if(heap[rt]>heap[ls]&&heap[rs]>=heap[ls]){//比較根節點和左右孩子,和最小的交換
            tmp=heap[rt];
            heap[rt]=heap[ls];
            heap[ls]=tmp;
            rt=ls;
        }else{
            tmp=heap[rt];
            heap[rt]=heap[rs];
            heap[rs]=tmp;
            rt=rs;
        }

    }
    return res;
}
int main(){
    //插入20個數據進行測試一下
    int a,i;
    for(i=1;i<=20;i++){
        a=rand()%100;
        printf("%2d ",a);
        insert(a);
    }
    printf("\n");
    while(end>0){
      printf("%2d ",getMin());
    }
    printf("\n");
return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章