本文共 1942 字,大约阅读时间需要 6 分钟。
先明白原理后看实现
一、堆原理
转载自
堆排序在最坏的情况下,其时间复杂度也为O(nlogn)
注:
如果根结点是从1开始,则左右孩子结点分别是2i和2i+1。
如果根结点是从0开始,则左右孩子结点分别是2i+1和2i+2,数组是以0开始的,所以一般使用这个!
二、实现与测试
#include#include /* 堆排序(heap_sort)*/ /* 堆调整,构建大顶堆,arr[]是待调整的数组,i是待调整的数组 元素的位置,length是数组的长度 */ void heap_adjust(int arr[], int i, int length) { int child; int temp; while (2 * i + 1 < length) { /* 子节点的位置 = 2 * (parent(父结点)) + 1 */ child = 2 * i + 1; /* 得到子结点中较大的结点 */ if(child < length - 1 && arr[child + 1] > arr[child]){ child++; } /* 如果较大的子结点大于父结点那么把较大的子结点往上移动替换它的父结点 */ if(arr[i] < arr[child]) {/* 此节点和自己的子节点数据进行交换,就必须进继续比较后代节点*/ temp = arr[i]; arr[i] = arr[child]; arr[child] = temp; i = child; }else {/*没有交换的话 就不对子节点做比较*/ break; } } } /* 堆排序算法 */ void heap_sort(int arr[], int length) { int i; /* 调整序列的前半部分元素,调整完之后第一个元素 是序列的最大元素,length/2-1是最后一个非叶子结点 */ for(i = length/2 - 1; i >= 0; --i) { heap_adjust(arr, i, length); } /* 从最后一个元素开始对序列进行调整,不断的缩小调整 的范围直到第一个元素 循环里是把第一个元素和当前的最后一个元素交换 保证当前的最后一个位置的元素是现在这个序列的最大的 不断的缩小调整heap的范围,每一次调整完毕保证第一个 元素是当前序列的最大的元素 */ for(i = length - 1; i > 0; --i) { arr[i] = arr[0]^arr[i]; /* 交换的一种实现 */ arr[0] = arr[0]^arr[i]; arr[i] = arr[0]^arr[i]; heap_adjust(arr, 0, i); /* 递归调整 */ } } int main() { int i; int num[] = {98, 48, 777, 63, 57, 433, 23, 1112, 1}; printf("sort before : "); for(i = 0; i < sizeof(num)/sizeof(int); i++) { printf("%d ", num[i]); } printf("\n"); heap_sort(num, sizeof(num)/sizeof(int)); printf("sort after : "); for(i = 0; i < sizeof(num)/sizeof(int); i++) { printf("%d ", num[i]); } printf("\n"); return 0; }