堆與堆排序

2021-09-30 11:16:43 字數 1745 閱讀 8235

堆排序是一種排序方式。

堆是一種資料結構,全稱二叉堆,也叫優先佇列。堆至少支援兩種操作,insert入堆和deletemin刪除掉堆中最小的節點。堆是一顆完全二叉樹,因為完全二叉樹的性質,我們可以用陣列來代替而不需要指標。對於陣列中任意元素i,它的左兒子下標是2i,右兒子是2i+1,父親在i / 2取下限。為了便於計算,陣列中的乙個元素不存放相關資料。因此堆得結構應該包含乙個陣列,乙個代表最大值的整數和當前堆得大小的整數。

struct heap;
堆的性質是快速被執行,為了找出最小元素,我們應該將最小元放在根,且任意子樹也是乙個堆,也應該符合這個原則。堆中除了根節點以為每乙個節點的關鍵字都大於等於其父節點的關鍵字。

heap * init(int maxelements)

h = malloc(sizeof(struct heap));

if(h == null)

eooro("out of space");

h -> elements = malloc((maxelements + 1) * sizeof(elementype));

h -> capacity = maxelements;

h -> size = 0;

h -> elements[0] = mindata;

return h;

}

插入操作,將乙個元素插入到堆得過程是首先在堆的最後乙個元素後邊取乙個空白節點。然後判斷要插入的元素如果插入空白節點的話,是否否符合堆得特性,即節點的值小於其父節點,如果符合則插入完畢,否則將空白節點的與父節點交換,在以此類推,直至堆得根節點。

void insert(elementtype x, heap * h)

for(i = ++h->size; h -> elements[i / 2] > x; i /= 2)

h -> elements[i] = x;

}

堆得根節點就是最小的元素,所以取最小值時間複雜度為o(1),刪除最小元素時,根節點變成了乙個空節點,取空節點的較小的子節點(這裡需要判斷是否有左右子節點),交換兩者,以此類推,直到空節點移動到了最後的乙個位置,通過size與下標判斷。這裡的刪除還可以認為是一次篩選,而且可以不設定是從頂部去篩選,該函式是將篩選的結點作為根節點實現堆的特性,為了方便建堆。

void heapadjust(heap * h, int s, int m)

h -> elements[j/2] = rc;

}

刪除根節點的時間複雜度是o(log k),k是節點個數。

堆得建立時間複雜度是o(n),設有n個元素,高h = logn,從下向上建立,而終端節點是不需要上述「篩選」操作的,可以得到最後乙個非終端節點是n/2取下限。第i層上節點數最多有2^(i-1)個,以該層節點為根節點的堆高度為h - i + 1,每次每個節點需要比較兩次,孩子節點比較,孩子于父節點比較,呼叫次數不會超過n/2取下限。

所以時間複雜度s = 2^(h-1) + 2^(h-2)*2 + … + 2 * (h - 1); 2s - s = s = 2^h -2h + 4 = n - 2logn + 4 = o(n);

堆的建立於排序都需要上述篩選的演算法,堆得排序又分大頂堆和小頂堆,其實就是從大到小和從小到大排序。

void heapsort(heap * h)

}

堆排序的時間複雜度就是建堆和不斷篩選上,即使在最壞的情況下,也是o(nlogn)。

堆與堆排序

二叉堆是完全二叉樹或者是近似完全二叉樹。二叉堆滿足二個特性 1 父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值。2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 當父結點的鍵值總是大於或等於任何乙個子節點的鍵值時為最大堆。當父結點的鍵值總是小於或等於任何乙個子節點的鍵值時...

堆與堆排序

堆排序與快速排序,歸併排序一樣都是時間複雜度為o n logn 的幾種常見排序方法。堆排序是就地排序,輔助空間為o 1 它是不穩定的排序方法。排序的穩定性是指如果在排序的序列中,存在前後相同的兩個元素的話,排序前 和排序後他們的相對位置不發生變化 先說說什麼是堆,堆通常是乙個可以被看做一棵樹的陣列物...

堆與堆排序

堆排序與快速排序,歸併排序一樣都是時間複雜度為o n logn 的幾種常見排序方法。學習堆排序前,先講解下什麼是資料結構中的二叉堆。二叉堆是完全二叉樹或者是近似完全二叉樹。二叉堆滿足二個特性 1 父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值。2 每個結點的左子樹和右子樹都是乙個二叉堆...