排序算法也就是我們通常說的將一組數據依照特定排序方式的一種算法。
排序算法的輸出必須要遵循兩個原則:
1.輸出的結果為遞增數列(遞增針對所需的排序順序而言)
2.輸出的結果為原輸入的一種排列或重組。
今天介紹的都是平均時間復雜度為O(N^2)的排序算法,即:冒泡排序、插入排序和選擇排序 。
1.冒泡排序
顧名思義就是誰冒泡泡冒的快,上升的就快。 看下圖:
相信大家一看 就很明白,首選將兩個數據進行比較,遇見比自己的大的數據,接着向后找,直到找到比自己小的數據,然后進行交換,第二個數據依次論推
上代碼:
1 /*冒泡排序 復雜度O(n^2) 2 * 1.比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。 3 2.對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。在這一點,最后的元素應該會是最大的數。 4 3.針對所有的元素重復以上的步驟,除了最后一個。 5 4.持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。 6 */ 7 public List<int> BubbingSort(List<int> arr) 8 { 9 int temp = 0; 10 11 for (int i = 0; i < arr.Count; i++) 12 { 13 for (int j = i + 1; j < arr.Count; j++) 14 { 15 if (arr[i] > arr[j]) 16 { 17 temp = arr[i]; 18 arr[i] = arr[j]; 19 arr[j] = temp; 20 } 21 } 22 } 23 return arr; 24
冒泡排序最優的時間復雜度是O(n) 最差的時間復雜度O(n^2) 平均時間復雜度O(n^2)
2.插入排序
工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從后向前掃描,找到相應位置並插入。時間復雜度同冒泡排序
主要有兩個動作:操作和交換,如果操作的代價大於交換的代價,建議采用二分查找來減少比較操作的代價,二分查找是插入排序的一個變異算法。
直接上代碼了
1 /*插入排序 默認第一個元素是已被排序 2 * 取出下一個元素 在已排序的元素中進行比較 3 * 如果已排序的元素大於該元素 則將該元素移動到下一位置 4 * 直到找到小於或等於的該元素的位置 5 * 將該元素插入到該位置 6 * 如果比較操作的代價大於交換操作的話 就要考慮用二分查找法 7 * 最差復雜度O(N^2) 最優時間復雜度O(N) 平均時間復雜度O(N^2) 空間復雜度O(N) 8 * 和冒泡排序是一個級別 9 */ 10 public List<int> InsertSort(List<int> arr) 11 { 12 for (int i = 1; i < arr.Count; i++) 13 { 14 int a = arr[i]; 15 int j = i; 16 while (j > 0 && arr[j - 1] > a) 17 { 18 arr[j] = arr[--j]; 19 } 20 arr[j] = a; 21 } 22 return arr; 23 }
3.選擇排序
在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續尋找最小元素,然后放到排序序列末尾(目前已被排序的序列)。以此類推,直到所有元素均排序完畢。
1 /*選擇排序:首先在未排序的元素中找到最小的元素 放在排序序列的起始位置 2 然后在從生下的序列元素中繼續找到最小元素,然后放在已排序序列的末尾 3 復雜度O(N^2)*/ 4 public List<int> SelectSort(List<int> arr) 5 { 6 int min = 0; 7 for (int i = 0; i < arr.Count; i++) 8 { 9 min = i; 10 //查找最小值 11 for (int j = i + 1; j < arr.Count; j++) 12 { 13 if (arr[min] > arr[j]) 14 min = j; 15 } 16 17 //交換 18 if (min != i) 19 { 20 int t = arr[i]; 21 arr[i] = arr[min]; 22 arr[min] = t; 23 } 24 } 25 return arr; 26 }
選擇排序的交換操作介於0和(n-1)次之間。選擇排序的比較操作為n(n-1)/2次之間。選擇排序的賦值操作介於0和3(n-1)次之間。比較次數O(n^2),比較次數與關鍵字的初始狀態無關,總的比較次數N=(n-1)+(n-2)+...+1=n*(n-1)/2。 交換次數O(n),最好情況是,已經有序,交換0次;最壞情況是,逆序,交換n-1次。 交換次數比冒泡排序少多了,由於交換所需CPU時間比比較所需的CPU時間多,n值較小時,選擇排序比冒泡排序快。