排序算法(2) 选择排序

选择排序

1. 算法原理

对于使用选择排序从小到大排序一个数组中的元素:
将一个数组分为已排序区和未排序区,每次遍历未排序区寻找区间内元素最小值,并将最小值元素与未排序区第一个元素互换,并将未排序区第一个位置划入已排序区。

2. 算法模拟

在这里插入图片描述

3. 算法分析

(1) 排序稳定性

由算法模拟图示可以看出数组中两个数值为4的元素,其排序前相对位置与排序后相对位置不同,这是由于当待排序数组a[i…n]中可能存在关系:
当 a [ i ] > a [ k ] , 且 m i n = a [ k ] 时 , 存在 a [ j ] = a [ i ] 且 i < j < k 当a[i] > a[k],且min=a[k]时,存在a[j]=a[i]且i<j<k a[i]>a[k],min=a[k],存在a[j]=a[i]i<j<k
通俗来讲就是,相同的两个元素,靠前的一位可能会被交换到靠后的一位的后面,原因是靠后一位的后面可能有比这两个元素数值还要小的元素
因此选择排序算法是不稳定的

(2) 时间复杂度

最坏时间复杂度
数组倒序时,需要遍历数组个数次,即n次,每次遍历还需要遍历待排序区数组个数次,对于第一个元素,该数字为n次。因此,最坏时间复杂度为:
O ( n 2 ) O(n^2) O(n2)
最优时间复杂度
数组顺序时,需要遍历数组个数次,即n次,每次遍历需要遍历待排序区数组个数次,对于第一个元素,该数字为n次。因此,最优时间复杂度为:
O ( n 2 ) O(n^2) O(n2)

4. 算法证明

接下来用循环不定式证明选择排序算法正确性:

初始:当i = 1时,已排序区为空,待排序区为nums[1…n],循环遍历找到最小值nums[ind],交换nums[1]与nums[ind]的位置,交换后nums[1]为待排序区nums[1…n]的最小值,即为原数组nums[1…n]的最小值,i自增1,在下一次循环时已排序区变成nums[1…1],待排序区变成nums[2…n]。

保持:当已排序区为nums[1…i - 1],待排序区为nums[i…n]时,循环遍历找到最小值nums[ind],交换nums[i]与nums[ind]的位置,交换后nums[ind]为待排序区nums[i…n]的最小值,同时由于nums[i - 1]是nums[i - 1…n]的最小值,因此满足:
n u m s [ i − 1 ] ≤ n u m s [ i ] nums[i - 1] \leq nums[i] nums[i1]nums[i]
i自增1,在下一次循环时已排序区变成nums[1…i - 1],待排序区变成nums[i…n]。

终止:当i = n + 1时,循环结束,已排序区为nums[1…i - 1]即为nums[1…n],即为原数组nums[1…n]的已排序版本。

证毕。

5. 代码演示

void select_sort(int *nums)
{
	for(int i = 1; i <= n; ++i)
	{
		int ind, minn = 0x3f3f3f3f;
		for(int j = i; j <= n; ++j)
		{
			if(nums[j] < minn)
			{
				minn = nums[j];
				ind = j;
			}
		}
		swap(nums[i], nums[ind]);
	}
	return;
}
  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值