堆排序-《算法導論》學習筆記六

堆排序就是將一組數按二叉樹層序遍歷的存儲順序,經過一系列比較轉移,最終變成有序的數組,這裏的二叉樹堆一定是完全二叉樹。堆排序能進行的基礎是有個最大堆的數組,最大堆性質是指樹上的每個節點的子節點都比自己小或等於。
因此最頂上的根節點一定是值最大的節點,有了最大堆在,堆排序就可以進行了,從層序遍歷的最後一個節點開始倒序循環,交換當前節點與最頂層根節點,即最大值的節點,這樣每次最大的節點都被放在層序遍歷的最後位置,類似冒泡排序了,而放了最大值的節點即從堆中排除(只要堆長度減一即表示堆沒有這個節點了),交換到頂點根節點的值再做一次下濾操作(以這個節點值與子樹的最大值交換),保證剩餘子樹一定也是最大堆性質。
貼代碼:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>

int parent( int );
int left( int );
int right( int );

inline int parent( int index )
{
    return index / 2;
}
inline int left( int index )
{
    return index * 2;
}
inline int right( int index )
{
    return index * 2 + 1;
}

//下濾
void max_heapify( 
    int *arr, 
    int heap_size, 
    int index )
{
    int l = left( index );  
    int r = right( index );
    int largest = 0;

    if ( l <= heap_size && arr[l] > arr[index] ) {
        largest = l;
    } else {
        largest = index;
    }
    if ( r <= heap_size && arr[r] > arr[largest] ) {
        largest = r;
    }
    if ( largest != index ) {
        int temp = arr[index];
        arr[index] = arr[largest];
        arr[largest] = temp;
        max_heapify( arr, heap_size, largest );
    } 
}
//構建最大堆
void build_max_heap( 
    int *arr,
    int length,
    int heap_size )
{
    int i = 0;

    for ( i = length / 2; i >= 1; i-- ) {
        max_heapify( arr, heap_size, i );
    }
}
//開始堆排序
void heap_sort(
    int *arr, 
    int length,
    int heap_size )
{
    int i = 0;

    build_max_heap( arr, length, heap_size );

    for ( i = heap_size; i >= 2; i-- ) {
        int temp = arr[1];
        arr[1] = arr[i];
        arr[i] = temp;
        heap_size -= 1;
        max_heapify( arr, heap_size, 1 );
    }
}
void check_is_inc_arr( 
    int *arr, 
    int len )
{
    int i = 0;

    for ( i = 1; i <= len; i++ ) {
        if ( arr[i] < arr[i - 1] ) {
            printf("check_is_inc_arr fail.\n");
            return;
        }   
    }
    printf("check_is_inc_arr ok.\n");
}
//初始化隨機數組
void initArr( int *arr, int lowV,
    int upV, int len )
{
    int i = 0;
    int size = upV - lowV;

    for ( i = 1; i < len + 1; i++ )
    {
        arr[i] = rand() % size + lowV;
    }
    arr[0] = 0;
}
void print_arr( 
    int *arr, 
    int len )
{
    int i = 0;

    printf("\n=============================================\n");
    for ( i = 0; i <= len; i++ ) {
        printf("%d ", arr[i]);
    }
    printf("\n=============================================\n");
}
int main(
    int argc,
    char **argv )
{
    if ( argc != 4 ) {
        printf("input array length and the random value range.\n");
        exit( 0 );
    }

    srand( (int)time(NULL) );

    int length = atoi( argv[1] );
    int lowV = atoi( argv[2] );
    int upV = atoi( argv[3] );

    int *arr = ( int * )malloc( sizeof(int) * (length + 1) );

    initArr( arr, lowV, upV, length );

    //print_arr( arr, length );
    heap_sort( arr, length, length );
    //print_arr( arr, length );

    check_is_inc_arr( arr, length );

    return 0;
}

上面代碼中因爲c數組從0開始的原因,因此0位置不參與存儲和運算,數據形式是{0, 2, 3, 4, 5, 6}。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章