今天讲一下选择排序和冒泡排序,这是两种很简单的排序算法。
一、冒泡排序法(BubbleSort)
从数组的第一个元素开始,进行两两比较,较大的移到前面,较小的移到后面,经过一轮比较后,最大的数将会被移动到最后面。
最无脑版本:
public int[] bubbleSort(int[] arr){
for(int i = 0; i < arr.length; i++){
for(int j = 0;j < arr.length-1; j++){
if(arr[j] > arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
}
}
//打印数组,查看排序过程 /*for (int ii : arr) { System.out.print(ii+"->"); } System.out.println("\b\b");*/
}
return arr;
}
去掉注释代码,程序输出:
5->2->7->3->8->1->6->9
2->5->3->7->1->6->8->9
2->3->5->1->6->7->8->9
2->3->1->5->6->7->8->9
2->1->3->5->6->7->8->9
1->2->3->5->6->7->8->9
1->2->3->5->6->7->8->9
1->2->3->5->6->7->8->9
这个版本有两个大问题:
- 假设我们把每次内循环完成称为“一轮”,每一轮过后,数组
arr
的最后一位元素已经是最大的了,而我们还是把它进行了比较,所以内层循环的“上限”需要修改。 - 通过上面输出我们可以发现,最后三轮比较没有交换任何元素,也就是说已经排序完成,可是我们的程序还是在“傻傻的”运行,所以我们应该设置一个flag,当检测到数组排好序后,终止程序。
修改版:
public int[] bubbleSort(int[] arr){
boolean swapNone;
for(int i = 0; i < arr.length; i++){
swapNone = true; //初始化flag for(int j = 0;j < arr.length-1-i; j++){
//这里注意是j < arr.length-1-i if(arr[j] > arr[j+1]){
int temp = arr[j+1];
arr[j+1] = arr[j];
arr[j] = temp;
swapNone = false;//记录交换 }
}
//如果无交换,结束 if(swapNone)break;
//打印数组,查看排序过程 /*for (int ii : arr) { System.out.print(ii+"->"); } System.out.println("\b\b");*/
}
return arr;
}
去掉注释代码,程序输出:
5->2->7->3->8->1->6->9
2->5->3->7->1->6->8->9
2->3->5->1->6->7->8->9
2->3->1->5->6->7->8->9
2->1->3->5->6->7->8->9
1->2->3->5->6->7->8->9
完美!
那么,冒泡排序的时间复杂度是O(n^2),空间复杂度是O(1)。
一般来说,冒泡排序是稳定的排序算法,但是如果比较条件中 arr[j]<arr[j+1]的“<”改为“<=”,那么冒泡排序就不稳定了。关于稳定性分析,我会在其他文章讲到。
二、选择排序法(SelectionSort)
选择排序的思路,和人类的思维是很相似的:先找出最小的来,放在第一位;然后再找出第二小的,放到第二位;再找出第三小的,以此类推。
代码如下:
public int[] selectionSort(int[] arr){
for(int i = 0; i < arr.length; i++){
//第i轮查找,找出第i小的,放到第i位 int minIndex = i;
//从i+1开始和第i个进行比较 for(int j = i+1; j < arr.length-1; j++){
//n个数共需要比较n-1次,最大的数自动被“挤”到最后 if(arr[j] < arr[minIndex]){
minIndex = j;
}
}
if(minIndex != i){
int temp = arr[minIndex];
arr[minIndex] = arr[i];
arr[i] = temp;
}
//打印数组,查看排序过程 /*for (int ii : arr) { System.out.print(ii+"->"); } System.out.println("\b\b");*/
}
return arr;
}
去掉注释代码,程序输出:
1->5->2->7->3->8->9->6
1->2->5->7->3->8->9->6
1->2->3->7->5->8->9->6
1->2->3->5->7->8->9->6
1->2->3->5->6->8->9->7
1->2->3->5->6->7->9->8
1->2->3->5->6->7->8->9
完美!
那么,选择排序的时间复杂度是O(n^2),空间复杂度是O(1)。
稳定性不敢讲,有大佬知道的,可以在评论区告诉我。大家也可以自行百度~~~