📑java實現幾種常用排序:冒泡排序


冒泡排序介紹

冒泡排序是我們得最多的排序方式之一,原因是簡單易實現,且原理易懂。顧名思義,冒泡排序,它的排序過程就像水中的氣泡一樣,一個一個上浮到水面。

冒泡排序原理分析

冒泡排序代碼實現

/**
 * @Author {LearnAndGet}
 * @Time 2019年1月8日
 * @Discription:
 */
package com.sort;

import java.util.Arrays;

public class MaopaoSort {
	
	static int[] array = {3,2,4,1,5,0};
	
	public static void maopaoSort(int[] a) 
	{
		//外層循環,是需要進行比較的輪數,一共進行5次即可
		for(int i=0;i<a.length-1;i++) 
		{
			//內存循環,是每一輪中進行的兩兩比較
			for(int j=0;j<a.length-1;j++) 
			{
				if(a[j] > a[j+1]) 
				{
					int temp = a[j];
					a[j] = a[j+1];
					a[j+1] = temp; 
				}
			}
			System.out.println("第"+(i+1)+"輪排序后的數組為: "+Arrays.toString(a));
		}
	}
	
	public static void main(String[] args) {
		maopaoSort(array);
	}
}

輸出結果

第1輪排序后的數組為: [2, 3, 1, 4, 0, 5]
第2輪排序后的數組為: [2, 1, 3, 0, 4, 5]
第3輪排序后的數組為: [1, 2, 0, 3, 4, 5]
第4輪排序后的數組為: [1, 0, 2, 3, 4, 5]
第5輪排序后的數組為: [0, 1, 2, 3, 4, 5]

冒泡排序的優化

1 .觀察上述代碼和運行結果,我們可以發現,當第一輪結束后,最后一個數字一定是數組中最大的元素,那么我們在進行第二趟的兩兩比較時,實際上是沒有必要再對第5個和第6個進行比較的。那么我們可以修改代碼如下:

public static void maopaoSort(int[] a) 
{
	//外層循環,是需要進行比較的輪數,一共進行5次即可
	for(int i=0;i<a.length-1;i++) 
	{
		//內存循環,是每一輪中進行的兩兩比較
        //並且每一輪結束后,下一次的兩兩比較中可以少比較一次
		for(int j=0;j<a.length-i-1;j++) 
		{
			if(a[j] > a[j+1]) 
			{
				int temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp; 
			}
		}
		System.out.println("第"+(i+1)+"輪排序后的數組為: "+Arrays.toString(a));
	}
}

繼續運行后,可以發現運行結果是一樣的。

2 .當我們用數組:{1,2,0,3,5,4}來測試上述冒泡排序時,運行結果如下:

第1輪排序后的數組為: [1, 0, 2, 3, 4, 5]
第2輪排序后的數組為: [0, 1, 2, 3, 4, 5]
第3輪排序后的數組為: [0, 1, 2, 3, 4, 5]
第4輪排序后的數組為: [0, 1, 2, 3, 4, 5]
第5輪排序后的數組為: [0, 1, 2, 3, 4, 5]

可以看到,在第2輪排序完成后,其實我們就已經的到了排好序的數組,但是我們的程序並不知道,仍然進行了后續的無用工作。那么,我們如何來讓程序知道已經完成好排序了呢?

這里可以想到,當某一輪的兩兩比較中,如果都沒有發生數組元素的互換,那么其實排序工作已經完成了,所以我們可以考慮在程序中加入一個flag,默認為false,含義是該輪比較中是否發生了元素互換,當程序中執行到元素互換時,將該flag置為true,當該輪比較結束時,若flag為flase,則說明該輪比較未發生元素互換,那么排序完成,若flag為true,說明本輪比較仍然有元素互換,需要繼續進行下輪排序。代碼實現如下:

/**
 * @Author {LearnAndGet}
 * @Time 2019年1月8日
 * @Discription:
 */
package com.sort;

import java.util.Arrays;

public class MaopaoSort {
	
	static int[] array = {1,2,0,3,5,4};
	
	public static void maopaoSort(int[] a) 
	{
		//外層循環,是需要進行比較的輪數,一共進行5次即可
		for(int i=0;i<a.length-1;i++) 
		{
			boolean flag = false;
			//內存循環,是每一輪中進行的兩兩比較
			for(int j=0;j<a.length-i-1;j++) 
			{
				if(a[j] > a[j+1]) 
				{
					int temp = a[j];
					a[j] = a[j+1];
					a[j+1] = temp;
					flag = true;
				}
			}
			System.out.println("第"+(i+1)+"輪排序后的數組為: "+Arrays.toString(a));
			if(flag == false)
			{
				System.out.println("本輪中的兩兩比較未發生元素互換,排序已經完成啦");
				return;
			}
		}
	}
	
	public static void main(String[] args) {
		maopaoSort(array);
	}
}

運行結果:

第1輪排序后的數組為: [1, 0, 2, 3, 4, 5]
第2輪排序后的數組為: [0, 1, 2, 3, 4, 5]
第3輪排序后的數組為: [0, 1, 2, 3, 4, 5]
本輪中的兩兩比較未發生元素互換,排序已經完成啦

冒泡排序的時間復雜度

冒泡排序是一種用時間換空間的排序方法,最壞情況是把順序的排列變成逆序,或者把逆序的數列變成順序。在這種情況下,每一次比較都需要進行交換運算。舉個例子來說,一個數列 5 4 3 2 1 進行冒泡升序排列

第一輪的兩兩比較,需要比較4次;得到 4 3 2 1 5
第二輪的兩兩比較,需要比較3次;得到 3 2 1 4 5
第三輪的兩兩比較,需要比較2次;得到 2 1 3 4 5
第四輪的兩兩比較,需要比較1次;得到 1 2 3 4 5

所以總的比較次數為 4 + 3 + 2 + 1 = 10次
對於n位的數列則有比較次數為 (n-1) + (n-2) + ... + 1 = n * (n - 1) / 2,這就得到了最大的比較次數。
而O(N^2)表示的是復雜度的數量級。舉個例子來說,如果n = 10000,那么 n(n-1)/2 = (n^2 - n) / 2 = (100000000 - 10000) / 2,相對10^8來說,10000小的可以忽略不計了,所以總計算次數約為0.5 * N2。用O(N2)就表示了其數量級(忽略前面系數0.5)。

綜上所述,冒泡排序的時間復雜度為:O(n²)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM