【排序算法】选择排序

一、定义:

        选择排序(Selection sort)是一种简单直观的排序算法。第一次从待排序的数据(元素)中选出最小(或最大)的一个元素,存放在数组的起始位置,然后再从剩余的没有排序的元素中寻找到最小(大)元素,然后放到已排序的数组的末尾。以此类推,直到全部待排序的数据元素的个数为零。对于数据量大的排序就没啥用了,排的比较慢。

二、原理:

1、 对于待排序的数组,我们从首元素开始,将首元素的下标用min记住,认为目前是最小的元素的下标;

2、开始遍历min所指向的元素后面的元素与每个元素和下标min所指向的元素进行比好,当遇到某个元素比min下标所指向的元素时,min里记录其下标,直到遍历结束为止。

3、此时找到了最小元素,和首元素(开始位置的元素)进行交换

4、首元素排序好,认为第一个元素为排序好的元素,进入第二次遍历,从未排序的元素开始(即该数组的第二个元素)将其下标用min记住,重复2-3,直到整个数组排序完成。

 动图用不了,画了遍历第一次的情况:

 三、时间复杂度:

无论最好还是最坏的情况都是O(N^2)

因为就算你是有序的也要遍历一遍,确认是否是最小的元素

 相同的100万个随机数据排序,选择排序堆排希尔排序进行比较效率,看结果就知道 为啥说选择排序用到的不多了吧,而且其稳定性也差;

四、代码:

这个是比较简单且没坑的写法!接下来还有一个思路

//交换数据
void Swp(int* p1, int* p2)
{
	assert(p1 && p2);
	int tmp = *p2;
	*p2 = *p1;
	*p1 = tmp;
}
//选择排序:
void SelectSort(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		int min = i;
		for (int j = i; j < n; j++)
		{
			if (a[j] < a[min])
			{
				min = j;
			}
		}
		Swp(&a[min], &a[i]);
	}

}

双向法👉一次性排好2个,一个maxi,一个mini,初始状态时,maxi和mini一起出发✨

接下来就是和上面一样的思路,分别进行比较,找到各自对应的最大值最小值 

 最小的元素到了首位置(begin),最大的到了尾位置(end);然后对2者中间当成未进行排序的数据,再次重复进行上述操作;此时从未排序的数组 从 下标1(begin+1)开始到下标4(end--)的位置结束;依次类推;

注意喽!!!实现这个时会出现一些问题哦!!不是这个方法不行,是个人没有考虑到方方面面!就是这个方法需要注意的地方

 一般人写好一次排序的代码可能会是这样的写的,从end+1开始比较的,一看是和自己比较没有意义,当然如果没有就算了,建议先完善好第一趟,再去考虑整体代码,减低错误;ok 回归正轨;下面听我分析  go——>✨✨✨✨✨✨✨✨

写了一个例子(单趟啊),如果刚好出现这种情况时,是不是就和我想要的结果不一样了,交换以后又回到了交换前,此时不得发现我们得考虑maxi在头位置不变的情况那么是不是当 maxi==beginmin = end  时是不是就是双方互相交换

 本来么,一开始想到的是直接换2个元素,但是仔细一想,我是指向的下标,那我是不是给maxi的指向改下;互换一下就可以了!!👉👉👉👉这样写憋说 还真有好处👍👍👍👍👍👍

✨好了,竟然我们能考虑了相等,为啥不考虑mini不在end的情况呢??咦~~~对哦,mini不在end的位置是怎么交换的??假设哈  🧑‍🎓🧑‍🎓咋看??看下结果🫰 maxi指向的还是最大的

这个时候我们在将maxi指向的元素和end(最后的位置)进行交换 问题就这么解决了!!!!!!!!!!!!

不知道有人会不会想如果minibegin的位置(下标为0)呢???其实不用考虑了,因为我们考虑maxibegin 是因为我们先将mini指向的元素头位置交换导致maxi丢掉了正确的指向,而mini指向begin时,不就是自己和自己交换么,不会影响双方的指向,当然不要考虑;没必要么

✨👉代码实现:

//交换数据
void Swp(int* p1, int* p2)
{
	assert(p1 && p2);
	int tmp = *p2;
	*p2 = *p1;
	*p1 = tmp;
}

void SelectSort(int* a, int n)
{
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int maxi = begin;
		int mini = begin;
		for (int i = begin + 1; i <= end; i++)
		{
			if (a[maxi] < a[i])
			{
				maxi = i;
			}
			if (a[mini] > a[i])
			{
				mini = i;
			}
		}
		Swp(&a[mini], &a[begin]);
		if (maxi == begin)
		{
			maxi = mini;
		}
		Swp(&a[maxi], &a[end]);
		begin++;
		end--;
	}
}

好了,就到这了,还是那句话,排序算法👉先写单趟,再写整体;先写内部再写外部;先修心再修身❤️🫰

感                      谢                 观                       看

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值