堆排序算法思想:
堆排序是利用二叉树的原理,模拟二叉树将所求的数据放入存放树中,先将所有数据按照大根堆排列,排列之后再依次的给树按从小到大排列.
例如
2 5 44 21 11 6 1 9
我们将数据按照这样的二叉树的形式列举出来,然后将数据进行大根堆的转换(注:我们再进行大根堆的转换的时候应该从最小的一个二叉树开始进行,然后逐渐进行),转换完成后将未定下来的最大数字跟最上面的节点交换,一直循环,直到完全有序
大根堆转换:转换的时候我们先比较左孩子跟右孩子的大小,然后将大的跟父进行比较,如果比父大,就交换这两个位置,一直循环进行
代码实现:
void HeapAdjust(int* arr, int start, int end)//堆调整
{
int tmp = arr[start];
for (int i = 2 * start + 1; i <= end; i=2*i+1)
{
if (i < end && arr[i] < arr[i + 1])//如果有右孩子,并且左孩子的值小于右孩子
{
i++;
}//i一定是左右孩子的最大值
if (arr[i] > tmp)
{
arr[start] = arr[i];
start = i;
}
else
{
break;
}
}
arr[start] = tmp;
}
void HeapSort(int* arr, int len)//堆排序,O(nlogn),O(1),不稳定
{
int i;
//第一次建立大根堆,从后往前,多次调整
for (i = (len - 1 - 1) / 2; i >= 0; i--)//有一个数学证明,O(n)
{
HeapAdjust(arr, i, len - 1);//第一次建立大根堆
}
//每次将根和待排序的最后一个交换,然后再次调整
int tmp;
for (i = 0; i < len - 1; i++) //O(nlogn)
{
//交换
tmp = arr[0];
arr[0] = arr[len - 1 - i];
arr[len - 1 - i] = tmp;
//再次调整
HeapAdjust(arr, 0, len -1-i -1);//堆调整
}
}
总结:
时间复杂度:O(nlogn),系数大,空间复杂度O(1),不稳定