C语言排序算法之选择排序(直接选择排序,堆排序)
#define _CRT_SECURE_NO_WARNINGS
#include
//打印数据
void Printf(int* a, int n)
{
for (int i = 0; i < n; ++i)
{
printf("%d ", a[i]);
}
}
//交换,传地址
void Swap(int* child, int* parent)
{
int tmp = *child;
*child = *parent;
*parent = tmp;
}
//向下调整算法
//从根节点开始,如果是建立小堆选出左右孩子中小的那一个,跟父亲比较,如果比父亲小就交换
void AdjustDwon(int* a, int n, int root)//建小堆
{
int parent = root;//父亲节点
int child = parent * 2 + 1;//默认是左孩子
while (child < n)//叶子节点下标不会超过数组总下标数n
{
//选出左右孩子中最小的那一个
if (child+1 < n&& a[child + 1] < a[child])
{
child += 1;//用a[child]与父亲节点a[parent]比较
}
if (a[child] < a[parent])
{
//交换,传地址
Swap(&a[child], &a[parent]);
//交换后,将child,作为根节点继续向下调整,持续建堆
parent = child;
//新的左孩子
child = parent * 2 + 1;
}
else
{
break;//如果不用交换,直接结束循环
}
}
}
//堆的建立
//大堆要求:树中所有的父亲都>=孩子,根是最大的
//小堆要求:书中所有的父亲都<=孩子,根是最小的
//建大堆排升序,建小堆排降序
//建堆的时间复杂度是O(N);
void HeapSort(int *a,int n)
{
//找父亲节点
for (int i=(n-1-1)/2;i>=0;--i)
{
//向下调整算法
AdjustDwon(a,n,i);
}
//大堆或小堆建立完毕,排序
//用主根节点与最后一个节点交换位置
int end = n - 1;
while (end>0)
{
//交换,传地址
Swap(&a[0],&a[end]);
//继续向下调整
AdjustDwon(a,end,0);
--end;
}
}
//选择排序—堆排序
int main()
{
int a[10] = {9,2,5,4,3,1,6,7,8,0};
//堆的建立
HeapSort(a,sizeof(a) / sizeof(a[0]));
//打印数据
Printf(a,sizeof(a) / sizeof(a[0]));
return 0;
}