堆排序的OC實現,堆排序OC實現
/* 建議先看堆調整方法,堆調整瞭解了,整個排序演算法就算掌握了 */- (void)viewDidLoad{ [super viewDidLoad]; /* 測試資料 */ NSArray *array=@[@3,@2,@6,@4,@1,@0,@6,@7,@5]; NSMutableArray *mutable=[NSMutableArray arrayWithArray:array]; mutable=[self createMaxHeap:mutable]; NSInteger num=mutable.count; /* 剩餘的元素個數不為1時則繼續調整,取出元素。取出的元素放在最後的一個節點。然後減小堆的元素的個數。所以大頂堆排序出來的是升序的。 */ while (num>1) { [mutable exchangeObjectAtIndex:0 withObjectAtIndex:num-1]; mutable=[self maxHeapAdjust:mutable index:0 length:num-1]; num--; }}/* 調整堆 遞迴調整的過程。這個調整堆的方法傳入的是待調整的數組,數組元素的長度(為什麼不直接用array.count呢?因為再進行排序 的時候,我們會動態更改無序堆的長度,而array的長度確是不變的,所以不用array.cout) 其實每調用一次調整堆方法,我們相當於只調整3個元素:父節點,左、右子節點。當左子結點是三者中最大的時候,把它和父節點進行交換。然後再遞迴調整以剛才的父節點(現在被降級為左子節點)為父節點的三個節點。此時為什麼不用調整右子節點呢?這是由於我們建立大頂堆的過程中,都是自下而上進行調整的,此時我們沒有動右子節點,且右子節點和現在的父節點(原來的左子節點)滿足大頂堆的條件,所以不用調整。 */-(NSMutableArray*)maxHeapAdjust:(NSMutableArray *)array index:(NSInteger)index length:(NSInteger)length{ NSInteger leftChildIndex =index*2+1;//擷取該節點的左子節點索引 NSInteger rightChildIndex=index*2+2;//擷取該節點的右子節點索引 NSInteger maxValueIndex=index;//暫時把該索引當做最大值所對應的索引 // leftChildIndex<length你 //array[leftChildIndex]>array[maxValueIndex] 判斷左子節點的值是否大於當前最大值 if (leftChildIndex<length && array[leftChildIndex]>array[maxValueIndex]) { //把左子節點的索引作為最大值所對應的索引 maxValueIndex=leftChildIndex; } // rightChildIndex<length //array[leftChildIndex]>array[maxValueIndex] 判斷左子節點的值是否大於當前最大值 if (rightChildIndex<length && array[rightChildIndex]>array[maxValueIndex]) { maxValueIndex=rightChildIndex; } //如果該節點不是最大值所在的節點 則將其和最大值節點進行交換 if (maxValueIndex!=index) { [array exchangeObjectAtIndex:maxValueIndex withObjectAtIndex:index]; //遞迴鄉下調整,此時maxValueIndex索引所對應的值是 剛才的父節點。 array=[self maxHeapAdjust:array index:maxValueIndex length:length]; } return array;}-(NSMutableArray*)createMaxHeap:(NSMutableArray*)array{ /* 從最後一個非葉子節點開始 自下而上進行調整堆 */ for (NSInteger i=(array.count/2-1);i>=0; --i) { array=[self maxHeapAdjust:array index:i length:array.count] ; } return array;}