vlambda博客
学习文章列表

选择排序算法(从粗糙到精细)

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾或者前段。我编写的程序选择的是找最小值放置数组前端。

平均时间复杂度:O(n2 ,空间复杂度:O(n),该排序不稳定。

第一次编码(整理基本思路):

public class test { public static void main(String[] args) { int[] arr={12,5,6,8,24,75,89,34,2,66};//要排序的无序数组 int minPos=0;//假设最小值的下标位置是0 for(int j=1;j<arr.length;j++)//从数组下标为1开始比较 { if(arr[j]<arr[minPos]) minPos=j;//交换下标值 }
System.out.println(arr[minPos]);//进行中间值测试,看是否找出最小值
int temp=arr[0];//利用中间量,让数组第一个数与找到的最小值 arr[0]=arr[minPos]; arr[minPos]=temp;
for(int i=0;i<arr.length;i++)//测试经过一轮排序后的数值 { System.out.print(arr[i]+" ");    }  }}

运行结果:

第二次编码(实现排序功能):

public class test { public static void main(String[] args) { int[] arr={12,5,6,8,24,75,89,34,2,66};//要排序的无序数组
for(int i=0;i<arr.length;i++)//外层遍历是为了找到每次遍历的起始位置i { int minPos=i;//设定最小值的下标为i for(int j=i+1;j<arr.length;j++)//起始位置i的下一个开始比较,即从i+1开始 { if(arr[j]<arr[minPos]) minPos=j;//交换最小值的下标 } System.out.println("第"+i+"轮找到的最小值:"+arr[minPos]);//进行中间值测试,看每一轮找出的最小值 int temp=arr[i];//利用中间量,让数组第一个数与找到的最小值 arr[i]=arr[minPos]; arr[minPos]=temp; }
for(int i=0;i<arr.length;i++)//打印经过i轮排序后的数组 { System.out.print(arr[i]+" "); } }
}

运行结果:

选择排序算法(从粗糙到精细)

第三次编程(优化代码):

public class test { public static void main(String[] args) { int[] arr={12,5,6,8,24,75,89,34,2,66};
for(int i=0;i<arr.length-1;i++)//不难发现外层循环运行了一次,所以arr.length-1 { int minPos=i; for(int j=i+1;j<arr.length;j++) { minPos=arr[j]<arr[minPos] ? j:minPos;//可以利用条件运算符去简化代码 } System.out.println("第"+i+"轮找到的最小值:"+arr[minPos]); int temp=arr[i]; arr[i]=arr[minPos]; arr[minPos]=temp;    } for(int i=0;i<arr.length;i++) { System.out.print(arr[i]+" "); } }}

优化代码:

1、不难发现,排序时外层循环多执行了一次,这是个要注意的小地方。在面试时,写for(int i=0;i<arr.length-1;i++)会给面试官留下会是不同的印象。

选择排序算法(从粗糙到精细)

2、可以利用条件运算符对代码进行简化,其实简化不简化都一样,因为处理逻辑是一样的。

第四次编程(继续优化代码):

这次优化是把每经过一轮排序后的结果都打印出来,方便观察。

public class test { public static void main(String[] args) { int[] arr={12,5,6,8,24,75,89,34,2,66};
for(int i=0;i<arr.length-1;i++)//不难发现外层循环运行了一次,所以arr.length-1 { int minPos=i; for(int j=i+1;j<arr.length;j++) { minPos=arr[j]<arr[minPos] ? j:minPos;//可以利用条件运算符去简化代码 } int temp=arr[i];//利用中间量,让数组第一个数与找到的最小值 arr[i]=arr[minPos]; arr[minPos]=temp; System.out.println(); System.out.println("经过第"+i+"次循环之后,数组的内容是:"); for(int k=0;k<arr.length;k++)//打印经过i排序后的数组 { System.out.print(arr[k]+" "); } }
System.out.println(); System.out.println("最终排序结果是:"); for(int k=0;k<arr.length;k++)//打印最终排序结果 { System.out.print(arr[k]+" "); } }}

运行结果:

第五次编程(继续优化代码):

我把打印结果和中间量交换的行为都封装成函数,因为之后的其它排序也会用到,索性封装成函数用到的时候调用即可。

public class test { public static void main(String[] args) { int[] arr={12,5,6,8,24,75,89,34,2,66};
for(int i=0;i<arr.length-1;i++)//不难发现外层循环运行了一次,所以arr.length-1 { int minPos=i; for(int j=i+1;j<arr.length;j++) { minPos=arr[j]<arr[minPos] ? j:minPos;//可以利用条件运算符去简化代码 } exchange(arr,i,minPos);//这里要区分开各自对应的参数
System.out.println(); System.out.println("经过第"+i+"次循环之后,数组的内容是:"); print(arr); }
System.out.println(); System.out.println("最终排序结果是:"); print(arr); }
static void print(int arr[])//封装函打印函数 { for(int k=0;k<arr.length;k++) { System.out.print(arr[k]+" "); } }
static void exchange(int arr[],int i,int j)//封装交换函数 { int temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; }}

其实这个排序算法还能继续优化,这个程序是遍历一次找出最小值并将其放置数组前端去,优化的思路是遍历一次同时找出最小值和最大值分别放置数组前端和后端去,这样我们程序遍历的次数会减少一半,即由arr.length-1次变成(arr.length-1)/2次。好了,下次有空再写。


我将会持续更新浅学《数据结构与算法》系列,以后算法的编写都用JAVA写,我能坚持下去吗?不能。。。


ColorC1Troupe

万     物     皆     可     递     归