前言
本文是第一站,大戰冒泡排序。你還在爲每次寫排序算法的時候發愁嗎?
喝了本專欄,保證你能手擼冒泡排序。
文章目錄
一、冒泡排序
1、冒泡排序原理
原理:
比較兩個相鄰的元素,符合要求(看自己的需求是從小到大,還是從大到小)即交換兩個元素的位置。
2、圖解冒泡排序原理
輸入一個數組,按小到大順序排列。
input:
[5,4,6,1,3,2]
output:
[1,2,3,4,5,6]
咱們就以這個題爲例子,來講解和演示一下冒泡排序的過程。
初始值就是:
我們最終通過冒泡排序要得到的結果:
第一趟冒泡:
第1次:
5與4相比,5>4,所以換位置
第2次:
5與6相比,5< 6,所以不換位置
第3次:
6與1相比,6>1,所以換位置
第4次:
6與3相比,6>3,所以換位置
第5次:
6與2相比,6>2,所以換位置
第6次:
此時已經到達了第一趟的最後一個元素了,所以第一趟結束。
第一趟結束,得到第一趟冒泡的結果:
[4,5,1,3,2,6]
以此類推,最終就得到了:
[1,2,3,4,5,6]
3、思路
例如有一個數組:A=[5,2,3];
1、第1次比較,首先比較第1和第2個數,(如果A[1]>A[2],則交換位置)將大的數放在後面,將小的數放在前面;
2、第2次比較,比較第2和第3個數,如果第2個大於第3個數,則交換位置。
…
以此類推,每一趟都減少一次。
4、代碼實現冒泡排序
註釋的很清楚了,看明白應該是沒問題的。
package 排序算法.冒泡排序;
import java.util.Arrays;
/**
* @Auther: truedei
* @Date: 2020 /20-6-2 20:15
* @Description:冒泡排序
*/
public class BubbleSort {
public static int[] sort(int A[]){
//一共冒泡A.length趟排序 如果有6個元素要排序,那麼就需要6次
for (int i = 0; i < A.length; i++) {
//第二層循環爲什麼是(A.length -i -1)
// 減i是:每趟都忽略已經排好
// 減1是:每次一趟的每一次到最後一個元素了
for (int j = 0; j < A.length -i - 1 ; j++) {
//比較i和j+1
//例如有:[3,2,5,4,...] 現在遍歷到第1個了,A[j]=3; A[j+1]=2
if(A[j] > A[j+1]){// 3 > 2 符合要求,則進入交換
int temp = A[j]; //定義一個臨時變量,用於交換數據
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
return A;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(sort(new int[]{3,9,4,1,6})));
}
}
運行之後,就可以得到結果:
[1, 3, 4, 6, 9]
上面這是從小到大排序的,下面這個是從大到小排序的:
只需要修改一下判斷條件: if(A[j] < A[j+1]){ } 即可
package 排序算法.冒泡排序;
import java.util.Arrays;
/**
* @Auther: truedei
* @Date: 2020 /20-6-2 20:15
* @Description:冒泡排序
*/
public class BubbleSort {
public static int[] sort(int A[]){
//一共冒泡A.length趟排序 如果有6個元素要排序,那麼就需要6次
for (int i = 0; i < A.length; i++) {
//第二層循環爲什麼是(A.length -i -1)
// 減i是:每趟都忽略已經排好
// 減1是:每次一趟的每一次到最後一個元素了
for (int j = 0; j < A.length -i - 1 ; j++) {
//比較i和j+1
//例如有:[3,2,5,4,...] 現在遍歷到第1個了,A[j]=3; A[j+1]=2
if(A[j] < A[j+1]){// 3 < 2 符合要求,則進入交換
int temp = A[j]; //定義一個臨時變量,用於交換數據
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
return A;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(sort(new int[]{3,9,4,1,6})));
}
}
5、冒泡排序的時間複雜度分析
分析算法的時間複雜度,通常都是分析最壞的時間複雜度的情況。讓程序在最壞的情況下,也能保證流暢的服務。這纔是分析的目的。
對於冒泡排序的最壞的情況就是逆序的情況。
例如:[6,5,4,3,2,1]
每一次比較,都去交換元素
對於這個排序算法:在做分析的時候,通常不會把for循環拿出來做分析的
public static int[] sort(int A[]){
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A.length -i - 1 ; j++) {
//比較j和j+1
if(A[j] < A[j+1]){
int temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
}
}
return A;
}
而真正實現排序的是下面這段代碼:
if(A[j] < A[j+1]){
int temp = A[j];
A[j] = A[j+1];
A[j+1] = temp;
}
就拿:[6,5,4,3,2,1] 來說
第一趟:
6與5比較,然後交換
6與4比較,然後交換
6與3比較,然後交換
6與2比較,然後交換
6與1比較,然後交換
第二趟:
5與4比較,然後交換
5與3比較,然後交換
5與2比較,然後交換
5與1比較,然後交換
第三趟:
4與3比較,然後交換
4與2比較,然後交換
4與1比較,然後交換
…
…
…
以此類推
元素比較的次數爲:
=
推導過後,得出冒泡排序時間複雜度是:
6、小技巧:常用時間複雜度
(1) O(1)
(1)O(1) 這個針對的是常數;對於一個N,不管這個N是如何增長,這個時間是不變的。
例如下面這些代碼的時間複雜度都是O(1):
/**
* @Auther: truedei
* @Date: 2020 /20-6-2 22:01
* @Description:
*/
public class Test {
public static void main(String[] args) {
System.out.println("你好,我叫鄭暉");
System.out.println("你好,我叫鄭暉");
System.out.println("你好,我叫鄭暉");
System.out.println("你好,我叫鄭暉");
}
}
還有這種:
我有一個數組,我知道了我需要的這個數據所在的索引,然後去拿這個值,咋這種也是O(1)
/**
* @Auther: truedei
* @Date: 2020 /20-6-2 22:01
* @Description:
*/
public class Test {
public static void main(String[] args) {
String[] names = {"小明","小紅","鄭暉"};
System.out.println("你好,我叫"+names[2]);
}
}
(2) O(n)
O(n)是一個線性增長的。
經常用在for()循環當中
例如下面這種代碼:
/**
* @Auther: truedei
* @Date: 2020 /20-6-2 22:01
* @Description:
*/
public class Test {
public static void main(String[] args) {
String[] names = {"小明","小紅","鄭暉"};
for (int i = 0; i < names.length; i++) {
System.out.println("你好,我叫"+names[i]);
}
}
}
(3) O(n^2)
是一個平方級的的增長。經常出現在兩層for循環
。
例如本文所寫的:
public static int[] sort(int A[]){
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A.length -i - 1 ; j++) {
.....
}
}
return A;
}
(4) O(n^3)
是一個立方級的增長。經常出現在遍歷一個三層的for循環
中
for (...) {
for (...) {
for (...) {
.....
}
}
}
(5) O(lg n)
是一個對數級。
在二分查找法裏就是O(lg n)
。
每次執行N是以一個倍數的形式是遞減的:
比如第1次:1/2
比如第2次:1/4
比如第3次:1/8
比如第4次:1/16
…
快速的讓N的規模變小。
(6) O(n lg n)
在排序中經常見到的
(7) O(2^n)
指數級的
7、附:常用的排序算法的時間複雜度和空間複雜度
排序法 | 最差時間分析 | 平均時間複雜度 | 穩定度 | 空間複雜度 |
---|---|---|---|---|
冒泡排序 | O(n^2) | O(n^2) | 穩定 | O(1) |
快速排序 | O(n^2) | O(n*log2n) | 不穩定 | O(log2n)~O(n) |
選擇排序 | O(n^2) | O(n^2) | 不穩定 | O(1) |
二叉樹排序 | O(n^2) | O(n*log2n) | 不穩定 | O(n) |
插入排序 | O(n^2) | O(n^2) | 穩定 | O(1) |
堆排序 | O(n*log2n) | O(n*log2n) | 不穩定 | O(1) |
希爾排序 | O | O | 不穩定 | O(1) |
二、小鄭有話說
如果對你有幫助,可以分享給你身邊的朋友。或者給俺點個大大的贊和大大的評論,點贊和評論就是給我最大的支持,感謝。
水平有限,難免會有疏漏或者書寫不合理的地方,歡迎交流討論。
作者:TrueDei
作者主頁:https://truedei.blog.csdn.net/(https://truedei.blog.csdn.net/article/details/106269373)
轉載說明:如需轉載請註明原地址和作者名。
如果喜歡我的文章,還沒看夠可以關注我,我會用心寫好每一篇文章。