排序算法之:冒泡排序和快速排序(java)

排序算法的分类:

  • 内部排序:整个排序过程在内存储器中进行。
  • 外部排序:由于待排序元素数量太大,以至于内存储器无法容纳全部数据,排序需要借助外部存储设备才能完成。

冒泡排序与快速排序效率:

类别 排序方法 时间复杂度 空间复杂度 排序方式 稳定性
平均时间复杂度 最好情况 最坏情况
交换排序 冒泡排序 O(n^2) O(n) O(n^2) O(1) In-place 稳定
快速排序 O(n\log n) O(n\log n) O(n^2) O(\log n) In-place 不稳定

接口:

package com.my.sort;

public interface IArraySort {
	public int[] sort(int[] sourceArray);
}

1. 冒泡排序

1.1 算法步骤

  • 比较相邻的元素,如果第一个比第二个大,就交换他们两个。
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素就会是最大的数。
  • 针对所有的元素重复以上的步骤,除了最后一个。
  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

1.2 举例说明

要排序数组:int[] arr = {7, 2, 6, 5, 9, 4};


第1轮排序前数组为:[7, 2, 6, 5, 9, 4]

第1轮第1次比较:7大于2交换位置:[2, 7, 6, 5, 9, 4]

第1轮第2次比较:7大于6交换位置:[2, 6, 7, 5, 9, 4]

第1轮第3次比较:7大于5交换位置:[2, 6, 5, 7, 9, 4]

第1轮第4次比较:7小于9不交换位置:[2, 6, 5, 7, 9, 4]

第1轮第5次比较:9大于4交换位置:[2, 6, 5, 7, 4, 9]

第1轮排序后数组为:[2, 6, 5, 7, 4, 9]


第2轮排序前数组为:[2, 6, 5, 7, 4, 9]

第2轮第1次比较:2小于6不交换位置:[2, 6, 5, 7, 4, 9]

第2轮第2次比较:6大于5交换位置:[2, 5, 6, 7, 4, 9]

第2轮第3次比较:6小于7不交换位置:[2, 5, 6, 7, 4, 9]

第2轮第4次比较:7大于4交换位置:[2, 5, 6, 4, 7, 9]

第2轮排序后数组为:[2, 5, 6, 4, 7, 9]


第3轮排序前数组为:[2, 5, 6, 4, 7, 9]

第3轮第1次比较:2小于5不交换位置:[2, 5, 6, 4, 7, 9]

第3轮第2次比较:5小于6不交换位置:[2, 5, 6, 4, 7, 9]

第3轮第3次比较:6大于4交换位置:[2, 5, 4, 6, 7, 9]

第3轮排序后数组为:[2, 5, 4, 6, 7, 9]


第4轮排序前数组为:[2, 5, 4, 6, 7, 9]

第4轮第1次比较:2小于5不交换位置:[2, 5, 4, 6, 7, 9]

第4轮第2次比较:5大于4交换位置:[2, 4, 5, 6, 7, 9]

第4轮排序后数组为:[2, 4, 5, 6, 7, 9]


第5轮排序前数组为:[2, 4, 5, 6, 7, 9]

第5轮第1次比较:2小于4不交换位置:[2, 4, 5, 6, 7, 9]

第5轮排序后数组为:[2, 4, 5, 6, 7, 9]


已排序后的数组为:[2, 4, 5, 6, 7, 9]

由此可见:N个数字要完成排序,总共要进行N-1轮排序,每i轮的排序次数为(N-i)次,所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数,即

for(int i = 0; i < arr.length - 1; i++){
    for(int j = 0; j < arr.length - (i + 1); j++){
        //交换位置
    }
}

1.3 代码

package com.my.sort;

import java.util.Arrays;

public class Client {
	public static void main(String[] args) {
		int[] sourceArray = {7,2,6,5,9,4};
		BubbleSort bSort = new BubbleSort();
		System.out.println(Arrays.toString(sourceArray));
		int[] arr = bSort.sort(sourceArray);
		System.out.println(Arrays.toString(arr));
	}
}
package com.my.sort;

import java.util.Arrays;

public class BubbleSort implements IArraySort {

	@Override
	public int[] sort(int[] sourceArray) {
		//对arr进行拷贝,不改变参数内容
		int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
		for(int i = 0; i < arr.length - 1; i++) {
			//设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成
			boolean flag = true;
			for(int j = 0; j < arr.length - (1 + i); j++) {
				if(arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
					
					flag = false;
				}
			}
			if(flag) {
				break;
			}
		}
		return arr;
	}
}

1.4 执行结果

[7, 2, 6, 5, 9, 4]
[2, 4, 5, 6, 7, 9]

2. 快速排序

2.1 算法步骤

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

2.2 举例说明

要排序数组:int[] arr = {7, 2, 6, 5, 9, 4};


下标:0          1          2          3          4          5      

元素:7          2          6          5          9          4         

假设7为基准值,pivot = 0

i  = 1,j  = 1:arr[j] < arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[7,2,6,5,9,4]           i++  ,  j++

i  = 2,j  = 2:arr[j] < arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[7,2,6,5,9,4]           i++  ,  j++

i  = 3,j  = 3:arr[j] < arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[7,2,6,5,9,4]           i++  ,  j++

i  = 4,j  = 4:arr[j] > arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[7,2,6,5,9,4]                      j++

i  = 4,j  = 5:arr[j] < arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[7,2,6,5,4,9]           i++  ,  j++

i  = 5,j  = 6

一轮交换结束,交换 pivot 和 i - 1所指向的值后,数组为:[4,2,6,5,7,9]

pivot = 4     arr[pivot] = 7


元素:{4          2          6          5}         {7}         { 9 }    

pivot = 4     arr[pivot] = 7

pivot 右边只有一个元素,不用排序

对 pivot 左边的元素进行快速排序

                 下标:0          1          2          3  

pivot 左边元素:4          2          6          5              

假设4为新的基准值,pivot = 0

i  = 1,j  = 1:arr[j] < arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[4,2,6,5]           i++  ,  j++

i  = 2,j  = 2:arr[j] > arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[4,2,6,5]                      j++

i  = 2,j  = 3:arr[j] > arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[4,2,5,6]                      j++

i  = 2,j  = 4

一轮交换结束,交换 pivot 和 i - 1所指向的值后,数组为:[2,4,5,6]

pivot = 1     arr[pivot] = 4

元素:{2        4          5         6}         {7}         {9}  


元素:{2}          {4}         {5          6}    

pivot = 1     arr[pivot] = 4

pivot 左边只有一个元素,不用排序

对 pivot 右边的元素进行快速排序

                 下标:0          1        

pivot 右边元素:5          6                

假设5为新的基准值,pivot = 0

i  = 1,j  = 1:arr[j] > arr[pivot],交换 arr[i] 和 arr[j] 后,数组为:[5,6]           j++

i  = 1,j  = 2

一轮交换结束,交换 pivot 和 i - 1所指向的值后,数组为:[5,6]

元素:{2}          {4}         {5          6} 


第一次合并左右数组后,数组为:[2,4,5,6,]

第二次合并左右数组后,数组为:[2,4,5,6,7,9]


已排序后的数组为:[2, 4, 5, 6, 7, 9]

2.3 代码

package com.my.sort;

import java.util.Arrays;

public class Client {
	public static void main(String[] args) {
		int[] sourceArray = {7,2,6,5,9,4};
		QuickSort qSort = new QuickSort();
		System.out.println(Arrays.toString(sourceArray));
		int[] arr = qSort.sort(sourceArray);
		System.out.println(Arrays.toString(arr));
	}
}
package com.my.sort;

import java.util.Arrays;

public class QuickSort implements IArraySort {

	@Override
	public int[] sort(int[] sourceArray) {
		//对arr进行拷贝,不改变参数内容
		int[] arr = Arrays.copyOf(sourceArray,sourceArray.length);
		//返回快速排序后的数组
		return quickSort(arr,0,arr.length - 1);
	}
	private int[] quickSort(int[] arr,int left,int right) {
		if(left < right) {
			//partitionIndex用来记录基准值的下标,partition方法用来找到基准值的下标
			int partitionIndex = partition(arr,left,right);
			//对基准值左侧的元素进行快速排序
			quickSort(arr,left,partitionIndex - 1);
			//对基准值右侧的元素进行快速排序
			quickSort(arr,partitionIndex + 1,right);
		}
		//返回排序好的数组
		return arr;
	}
	//找到基准值并返回其下标
	private int partition(int[] arr,int left,int right) {
		//设置基准值(pivot)
		int pivot = left;
		int index = pivot + 1;
		for(int i = index; i <= right; i++) {
			if(arr[i] < arr[pivot]) {
				swap(arr,i,index);
				index++;
			}
		}
		swap(arr,pivot,index - 1);
		return index - 1;
	}
	//交换指定数组的两个指定元素的值
	private void swap(int[] arr,int i,int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}

2.4 执行结果

[7, 2, 6, 5, 9, 4]
[2, 4, 5, 6, 7, 9]

 

猜你喜欢

转载自blog.csdn.net/xiongmengyao/article/details/86742348