“选择”排序

       何为选择排序?其实选择排序是最好理解的排序,就是每次遍历数组,从中选出一个最大的和一个最小的数,把最小的数放到数组的最左边,最大的数放到数组的最右边,两边缩小一个位置(因为最大和最小的数已经排好了),再遍历剩下的数找出最小的和最大的数放到第二个位置和倒数第二个位置,以此类推,最终就能使数组有序。

动图如下:

        但是这里的动图演示的是每次找出数组中的一个最小值放到左边,其实遍历一遍是可以同时找到最大值和最小值的,这样的话效率会高一倍。这个看个人喜好吧,想一次选最大和最小或者一次就选一个最小都是可以的。

        毫无疑问,选择排序需要执行的次数是:第一次遍历数组选最小值需要n次,第二次遍历数组找最小值需要n-1次,以此类推,最后递减到1次,这是一个等差数列的求和,所以时间复杂度为经典的O(N^2), 而且选择排序对数据敏感性不高,就是无论是什么情况的数据它的时间复杂度都是O(N^2),因为即使数组本来就是有序的,但是每一次仍然需要遍历剩下的所有数才能选出最小的。所以选择排序是最“稳定”的排序,但是这个“稳定”是一个调侃的词。由于选择排序的效率是非常稳定的慢,所以在实际中很少被使用。

参考代码如下:

//这里的代码是每一次同时选出一个最大值和最小值的,
//参数n代表数组的元素个数
void SelectSort(int* a, int n)
{
	assert(a);
	//左下标
	int left = 0;
	//右下标
	int right = n - 1;
	int i = 0;

	//只要左右下标还没有相遇,就说明两个下标之间
	// 还有没排好的数据,一直循环到left==right
	while (left < right)
	{
		//可以设待排序的数组中的任意一个数的下标作为最大值或者最小者
		// 的下标,因为后面比较的时候会被真正的最大最小值换掉,但是不
		//能用不是数组内的值作为基准
		int mini = left;
		int maxi = left;
		//遍历一遍选出最大值和最小值的下标,由于left作为基准了,所以
		//i可以直接从left+1开始,不用跟自己比较了
		for (i = left + 1; i <= right; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}
		//最小值换到左边
		Swap(&a[left], &a[mini]);
		//但是这里需要注意,因为left可能就是最大值的下标
		//所以在把最小值换到左边的时候可能把最大值从左边
		//换到了最小值的位置,所以如果找到的最大值的下标是
		//left,即left==maxi的话,经过了上面的交换,最大
		//值就被交换了,需要修正一下最大值的下标,此时它应该
		//在原来最小值的位置mini上,所以maxi=mini修正一下。
		//如果每次只找一个最小值的话就不会出现这种需要修正的
		//情况咯
		if (left == maxi)
		{
			maxi = mini;
		}
		//最大值换到右边
		Swap(&a[right], &a[maxi]);
		//左边最小,右边最大之后下一次就不用对这两个数排序了
		//所以两边缩小一个位置,即left++,right--,再从剩
		//下的数中遍历找最大和最小值,迭代走下去,直到left和right相遇
		++left;
		--right;
	}

}

        这个简单的选择排序,你学会了吗?如果对你有帮助,那就点一下小心心,顺便点点关注呗!后面还会出不同的排序算法哦!!!

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值