1. 程式人生 > >堆的構建、堆的插入、堆的刪除、堆排序

堆的構建、堆的插入、堆的刪除、堆排序

#include<stdio.h>
#include<stdlib.h>
#define INIT_ARRAY_SIZE 50

int heap_size; //堆大小
int heap_cap_size;  //堆容量大小

/*函式宣告*/  
//構建堆
void build_heap(int array[], int length);
//堆的調整
void max_heap_adjust(int array[], int index);
//堆的刪除
void heap_delete(int array[], int value);
//堆的插入
void heap_insert(int** array, int value);
//堆排序
void heap_sort(int array[], int length);

/*返回以index為根的完全二叉樹的左子樹的索引,整個二叉樹索引以0為開始*/  
int left(int index) {
	return ((index << 1) + 1);
}
/*返回以index為根的完全二叉樹的右子樹的索引,整個二叉樹索引以0為開始*/ 
int right(int index) {
	return ((index << 1) + 2);
}
/*兩個數的交換*/ 
void swap(int* a ,int* b) {
	int temp = *a;
		*a = *b;
		*b = temp;
	return;
}

void build_heap(int array[], int length) {
	heap_size = length;
	for (int i = ((heap_size - 1) >> 1); i >= 0; --i) {
		max_heap_adjust(array, i);
	}
}

void max_heap_adjust(int array[], int index) {
	int left_index = left(index);
	int right_index = right(index);
	int largest = index;
	//左子樹和父節點進行對比
	if (left_index <= (heap_size-1) && array[left_index] > array[largest]) {
		largest = left_index;
	}
	//右子樹和父節點進行對比
	if (right_index <= (heap_size-1) && array[right_index] > array[largest] ) {
		largest = right_index;
	}
	if (largest == index) {
		return;
	} else {
		//需要交換
		swap(&array[index], &array[largest]);
		//遞迴呼叫
		max_heap_adjust(array, largest);
	}
}

void heap_delete(int array[], int value) {
	int index = 0;
	for (index = 0; index < heap_size; index++) {
		if (array[index] == value) {
			break;
		}
	}
	array[index] = array[heap_size - 1];
	--heap_size;
	max_heap_adjust(array, index);
}

void heap_insert(int** array, int value) {
	int index = 0;
	int parent_index = 0;
	if (heap_size+1 > heap_cap_size) {
		*array = (int*) realloc(*array, 2*INIT_ARRAY_SIZE*sizeof(int));
	}
	(*array)[heap_size] = value; //一定要記得加上()既(*array)[heap_size] 如果寫出*array[heap_size]肯定會出問題
	index = heap_size;
	heap_size++;//要記得這裡堆大小變大了
	//和父節點對比,哪個大就往上移動
	while (index) {
		parent_index = ((index-1) >> 1);
		if ((*array)[parent_index] < (*array)[index]) {
			swap(&((*array)[parent_index]), &((*array)[index]));	
		}
		index = parent_index;
	}
}

void heap_sort(int array[], int length) {
	int old_heap_size  = heap_size;
	int i;
	for (i = length-1; i >= 1; --i) {
		swap(&array[i], &array[0]);
		--heap_size;
		max_heap_adjust(array, 0);
	}
	//恢復堆的大小
	heap_size = old_heap_size;
}

void print_array(int* a , int length) {
	for (int i =0; i < length; i++) {
		printf("%d\t", a[i]);
	}
	printf("\n");
}
int main() {
	int i = 0;
	int a[] = {9, 3, 7, 6, 5, 1, 10, 2};
	int *array = NULL;
	array = (int *)malloc(INIT_ARRAY_SIZE*sizeof(int));
	int length = sizeof(a)/sizeof(int);
	printf("陣列的長度是:%d\n", length);
	for (i = 0; i < length; ++i) {
		array[i] = a[i];
	}
	printf("原始陣列為\n");
	print_array(array, length);
	printf("堆的建立後的陣列\n");
	build_heap(array, length);
	print_array(array, length);
	printf("堆排序後的陣列為\n");
	heap_sort(array, length);
	print_array(array, length);
    //這個地方一定要記得先構建堆,不然下面執行刪除和插入有問題
	build_heap(array, length);

	printf("刪除資料10後的陣列\n");
	heap_delete(array, 10);
	length--;
	print_array(array, length);

	printf("插入資料10後的陣列\n");
	length++;
	heap_insert(&array, 10);
	print_array(array, length);

	printf("堆排序後的陣列為\n");
	heap_sort(array, length);
	print_array(array, length);
	return 0;
}

執行結果: