核心概念
利用最大堆(或者最小堆)输出堆顶元素,即最大值(或最小值),将剩余元素重新生成最大堆(或者最小堆),继续输出堆顶元素,重复此过程,直到全部元素都已输出,得到的输出元素序列极为有序序列。
代码思路
这里的堆排,实际就像最大堆的删除一样
先建堆,从最后一个父节点开始,把左右子节点比较,取大值,记得把小值给回曾经的父节点
删除堆,从根节点开始,与最后一个节点交换,并不断调整调整
代码
//堆排序
//选择排序
#include<stdio.h>
typedef int ElementType;
void Print_Array(ElementType A[],int N)
{
printf("\n");
for(int i=0;i<N;i++)
printf("%d ",A[i]);
}
void Swap(int *X,int *Y)
{
int tmp = *X;
*X = *Y;
*Y = tmp;
}
void PercDown(ElementType A[],int p,int N)
{{/* 改编代码4.24的PercDown( MaxHeap H, int p ) */
/* 将N个元素的数组中以A[p]为根的子堆调整为最大堆 */
int Parent,Child;
ElementType X;
X = A[p]; /* 取出根结点存放的值 */
for(Parent = p;(Parent*2+1)<N;Parent=Child) /*(Parent*2+1)左子树,原来最大堆那里左子树是parent*2,因为parent从1开始,0是最为哨兵的*/
{
Child = Parent * 2+1;
if((Child != N-1) && (A[Child]<A[Child+1]))/*判断左儿子是否是最后节点*/
Child ++;/*指向较大的儿子*/
if(X>=A[Child]) break;/* 找到了合适位置 */
else
A[Parent] = A[Child];//找到最大的父节点的位置
}
A[Parent] = X;
}
void Heap_Sort(ElementType A[],int N)
int i;
for(i=N/2-1; i>=0;i--)/*这里要变成N/2-1,因为i要有等于0的情况,如果不-1,i最小为1*/
PercDown(A,i,N);/*建立最大堆 */
for(i=N-1;i>0;i--)
{
Swap(&A[0],&A[i]);/*根元素和最后一个元素互换*/
PercDown(A,0,i);/*继续调整*/
}
}
int main()
{
int arr[5] = {3,8,9,7,1};
Print_Array(arr,5);
Heap_Sort(arr,5);
Print_Array(arr,5);
return 0;
}
O(NlogN)
O(1)的空间复杂度