2.选择排序(直接选择排序和堆排序)

选择排序的基本思想:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已拍好序子表的最后,直到全部记录排序完毕。

由于选择排序方法每一趟总是从无序区中选出全局最小(最大)的关键字,所以适合于从大量的记录中选择一部分排序记录。

1.直接选择排序

基本思想:n个记录的直接选择排序可经过n-1趟直接选择排序得到有序结果。(从小到大,每次将a[i]到a[n]中最小的值找到,并放到a[i]处

void Select_sort(int a[],int size)
{
	int i,j,k;
	for (i=0;i<size;i++)			//做第i趟排序
	{
		k=i;
		for (j=i+1;j<size;j++)		//在当前无序区选择最小的记录
		{
		
			if(a[j]<a[k])
			{
				k=j;				//k记下目前找到的最小关键字所在的位置。
			}
			if (k != i)
			{
				a[i]^=a[k];			//一趟排序仅交换一次。
				a[k]^=a[i];
				a[i]^=a[k];
			}
		}
	}
}
直接选择排序是一个不稳定的排序方法,该方法得到平均时间复杂度为O(n^2)。

2.堆排序

堆排序是一种树形选择排序方法,它的特点是:在排序过程中,将无序区看成一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大的记录。

二叉堆的特性:
1、父结点的键值总是>=(<=)任何一个子结点的键值

2、每个结点的左右子树都是二叉堆

void sift(int a[],int low,int high)//构造初始堆
{
	int i=low,j=2*i;				//i为父结点,j为子结点的左孩子。
	int temp = a[i];				//将父结点的值保存到临时变量中
	while (j <= high)				//保证j在有效范围内
	{
		if (j<high && a[j]<a[j+1])	//比较两个孩子值的大小,获取值最大的下表。左孩子大则j=2*i,右孩子大则j=2*i+1。
		{
			j++;
		}
		if (temp<a[j])				
		{
			a[i]=a[j];				//比较父结点与最大孩子结点值的大小,如果孩子结点值大,则将a[j]调整到父结点。
			i=j;					//修改i值(父结点下标),以便继续向下筛选。
			j=2*i;					//修改j值(子结点下标)
		}
		else break;
	}
	a[i]=temp;
}

void HeapSort(int a[],int size)
{
	int i;
	int temp;
	for (i=size/2;i>=1;i--)			//循环建立初始堆
	{
		sift(a,i,size);
	}
	for (i=size;i>1;i--)			//将最后一个元素同当前区间内a[1]对换。
	{
		temp = a[1];
		a[1] = a[i];
		a[i] = temp;
		sift(a,1,i-1);				//筛选a[i]结点,得到i-1个结点的堆。
	}
}
堆排序是一种不稳定的排序算法,该算法的平均时间复杂度为O(nlogn)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值