記得當初第一年的時候、接觸算法、有那麼兩個視頻、跳舞的、講的是冒泡排序跟選擇排序、當時看了好多遍最終懂了、此次多了一些算法、學起來也還好吧、咱是有基礎的人、找到了曾經的視頻、有的就發了、沒找到的就無法、事實上算法並不難、繞繞就明確了、先別看代碼- -html
從頭至尾巴、從第二個開始、向左進行插入、這裏說的插入是指做比較、直到比較出比本身小的就插入到他的前面。java
樣例ios
1 7 4 8 6 5算法
插入排序數組
[1]7 4 8 6 5dom
[1 7] 4 8 6 5 post
[1 4 7] 8 6 5 性能
[1 4 7 8 ] 6 5
ui
[1 4 6 7 8 ] 5 spa
[1 4 5 6 7 8 ]
特性
算法是穩定的、時間複雜度爲O(n2)、空間複雜度爲O(1)、需要一個輔助的空間變量
代碼(java)
<span style="font-size:18px;">// insert_sort publicint[] insert_sort(int[] arr) { int[] intArr = arr; int i, j, key; for (j = 1; j < intArr.length; j++) { key = intArr[j]; i = j - 1; while (i >= 0 && intArr[i] > key) { intArr[j] = intArr[i]; i--; } intArr[i + 1] = key; } return intArr; }</span>
小編:咳咳咳、此次也自稱小編了、事實上插入排序真的沒啥- -、就是一個個往有序序列裏面插入新的數值。
視頻(插入)
交換排序事實上就是兩個值相互比較的思想、假設後面的值比前面的小、就交換位置(從小到大排序)、交換排序通常有冒泡排序、高速排序兩種。
第一次據說這個算法就想到了兒時家裏養的金魚、常常看它吐泡泡、(儘管不久它就不在了)、但是思想很是明顯、那就是氣泡在水裏會上浮、所謂的冒泡排序就是從頭到位、依次兩個值作比較、假設後面的值比前面小、兩個值就交換、每次都可以交換出一個’最大值‘,就好像大泡泡上浮同樣。
樣例(相鄰的兩個數交換、每循環一次交換就能找出一個最大的)
特性:時間複雜度爲O(n2)是穩定的算法、但是數據大的時候不建議使用。
代碼
<span style="font-size:18px;">void BubbleSort3(int a[], int n) { int j, k; int flag; flag = n; while (flag > 0) { k = flag; flag = 0; for (j = 1; j < k; j++) if (a[j - 1] > a[j]) { Swap(a[j - 1], a[j]); flag = j; } } }</span>
視頻(冒泡)
事實上是冒泡排序的一種改進、取一個鍵值、而後與其它值相比較、比鍵值大的放後面鍵值小的放前面(交換)、循環一次的效果就是比鍵值大的都在前面了、比鍵值小的都在後面了、而後再在前面那半取一個鍵值、循環上邊步驟、不斷劃分、直到排序完畢。
樣例:
特性:時間複雜度爲O(nlog2n)、不穩定!平均時間最佳。最壞狀況近似O(n2)
代碼
<span style="font-size:18px;">#include<iostream> using namespace std; void quickSort(int a[],int,int); int main() { int array[]={34,65,12,43,67,5,78,10,3,70},k; int len=sizeof(array)/sizeof(int); cout<<"The orginal arrayare:"<<endl; for(k=0;k<len;k++) cout<<array[k]<<","; cout<<endl; quickSort(array,0,len-1); cout<<"The sorted arrayare:"<<endl; for(k=0;k<len;k++) cout<<array[k]<<","; cout<<endl; system("pause"); return 0; } void quickSort(int s[], int l, int r) { if (l< r) { int i = l, j = r, x = s[l]; while (i < j) { while(i < j && s[j]>= x) // 從右向左找第一個小於x的數 j--; if(i < j) s[i++] = s[j]; while(i < j && s[i]< x) // 從左向右找第一個大於等於x的數 i++; if(i < j) s[j--] = s[i]; } s[i] = x; quickSort(s, l, i - 1); // 遞歸調用 quickSort(s, i + 1, r); } } </span>
視頻(高速)
這個真的簡單的不想說了= = 、有一行數、每次都選擇一個最小的出來、如圖
<span style="font-size:18px;">//爲了使用Random類,需要增長例如如下這行: import java.util.*; /** * 直接選擇排序算法的Java實現。<br/> * 1:從a[0]-a[N-1]中選出最小的數據,而後與a[0]交換位置<br/> * 2:從a[1]-a[N-1]中選出最小的數據,而後與a[1]交換位置(第1步結束後a[0]就是N個數的最小值)<br/> * 3:從a[2]-a[N-1]中選出最小的數據。而後與a[2]交換位置(第2步結束後a[1]就是N-1個數的最小值)<br/> * 以此類推。N-1次排序後,待排數據就已經依照從小到大的順序排列了。<br/> * 此代碼做爲課件提供給學生參考,在學完數組、循環、推斷後練習。<br/> * @author luo_wenqiang@126點com * @version 1.0.0 */ public class 直接選擇排序 { public static void main(String[] args) { //聲明一個數組 int[] array = new int[10]; //爲這個數組隨機填入整型數字 Random random = new Random(); for (int i = 0; i < array.length ; i++) { array[i] = random.nextInt(500); } System.out.print("原始數組 :"); System.out.println(Arrays.toString(array)); /**************************************** 如下開始正式的「直接選擇排序」算法 直接選擇排序的關鍵: 1:從a[0]-a[N-1]中選出最小的數據,而後與a[0]交換位置 2:從a[1]-a[N-1]中選出最小的數據,而後與a[1]交換位置(第1步結束後a[0]就是N個數的最小值) 3:從a[2]-a[N-1]中選出最小的數據,而後與a[2]交換位置(第2步結束後a[1]就是N-1個數的最小值) 以此類推。N-1次排序後。待排數據就已經依照從小到大的順序排列了。****************************************/ //N個數組元素,就需要循環N輪 for(int i = 0; i < array.length; i++){ //最小數的索引,該索引每次都依據外層循環的計數器來認爲初始值。
int minIndex = i; for (int j = i; j < (array.length); j++) { //依據最小數的索引,推斷當前這個數是否小於最小數。
//假設小於。則把當前數的索引做爲最小數的索引。
//不然不處理。 if(array[minIndex] > array[j]){ minIndex = j; } //直到循環完畢的時候。minIndex確定就是當前這輪循環中。最小的那個。 } //System.out.print(i + "輪。最小數" + array[minIndex] + "。"); //System.out.print("原索引" + minIndex + ",新索引" + i); //獲得最小數的索引後。把該索引相應的值放到最左邊,並且把最左邊的值放到索引所在的位置. //最左邊的值 int temp = array[i]; //把最小數索引相應的值放到最左邊 array[i] = array[minIndex]; //把原來最左邊相應的值放到最小數索引所在的位置 array[minIndex] = temp; System.out.println(String.format("%2s",(i + 1)) + "輪排序後:" + Arrays.toString(array)); } } }</span>
簡單的瞭解下堆、堆分最大堆和最小堆、最大堆跟比也子節點大、最小堆相反
最大堆和最小堆
假設從小到大用堆排序、每次都把最小堆的根輸出、而後用堆的最後一層最右邊的葉子節點補上去、而後進行堆排序(從節點數除以2的根開始排序)、選出最小根、輸出、依次這樣直到堆的數都輸出完。
這裏最重點的事實上是堆排序
推薦一篇博客吧
http://blog.csdn.net/genios/article/details/8157031
把每兩個數分紅一組、相比較、假設順序不正確就交換順出、循環一次以後、把兩個分組合成一個分組、這時候這個分組有四個數、而後進行排序、依此循環、最總合併成一個組、就是按從大到小排序的了、發張圖吧= =說的不太清。
代碼
package algorithm; public class MergeSort { // private static long sum = 0; /** * <pre> * 二路歸併 * 原理:將兩個有序表合併和一個有序表 * </pre> * * @param a * @param s * 第一個有序表的起始下標 * @param m * 第二個有序表的起始下標 * @param t * 第二個有序表的結束小標 * */ private static void merge(int[] a, int s, int m, int t) { int[] tmp = new int[t - s + 1]; int i = s, j = m, k = 0; while (i < m && j <= t) { if (a[i] <= a[j]) { tmp[k] = a[i]; k++; i++; } else { tmp[k] = a[j]; j++; k++; } } while (i < m) { tmp[k] = a[i]; i++; k++; } while (j <= t) { tmp[k] = a[j]; j++; k++; } System.arraycopy(tmp, 0, a, s, tmp.length); } /** * * @param a * @param s * @param len * 每次歸併的有序集合的長度 */ public static void mergeSort(int[] a, int s, int len) { int size = a.length; int mid = size / (len << 1); int c = size & ((len << 1) - 1); // -------歸併到僅僅剩一個有序集合的時候結束算法-------// if (mid == 0) return; // ------進行一趟歸併排序-------// for (int i = 0; i < mid; ++i) { s = i * 2 * len; merge(a, s, s + len, (len << 1) + s - 1); } // -------將剩下的數和倒數一個有序集合歸併-------// if (c != 0) merge(a, size - c - 2 * len, size - c, size - 1); // -------遞歸運行下一趟歸併排序------// mergeSort(a, 0, 2 * len); } public static void main(String[] args) { int[] a = new int[] { 4, 3, 6, 1, 2, 5 }; mergeSort(a, 0, 1); for (int i = 0; i < a.length; ++i) { System.out.print(a[i] + " "); } } }
排序算法 |
時間 |
特性 |
插入排序(插入) |
O(n2) |
記錄少適用、記錄多不適用 |
冒泡排序(交換) |
O(n2) |
穩定! |
高速排序(交換) |
O(nlog2n) |
不穩定! 平均時間最佳! 最壞狀況近似 O(n2) |
直接選擇(選擇) |
O(n2) |
簡單、easy實現、不適合N較大的狀況 |
堆排序(選擇) |
O(n log2n) |
不適用排序記錄較少、適合較多記錄 |
有序序列合併(歸併) |
O(n-h+1) |
|
二路歸併排序(歸併) |
O(n log2n) |
N較大時、歸併排序時間性能優於堆排序、但是所需儲存量較大 |
|
|
|
這些算法預計之後用都是別人封裝好的、拿來直接用便可、但是用東西、要知道他的特性、數多的時候用哪一個?數少的時候用哪一個、何時用、事實上算法也就那麼回事、不要想太複雜、考試的話、時間複雜度主要考考、空間複雜度很是少考、特性要考的、會出給一列數、讓你用算法排序、把步驟寫出來。
————————————高大上的算法————————————-
———————chenchen————————