经典排序之冒泡排序和快速排序

Posted 奔跑在梦想的道路上

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经典排序之冒泡排序和快速排序相关的知识,希望对你有一定的参考价值。

一、冒泡排序

冒泡排序(Bubble Sort)是一种比较经典的排序算法。

之所以称为“冒泡排序” ,是因为在排序中,越大(降序排列)或越小(升序排列)的相邻元素会经由交换逐渐“浮”到前面,有如 水中浮出的水泡,故形象地命名为“冒泡排序”。

冒泡排序主要对相邻的两个元素进行比较。

在时间复杂度方面,若数据集的初始状态是正序的,一趟扫描即可完成排序。这时,排序中的比较 次数和移动次数均达到最小值,其时间复杂度O(N)。

若数据集的初始状态是反序的,需要进行n-1趟排序;每趟排序要进行n-i次关键字的比较 (1≤i≤n-1)。在这种情况下,比较和移动次数均达到最大值,其时间复杂度为O(n2)。

总的来说,冒泡排序的平均时间复杂度为O(n2)。

我们接下来通过代码来看冒泡排序。 

import java.util.Arrays;

/**
  * 未优化的冒泡排序
  */
public class Demo1 {
public static void main(String[] args) {
int[] arr=new int[]{15,32,14,86,54,78,36};
System.out.println("排序前的数组:"+Arrays.toString(arr));
System.out.println("排序中:");
int k=0;
for(int j=0;j<arr.length-1;j++){
for(int i=0;i<arr.length-1;i++){
if(arr[i]>arr[i+1]){
int temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
System.out.println("第 "+(++k)+" 次:"+Arrays.toString(arr));
}
}
System.out.println("排序后的数组:"+Arrays.toString(arr));
}

上述代码运行结果如下:

排序前的数组:[15, 32, 14, 86, 54, 78, 36]  

排序中:

第 1 次:[15, 32, 14, 86, 54, 78, 36]

第 2 次:[15, 14, 32, 86, 54, 78, 36]

第 3 次:[15, 14, 32, 86, 54, 78, 36]

第 4 次:[15, 14, 32, 54, 86, 78, 36]

第 5 次:[15, 14, 32, 54, 78, 86, 36]

第 6 次:[15, 14, 32, 54, 78, 36, 86]

第 7 次:[14, 15, 32, 54, 78, 36, 86]

第 8 次:[14, 15, 32, 54, 78, 36, 86]

第 9 次:[14, 15, 32, 54, 78, 36, 86]

第 10 次:[14, 15, 32, 54, 78, 36, 86]

第 11 次:[14, 15, 32, 54, 36, 78, 86]

第 12 次:[14, 15, 32, 54, 36, 78, 86]

第 13 次:[14, 15, 32, 54, 36, 78, 86]

第 14 次:[14, 15, 32, 54, 36, 78, 86]

第 15 次:[14, 15, 32, 54, 36, 78, 86]

第 16 次:[14, 15, 32, 36, 54, 78, 86]

第 17 次:[14, 15, 32, 36, 54, 78, 86]

第 18 次:[14, 15, 32, 36, 54, 78, 86]

第 19 次:[14, 15, 32, 36, 54, 78, 86]

第 20 次:[14, 15, 32, 36, 54, 78, 86]

第 21 次:[14, 15, 32, 36, 54, 78, 86]

第 22 次:[14, 15, 32, 36, 54, 78, 86]

第 23 次:[14, 15, 32, 36, 54, 78, 86]

第 24 次:[14, 15, 32, 36, 54, 78, 86]

第 25 次:[14, 15, 32, 36, 54, 78, 86]

第 26 次:[14, 15, 32, 36, 54, 78, 86]

第 27 次:[14, 15, 32, 36, 54, 78, 86]

第 28 次:[14, 15, 32, 36, 54, 78, 86]

第 29 次:[14, 15, 32, 36, 54, 78, 86]

第 30 次:[14, 15, 32, 36, 54, 78, 86]

第 31 次:[14, 15, 32, 36, 54, 78, 86]

第 32 次:[14, 15, 32, 36, 54, 78, 86]

第 33 次:[14, 15, 32, 36, 54, 78, 86]

第 34 次:[14, 15, 32, 36, 54, 78, 86]

第 35 次:[14, 15, 32, 36, 54, 78, 86]

第 36 次:[14, 15, 32, 36, 54, 78, 86]

排序后的数组:[14, 15, 32, 36, 54, 78, 86] 

上述是未优化的结果 ,优化后的代码如下:

import java.util.Arrays;

public class Demo2 {
static int k=0;
static void bubleSort(int[] arr){
boolean boo=false;//判断是否有排序发生,若未发生,表明已排好序,避免重复排序
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-1;j++){
if(arr[j]>arr[j+1]){
boo=true;
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
System.out.println("第"+(++k)+" 次:"+Arrays.toString(arr));
}
}
if(!boo){
break;
}
}
}
public static void main(String[] args) {
int[] arr=new int[]{15,32,14,86,54,78,36};
System.out.println("排序前的数组:"+Arrays.toString(arr));
bubleSort(arr);
System.out.println("排序后的数组:"+Arrays.toString(arr));
}
}

 上述代码运行结果如下:

排序前的数组:[15, 32, 14, 86, 54, 78, 36]
第1 次:[15, 14, 32, 86, 54, 78, 36]
第2 次:[15, 14, 32, 54, 86, 78, 36]
第3 次:[15, 14, 32, 54, 78, 86, 36]
第4 次:[15, 14, 32, 54, 78, 36, 86]
第5 次:[14, 15, 32, 54, 78, 36, 86]
第6 次:[14, 15, 32, 54, 36, 78, 86]
第7 次:[14, 15, 32, 36, 54, 78, 86]
排序后的数组:[14, 15, 32, 36, 54, 78, 86] 

可见,优化后的代码,比原先减少重复排序(36-7=29) 29次之多。

二、快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。

它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 

我们还使用上述的待排序数据集,演示快速排序。

/**
 * 快速排序
 * @author 李章勇
 */
import java.util.Arrays;
public class Demo1 {
static int k=0;
public static void quickSort(int[] arr,int _left,int _right){
if(_left>_right){
return;
}
int left=_left;
int right=_right;
int temp=arr[left];
while(left!=right){
while(right>left && arr[right]>=temp){
right--;
}
arr[left]=arr[right];
while(left<right && arr[left]<=temp){
left++;
}
arr[right]=arr[left];
}
// arr[right]=temp;
arr[left]=temp;//此时,left和right相等
System.out.println("第"+(++k)+" 次:"+Arrays.toString(arr));
quickSort(arr,_left,left-1);
quickSort(arr,left+1,_right);
}
public static void main(String[] args) {
int[] arr=new int[]{15,32,14,86,54,78,36};
System.out.println("排序前的数组:"+Arrays.toString(arr));
quickSort(arr, 0, arr.length-1);
System.out.println("排序后的数组:"+Arrays.toString(arr));
}
上述代码运行后,结果如下: 
排序前的数组:[15, 32, 14, 86, 54, 78, 36] 
第1 次:[14, 15, 32, 86, 54, 78, 36]
第2 次:[14, 15, 32, 86, 54, 78, 36]
第3 次:[14, 15, 32, 86, 54, 78, 36]
第4 次:[14, 15, 32, 36, 54, 78, 86]
第5 次:[14, 15, 32, 36, 54, 78, 86]
第6 次:[14, 15, 32, 36, 54, 78, 86]
第7 次:[14, 15, 32, 36, 54, 78, 86]
排序后的数组:[14, 15, 32, 36, 54, 78, 86] 

最后,在时间复杂度方面,快速排序的最糟糕状况是O(n2) ,平均时间复杂度为O(nlogn)。

以上是关于经典排序之冒泡排序和快速排序的主要内容,如果未能解决你的问题,请参考以下文章

九种经典排序算法详解(冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序,计数排序,桶排序,基数排序)

js三种经典排序:冒泡排序插入排序快速排序

交换排序之冒泡排序和快速排序

排序算法之交换排序(冒泡排序快速排序)

三大经典排序 冒泡排序,选择排序,快速排序

JAVA实现经典排序算法(冒泡排序选择排序插入排序希尔排序堆排序归并排序快速排序)