一、簡介
排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。
二、排序算法分類
三、排序算法複雜度
概念:
- 穩定:如果a原本在b前面,而a=b,排序之後a仍然在b的前面。
- 不穩定:如果a原本在b的前面,而a=b,排序之後 a 可能會出現在 b 的後面。
- 時間複雜度:對排序數據的總的操作次數。算法的運行時間。
- 空間複雜度:是指算法在計算機內執行時所需存儲空間的度量。
四、原理及實現
1、冒泡排序
1.1、基本思想
冒泡排序(Bubble Sort)是一種簡單的排序算法。它重複訪問要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。訪問數列的工作是重複地進行直到沒有再需要交換的數據,也就是說該數列已經排序完成。這個算法的名字由來是因爲越小的元素會經由交換慢慢“浮”到數列的頂端,像水中的氣泡從水底浮到水面。
1.2、算法描述
冒泡排序算法的算法過程如下:
①. 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
②. 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。這步做完後,最後的元素會是最大的數。
③. 針對所有的元素重複以上的步驟,除了最後一個。
④. 持續每次對越來越少的元素重複上面的步驟①~③,直到沒有任何一對數字需要比較。
1.3、代碼實現
/**
* 說明:升序/降序就是將if括號裏的>改成<
*/
@Test
public void TestBubble(){
int[] arr = {2,8,0,1,9,4,6,7,6,3};
for (int i = 0; i <arr.length-1 ; i++) {
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;
}
}
}
for (int i : arr) {
System.out.println("i = " + i);
}
}
2、選擇排序
2.1、基本原理
在未排序序列中找到最小(大)元素,存放到未排序序列的起始位置。然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
2.2、算法描述
①. 從待排序序列中,找到關鍵字最小的元素;
②. 如果最小元素不是待排序序列的第一個元素,將其和第一個元素互換;
③. 從餘下的 N – 1 個元素中,找出關鍵字最小的元素,重複①、②步,直到排序結束。
2.3、代碼實現
@Test
public int[] selectSort() {
int[] arr = {1,2,4,5,73,23,12};
int len = arr.length;
int minIndex, temp;
for (int i = 0; i < len - 1; i++) {
minIndex = i;
for (int j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { // 尋找最小的數
minIndex = j; // 將最小數的索引保存
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
@Test
public void Test1(){
int[] a = selectSort();
for (int i : a) {
System.out.println("i = " + i);
}
}
3、插入排序
3.1、基本原理
插入排序(Insertion-Sort)算法是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。
3.2、算法描述
- 從第一個元素開始,該元素可以認爲已經被排序;
- 取出下一個元素,在已經排序的元素序列中從後向前掃描;
- 如果該元素(已排序)大於新元素,將該元素移到下一位置;
- 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;
- 將新元素插入到該位置後;
- 重複步驟2~5。
3.3、代碼實現
@Test
public void Test1(){
int[] arr = {11,24,46,2,3,1,6,4,23,14,56,86,42};
int[] a = insertSort(arr);
for (int i : a) {
System.out.println("i = " + i);
}
}
@Test
public int[] insertSort(int[] arr){
int preIndex,current;
for (int i = 1; i< arr.length; i++ ){
preIndex = i -1; //相對當前下標前一個下標
current = arr[i];//當前下標的值
while (preIndex >=0 && arr[preIndex] > current){
//前一個下標必須大於等於0、且前一個值大於後一個值、才交換位置
arr[preIndex+1] = arr[preIndex];//賦值當前值爲前一個下標的值(交換數值)
preIndex--;
}
arr[preIndex+1]=current;//賦值前一個值爲當前值 (交換數值)
}
return arr;
}
4、歸併排序
4.1、基本原理
該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列區間有序。若將兩個有序表合併成一個有序表,稱爲2-路歸併
4.2、算法描述
- 把長度爲n的輸入序列分成兩個長度爲n/2的子序列;
- 對這兩個子序列分別採用歸併排序;
- 將兩個排序好的子序列合併成一個最終的排序序列
4.3、代碼實現 (有時間在整理)
5、快速排序
3.1、基本原理
3.2、算法描述
3.3、代碼實現
6、堆排序
3.1、基本原理
3.2、算法描述
3.3、代碼實現
7、希爾排序
3.1、基本原理
3.2、算法描述
3.3、代碼實現
8、基數排序
3.1、基本原理
3.2、算法描述
3.3、代碼實現
9、計數排序
3.1、基本原理
3.2、算法描述
3.3、代碼實現
公衆號 關注一波 (一葉知秋博客)
不定期分享視頻資料