堆排序算法-OC實現(xiàn)

  • 簡介

堆排序(英語:Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法。堆是一個近似完全二叉樹的結(jié)構(gòu),并同時滿足堆積的性質(zhì):即子結(jié)點的鍵值或索引總是小于(或者大于)它的父節(jié)點。
堆分為最大堆和最小堆,其實就是完全二叉樹。最大堆要求節(jié)點的元素都要不小于其孩子,最小堆要求節(jié)點元素都不大于其左右孩子,兩者對左右孩子的大小關(guān)系不做任何要求,其實很好理解。有了上面的定義,我們可以得知,處于最大堆的根節(jié)點的元素一定是這個堆中的最大值。

  • 算法原理

1、將初始待排序關(guān)鍵字序列(R1,R2....Rn)構(gòu)建成大頂堆,此堆為初始的無序區(qū)
2、將堆頂元素R[1]與最后一個元素R[n]交換,此時得到新的無序區(qū)(R1,R2,......Rn-1)和新的有序區(qū)(Rn)
3、由于交換后新的堆頂R[1]可能違反堆的性質(zhì),因此需要對當(dāng)前無序區(qū)(R1,R2,......Rn-1)調(diào)整為新堆,然后再次將R[1]與無序區(qū)最后一個元素交換,得到新的無序區(qū)(R1,R2....Rn-2)和新的有序區(qū)(Rn-1,Rn)。不斷重復(fù)此過程直到有序區(qū)的元素個數(shù)為n-1,則整個排序過程完成

  • C語言實現(xiàn)
//最大堆調(diào)整(Max Heapify):將堆的末端子節(jié)點作調(diào)整,使得子節(jié)點永遠小于父節(jié)點
void maxHeapify(int numbers[], int start, int end) {
    //建立父節(jié)點指標(biāo)和子節(jié)點指標(biāo)
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end) { //若子節(jié)點指標(biāo)在范圍內(nèi)才做比較
        if (son + 1 <= end && numbers[son] < numbers[son + 1]) { //先比較兩個子節(jié)點大小,選擇最大的
            son++;
        }
        if (numbers[dad] > numbers[son]) {//如果父節(jié)點大于子節(jié)點代表調(diào)整完畢,直接跳出函數(shù)
            return;
        }else { //否則交換父子內(nèi)容再繼續(xù)子節(jié)點和孫節(jié)點比較
            int temp = numbers[son];
            numbers[son] = numbers[dad];
            numbers[dad] = temp;
            dad = son;
            son = dad * 2 + 1;
        }
    }
}

/**堆排序(HeapSort):
 1、首先從最后一個父節(jié)點做最大堆調(diào)整,找出最大值,此時最大值位于根節(jié)點
 2、然后將最大值和已排好元素(依次找出的最大值排出的序列,如:6 3 9 23 12 8 [15 16 17 18])前一位元素交換位置,再將除已排好元素外的其他元素(6 3 9 23 12 8)做最大堆調(diào)整,找出最大值,此時最大值位于根節(jié)點
 3、重復(fù)步驟2,直至結(jié)束
 */
void heapSort(int numbers[], int length) {
    //初始化,i從最後一個父節(jié)點開始做最大堆調(diào)整,調(diào)整結(jié)束后根節(jié)點得到最大值
    for (int i = length / 2 - 1; i >= 0; i--) {
        maxHeapify(numbers, i, length - 1);
    }
    //先將第一個元素和已排好元素前一位做交換,再重新調(diào)整,直到排序完畢
    for (int i = length - 1; i > 0; i--) {
        int temp = numbers[0];
        numbers[0] = numbers[i];
        numbers[i] = temp;
        maxHeapify(numbers, 0, i - 1);
    }
}

//調(diào)用
    int number[5] = {95, 45, 15, 78, 84};
    heapSort(number, 5);
    for (i = 0; i < 5; i++) {
        printf("%d\n", number[i]);
    }
  • OC實現(xiàn)
//最大堆調(diào)整(Max Heapify):將堆的末端子節(jié)點作調(diào)整,使得子節(jié)點永遠小于父節(jié)點
- (void)maxHeapifyWithNumbers:(NSMutableArray *)numbers start:(int)start end:(int)end {
    //建立父節(jié)點指標(biāo)和子節(jié)點指標(biāo)
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end) { //若子節(jié)點指標(biāo)在范圍內(nèi)才做比較
        if (son + 1 <= end && [numbers[son] intValue] < [numbers[son + 1] intValue]) { //先比較兩個子節(jié)點大小,選擇最大的
            son++;
        }
        if ([numbers[dad] intValue] > [numbers[son] intValue]) {//如果父節(jié)點大于子節(jié)點代表調(diào)整完畢,直接跳出函數(shù)
            return;
        }else { //否則交換父子內(nèi)容再繼續(xù)子節(jié)點和孫節(jié)點比較
            [numbers exchangeObjectAtIndex:son withObjectAtIndex:dad];
            dad = son;
            son = dad * 2 + 1;
        }
    }
}

/**堆排序(HeapSort):
 1、首先從最后一個父節(jié)點做最大堆調(diào)整,找出最大值,此時最大值位于根節(jié)點
 2、然后將最大值和已排好元素(依次找出的最大值排出的序列,如:6 3 9 23 12 8 [15 16 17 18])前一位元素交換位置,再將除已排好元素外的其他元素(6 3 9 23 12 8)做最大堆調(diào)整,找出最大值,此時最大值位于根節(jié)點
 3、重復(fù)步驟2,直至結(jié)束
 */
- (void)heapSortWithNumbers:(NSMutableArray *)numbers {
    //初始化,i從最後一個父節(jié)點開始做最大堆調(diào)整,調(diào)整結(jié)束后根節(jié)點得到最大值
    for (int i = (int)numbers.count / 2 - 1; i >= 0; i--) {
        [self maxHeapifyWithNumbers:numbers start:i end:(int)numbers.count - 1];
    }
    //先將第一個元素和已排好元素前一位做交換,再重新調(diào)整,直到排序完畢
    for (int i = (int)numbers.count - 1; i > 0; i--) {
        [numbers exchangeObjectAtIndex:0 withObjectAtIndex:i];
        [self maxHeapifyWithNumbers:numbers start:0 end:i - 1];
    }
    NSLog(@"%@",numbers);
}

//調(diào)用
NSMutableArray *array = [NSMutableArray arrayWithObjects:@(10),@(4),@(8),@(99),@(16),@(19),@(3), nil];
[self heapSortWithNumbers:array];
  • 時間復(fù)雜度

最好、最壞和平均時間復(fù)雜度都為O(nlogn)。

  • 算法穩(wěn)定性

不穩(wěn)定的排序算法

提供一個他人的更詳細(xì)的解讀堆排序

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容