學習資料結構的時候就學習過堆,不過忘了很多了,《程式設計珠璣》裡也有這一章,因此重新總結一下。
堆的兩個性格:(1)順序性質:任何結點的值都小於或等於子結點的值。(對於最小堆而言)
(2)形狀性質:二叉樹結構,最多在兩層上具有葉結點,其中最底層的結點盡可能的靠左分布。
堆的實現:考慮以陣列實現,對於大小為n的堆,宣告陣列x[n+1],下標從1開始並浪費x[0]。樹種常見的函式定義如下:
root = 1;
value(i) = x[i];
leftchild(i) = 2*i;
rightchild(i) = 2*i+1;
parent(i) = i /2;
null(i) = (i < 1) or (i > n).
堆的兩個關鍵函式:即上濾siftup和下濾siftdown函式,後面操作都要反覆呼叫這兩個函式。
siftup函式:當存在heap(1,n-1),考慮在n處插入乙個新的元素。新插入的元素可能會破壞堆的性質,如果新插入的元素比它的父節點小,就需要將元素和父結點交換,直到到達合適的位置並成為根的右結點為止。
void siftup(n)
下面考慮下濾siftdown,假設給x[1]乙個新值,使用siftdown函式使堆的性質保持。這裡除了要考慮邊界條件還要考慮到存在兩個子結點,處理辦法是總是與較小的子結點交換。
void siftdown(n)
}
有了資料結構,開始考慮對堆進行的一些操作了。
構建堆:一般的演算法是將n個關鍵字以任意順序放入樹中,保持結構特性。考慮將結點上濾可以完成一顆具有堆序的樹。
//上濾建堆
for(int i = 2; i <= n; ++i)
siftup(i);
堆的插入操作:把新加入的元素放在堆得末尾,實現上濾就可以了,同時考慮邊界。
void insert(t)
函式extractmin查詢並刪除集合中的最小元素,然後重新組織使其具有堆性質。思想是從堆頂取出元素,將堆的最後乙個元素賦給堆頂然後下濾。
elementtype extractmin()
封裝成c++類:
templateclass priqueue
public:
priqueue(int m)
void siftup(n)
void siftdown(n)
}void insert(t)
t extractmin()
};
堆排序:通過建立優先佇列然後反覆呼叫extractmin函式可以實現排序,建優先佇列和extractmin的時間開銷均為o(nlogn);但是優先佇列和陣列的空間開銷分別為n+1和n.利用堆排序可以直接在陣列上排序。時間複雜度o(nlogn).
//優先佇列排序
templatevoid pqsort(t v, int n)
//堆排序
void swap(int *v, int i, int j)
void siftup(int *v, int n)
void siftdown(int *v, int n)
}
//堆排序
void heapsort(int *v, int n)
}
上面討論的堆捨棄了陣列0位置不用,如果考慮以0位置作為根的話,則左子結點為2*i+1,父結點為(i-1)/2,重新利用堆排序如下:
void swap(int *v, int i, int j)
void siftup(int *v, int n)
void siftdown(int *v, int n)
}
//堆排序
void heapsort(int *v, int n)
}
堆和優先佇列
優先佇列 priority queue 特殊的 佇列 取出元素的順序是依照元素的優先權 關鍵字 大小,而不是元素進入佇列的先後順序。優先佇列的完全二叉樹表示 note 0號位置是為了之後的插入操作方便,而加入的哨兵,如果在堆排序中,未給出這樣的結點,則可不設定。堆的兩個特性 結構性 用陣列表示的完全...
堆和優先佇列
include using namespace std class heap public heap int intput capacity heap void push int value size void heap sort void output cout n inttop void pop...
優先佇列和堆
怎麼理解優先佇列和堆的關係?簡單來說 堆排序是一種排序演算法,利用堆結構完成排序的功能 優先佇列是一種資料結構,它是利用堆來實現。具體來說,堆排序過程 建堆 堆頂就是最大 或小 值,然後堆頂跟最後乙個元素交換 調整堆,反覆這個過程,直到堆裡面所有元素都交換好 而優先佇列 建堆 堆頂元素就是優先順序最...