1. 程式人生 > >【學習筆記】堆的定義及其建立、排序等基本操作的實現

【學習筆記】堆的定義及其建立、排序等基本操作的實現

目錄

堆的定義:

堆的基本操作的程式碼實現:


詳情請參見《演算法筆記》P335,此處只做簡單的學習筆記記錄。

 

堆的定義:


堆是一棵完全二叉樹,樹中的每個結點的值都不小於(或不大於)其左右孩子結點。

堆一般用於優先佇列的實現(目前不是很懂),故預設使用的是大頂堆(每個結點的值都大於或等於其左右孩子結點,小於等於時即為小頂堆)。

 

堆的基本操作的程式碼實現:


堆的定義:因為堆是完全二叉樹,所以可以用陣列存。陣列的下標為1~n,表示第1~n個結點。

const int maxn=100;
int heap[maxn],n=10;//heap為堆,n為元素個數

向下調整:O(logn)

void downAdjust(int low,int high)//low為欲調整結點的陣列下標,high一般為堆的最後一個元素的陣列下標
{
    int i=low,j=i*2;//i為根結點,j為左孩子結點
    while(j<=high)//存在孩子結點
    {
        if(j+1<=high && heap[j+1]>heap[j])//存在右孩子且右孩子的值大於左孩子的值
            j=j+1;//左右孩子中較大的那個的下標
        if(heap[j]>heap[i])
        {
            swap(heap[j],heap[i]);
            i=j;
            j=i*2;
        }
        else break;
    }
}

建堆:O(n)

void createHeap()//倒序遍歷父親結點
{
    for(int i=n/2;i>=1;i--)
        downAdjust(i,n);//對父親結點向下調整
}

刪除堆頂元素:O(logn)

void deleteTop()
{
    heap[1]=heap[n--];//堆頂元素和最後一個元素交換,且元素個數-1,再對當前的堆頂結點向下調整
    downAdjust(1,n);
}

向上調整:O(logn)

void upAdjust(int low,int high)//low一般為1,high一般為預調整結點的陣列下標
{
    int i=high,j=high/2;//i為孩子結點,j為根結點
    while(j>=low)//根結點在[low,high]範圍內
    {
        if(heap[i]>heap[j])//孩子結點的值大於根結點的值
        {
            swap(heap[i],heap[j]);
            i=j;
            j=i/2;
        }
        else break;
    }
}

新增元素:在堆尾

void insert(int x)
{
    heap[++n]=x;
    upAdjust(1,n);//向上調整新加入的結點n
}

堆排序:

void heapSort()
{
    createHeap();//建堆
    for(int i=n;i>1;i--)//直到堆裡只有一個元素時
        downAdjust(1,i-1);//調整棧頂,heap[i]此時不算入堆中
}