概念堆是按照一定規則順序儲存的
完全二叉樹
(二叉樹是每個節點最多有兩個子樹的樹結構),其中可以分為大根堆和小根堆。
* 大根堆: 每個父結點的關鍵字都大於其子節點的關鍵字(如果有子結點的話)
* 小根堆: 每個父結點的關鍵字都小於其子節點的關鍵字(如果有子結點的話)
舉例來說,有個陣列[a0, a1, a2, a3…an]假設父結點為ai(其中i=1,2,…,n/2向下取整), 由二叉樹的排列規律可知其左子結點為a(2 * i + 1), 右子結點為a(2 * i + 2)因此大根堆
必須滿足:ai >= a(2 * i + 1)且ai >= a(2 * i + 2),小根堆
必須滿足ai <= a(2 * i + 1)且ai <= a(2 * i + 2)
假如有個數列[3, 8, 15, 31, 25],以二叉樹的形式表示如下圖:
首先需要按照堆的規則去構造初始堆(即構建乙個完全二叉樹,保證所有的父結點都比它的孩子結點數值大),構造規則為不同行從下往上、相同行從右往左
分別比較每乙個子二叉樹的結點,如果父結點的關鍵字不是最大值,讓子節點中最大的值與父節點進行交換。如此遍歷一遍後可以得到乙個初始堆。
注意: 當第一級二叉樹子結點值大於父結點的值進行交換後,交換後新的子結點作為父結點的第二級子二叉樹中如果依然不是最大值則需要再次與其最大子結點進行交換。例:有個陣列[5,3,1,8,7]在調整後變為[5,8,1,3,7]->[8,5,1,3,7],然而此時由於在(5,3,7)這個子二叉樹中父結點5不是最大值,因此需要再次向下比較一次進行交換
在初始堆的基礎上交換陣列中被調整的首尾元素,並讓陣列重新調整為大根堆(這次調整忽略移到末尾的元素),採用遞迴的方式就可以依次把所有元素按公升序排列到陣列中了。
oc語言例項給可變陣列建立乙個分類來存放該堆排序方法。
- (nsmutablearray *)heapsort
}nsassert(isfullnsnumber, @"陣列中應當全是nsnumber物件");
// 初始化乙個終止計算結點索引位置(一次排序後把最大值移動到陣列計算結點範圍的末尾)
int endindex = (int)(self
.count - 1);
while (endindex > 0)
return
self;
}
/// 二叉樹規則(大根堆)排序 -- (排序範圍為索引為0的位置到待排序結點最大索引位置)
- (void)binarytreesortwitharray:(nsmutablearray *)array maxindex:(int)maxindex}}
/// 遞迴比較指定索引位置的結點與其左右子節點的大小
- (int)comparenodessizewithmaxindex:(int)maxindex fathernodeindex:(int)fatherindex
if (rightindex <= maxindex)
if (rightvalue != nil) // 右子節點存在, 則左子節點必定存在, 判斷三者的值並把最大值換到父節點上
else
}else
if (leftvalue != nil) // 右結點不存在, 左結點存在, 判斷左結點是否大於父結點的值
else
}return -1;
}
排序之堆排序
堆排序是一種基於比較排序的另一種排序演算法,它採用了一種近似完全二叉樹的二叉堆資料結構。演算法實現相容了插入排序的空間原址性 即只需要有限個額外的儲存空間 和歸併排序的優良時間複雜度。偽 如下 heapsort a build max heap a for i a.length downto 2 e...
排序之堆排序
這裡沒有對0號元素進行排序 堆排 public class heap public static void exec comparable array,int i,int j 下沉 private static void sink comparable array,int k,int n publi...
排序之堆排序
堆其實是一種完全二叉樹,從上到下從左到右,大頂堆的父節點大於其左右子節點,小頂堆的父節點小於其左右子節點 1 首先是進行heapify,建立堆 2 從下到上,從右到左的進行heapify構建有序的堆 3 進行排序,將堆頂父節點和底層最右邊的子節點互換,然後不斷重複以上步驟 1 heapify def...