返回 Java编程练习目录
穷举算法、枚举算法或蛮力算法等,在解决问题优先的指导方针下,是很有意义的。
1.粗暴到底
嗨,baby,把待排序的数组
int[] arr按照非降序(前面的数小于或等于后面的数)排列.
最为简单粗暴的方式:
- 奢侈地使用辅助空间arr2,
- 用眼睛从头到尾地扫描一次arr,从中选择一个最小的元素,而且放入arr2[0],而且在arr原位置打个叉(或标记为Max);
- 依此类推,扫描n次。
package algorithm.sorting;
public class MySelectionSort extends IntSort{
@Override public int[] sort(int[] arr){
int[] arr2 = new int[arr.length];//奢侈地使用一个辅助空间arr2
for(int i=0;i<arr2.length;i++){
arr2[i] = scan(arr);
}
return arr2;
}//end sort
/**
* 用眼睛从头到尾地扫描一次arr,从中选择一个最小的元素并放入arr2[0],
* 将arr原来最小的元素位置标记为Max;
*/
private int scan(int[] arr){
int min=arr[0];
int index =0;
for(int i=0;i<arr.length;i++){
if(min>arr[i]) {
min=arr[i];
index=i;
}
}
arr[index]=0X7fffffff;
return min;
}
}
你还能够再粗暴一点吗?
- 辅助空间arr2,空间复杂度为O(n)。就地 (in-place) 排序指排序时仅借用常数个辅助内存空间即空间复杂度为O(1),而排序工作主要在数组arr自己的空间中通过元素交换位置或移动位置完成。有没有用空间换时间的例子?
- 在选择出一个最小的元素后,我们能不能把剩下的数拷贝到辅助空间arr3中,据说有些人用筛子解题。
- 为什么把最小元素的位置标记为int的最大值0X7fffffff,我找出当前arr的Max不行吗?
好吧,我们上面的选择排序MySelectionSort已经够了。 sort的循环一个n,循环中调用的scan一个n,总共需要比较n*n次,时间复杂度为O(n
2)。
2.简单选择排序
简单选择排序或
选择排序(SelectionSort),在arr中拿出一个位置(第一趟排序拿出arr[0]),向后面扫描过去,遇到比自己当前值小的就交换。如{5,7,6,2,3,8,4,1,9},第一趟中先将5与2换位,再将2与1换位,结果为{1,7,6,5,3,8,4,2,9}。第二趟,以arr[1]为起点,交换交换得到{1,2,7,6,5,8,4,3,9}...
练习11-5:写出{5,8,5,4,3,5,2,7,1,9}在第一、二趟排序后的结果。编写SelectionSort的sortDeme(),打印每一趟排序的结果。
package algorithm.sorting;
import static tips.Print.*;//<span style="font-family: Arial, Helvetica, sans-serif;">pln(int[])</span>
/**
* SelectionSort.java.
* 简单选择排序。是蛮力算法、本地排序、基于比较的排序。时间复杂度为O(n*(n-1)/2)=O(n2)
* @author yqj2065
* @version 0.1
*/
public class SelectionSort extends IntSort{
/**
* 简单选择排序,选择最小元素-交换
*/
public static void sortDeme(){
int[] arr = new int[]{5,7,6,2,3,8,4,1,9};
p("排序前:");
pln(arr);
pln("排序...");
for(int i=0; i< arr.length; i++){
int min =arr[i];//可以省略这一辅助空间
for(int j=i+1; j< arr.length; j++){
if( min > arr[j]){ //选择最小的数
min =arr[j];
IntSort.swap(arr ,i, j);
}//end if
}
p("第"+i+"趟:");
pln(arr);
}
}//end sort
@Override public int[] sort(int[] arr){
//
}
}
排序前:[5, 8, 5, 4, 3, 5, 2, 7, 1, 9]
排序...
第0趟:[1, 8, 5, 5, 4, 5, 3, 7, 2, 9]
第1趟:[1, 2, 8, 5, 5, 5, 4, 7, 3, 9]
第2趟:[1, 2, 3, 8, 5, 5, 5, 7, 4, 9]
第3趟:[1, 2, 3, 4, 8, 5, 5, 7, 5, 9]
第4趟:[1, 2, 3, 4, 5, 8, 5, 7, 5, 9]
第5趟:[1, 2, 3, 4, 5, 5, 8, 7, 5, 9]
第6趟:[1, 2, 3, 4, 5, 5, 5, 8, 7, 9]
第7趟:[1, 2, 3, 4, 5, 5, 5, 7, 8, 9]
第8趟:[1, 2, 3, 4, 5, 5, 5, 7, 8, 9]
第9趟:[1, 2, 3, 4, 5, 5, 5, 7, 8, 9]
练习11-5:编写@Override public int[] sort(int[] arr)
提示:剩下的最后一个元素不动;
思考:上面第7趟已经完成排序,怎样避免多余的趟?
结语:
简单选择排序是蛮力算法、就地排序、基于比较的排序。
选择排序的时间复杂度为O(n*(n-1)/2)=O(n2),比较次数不到前面的例子MySelectionSort的n*n次的一半——虽然都是O(n2)。