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