冒泡排序真的是太烦了,需要一直两两比较,将最大的浮动到上面的位置去,可能有人在想,我为什么不记住最大或最小的位置,遍历完成之后只需要交换最大或最小的和对应的位置不就可以了,省去了来回串来串去的烦恼。
确实是这个道理,这个方法就是选择排序。
我们使用例子演示一下
首先从第一位遍历 我们假设当前最小的是第一个
第一位跟第二位比较,第二位更小,记录的序号更新为1
最小值变为3,第二位,和第三位继续比较 1<3 纪录最小值序号为2
第三位和第四位比较 1<7 第三位跟第五位比较 1<6 第三位和第六位比较 1<2 所以序号一直不变
我们得到了最小的值,将第一位和最小值位置的数据交换
而后以此类推,开始获取第二小的数,将第二个元素视作当前基准得到的结果如下:
初始最小的位置记录是1,更改顺序为1-->5 第二小位置找到,更换元素
交换元素
最终我们得到的结果是
再执行一次之后已经成功排序。我们来分析一下思路:
1.需要使用一个外层循环控制当前第几小的数的位置
2.需要一个内层循环遍历其余的所有元素,找到当前最小的值
3.需要额外的变量记录位置和交换元素
实际代码:(实际例子就使用java写了,比较通用的写法,其他程序也差不多,推荐的在线网站https://tool.lu/coderunner/)
class Untitled {
public static void main(String[] args) {
int[] array = new int[]{4,3,1,7,6,2}; //我们的需要排序的数组
int index=0; //临时变量 记录位置的
int temp; //临时变量 用于交换时候保存临时值的
for(int i=0;i<array.length-1;i++)
{
index=i; //当前位置作为基准
for(int j=i+1;j<array.length;j++) //内层遍历从当前位置+1到最后一个元素
{
if(array[j]<array[index]) //每次跟基准比较 小于就更新基准
{
index=j;
}
}
//得到了当前最小值的位置
if(index!=i) //判断了一下最小值位置是否为当前位置 是的话就不用交换了
{
temp = array[index];
array[index]=array[i];
array[i]=temp;
}
}
//输出所有元素
for(int ele:array)
{
System.out.println(ele);
}
}
}
我们再次分析一下时间复杂度和空间复杂度。
随着问题n规模的扩大,我们需要的循环次数是(也是等差序列) (n-1) +(n-2)+.....+1
即n(n-1)/2 = (n²-1)/2 最高的多项式为n²,即O(n²);
随着问题n规模的扩大,并不影响空间的使用,依旧是那两个临时变量,所以空间复杂度为O(1);
稳定排序与不稳定排序
但是上边突然涉及了一个什么稳定不稳定的问题,冒泡是稳定排序,选择是不稳定排序,实际上指的是排序算法是否会影响相同元素的顺序。
假设有以下的数字数组
经过冒泡排序之后为
两个相同元素的相对前后位置并没有发生变换,因为每次都是两两比较相同的元素不会发生位置前后变化
但是经过选择排序之后是这样的顺序:
。。。。。最终的结果为
虽然排序结果看着是一样,但是很多的应用场景要求排序的同时相同数字的的相对位置不发生变化。
这就是稳定与不稳定原因。