排序,就是使一串記錄,按照其中的某個或某些關鍵字的大小,遞增或遞減的排列起來的操做。排序算法,就是如何使得記錄按照要求排列的方法。算法
排序算法大致可分爲兩種:shell
一種是比較排序,時間複雜度O(nlogn) ~ O(n^2),主要有:冒泡排序,選擇排序,插入排序,歸併排序,堆排序,快速排序等。數組
另外一種是非比較排序,時間複雜度能夠達到O(n),主要有:計數排序,基數排序,桶排序等函數
穩定:若是a本來在b前面,而a=b,排序以後a仍然在b的前面。性能
不穩定:若是a本來在b的前面,而a=b,排序以後 a 可能會出如今 b 的後面。spa
時間複雜度:對排序數據的總的操做次數。反映當n變化時,操做次數呈現什麼規律。code
空間複雜度:是指算法在計算機內執行時所需存儲空間的度量,它也是數據規模n的函數。 blog
一、冒泡排序排序
* 冒泡排序
* 冒泡排序是一種極其簡單的排序算法,也是我所學的第一個排序算法。它重複地走訪過要排序的元素,依次比較相鄰兩個元素
* ,若是他們的順序錯誤就把他們調換過來,直到沒有元素再須要交換,排序完成。這個算法的名字由來是由於越小(或越大)的
* 元素會經由交換慢慢「浮」到數列的頂端。
*
* 冒泡排序算法的運做以下:
* (1)比較相鄰的元素,若是前一個比後一個大,就把它們兩個調換位置。
* (2)對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對。這步作完後,最後的元素會是最大的數。
* (3)針對全部的元素重複以上的步驟,除了最後一個。
* (4)持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較。遞歸
public class BubbleSort { public static int[] sort(int[] arr){ int temp=0; int n=arr.length; for(int i=1;i<n;i++){ for(int j=0;j<n-i;j++){ if(arr[j]>arr[j+1]){ temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } //輸出每次排序完成後的數組 PrintArray.printArray(arr); System.out.println(); } return arr; } }
二、插入排序
插入排序在實現上,一般採用in-place排序(即只需用到O(1)的額外空間的排序),於是在從後向前掃描過程當中,
* 須要反覆把已排序元素逐步向後挪位,爲最新元素提供插入空間。
*
* 具體算法描述以下:
* 從第一個元素開始,該元素能夠認爲已經被排
* 取出下一個元素,在已經排序的元素序列中從後向前掃描
* 若是該元素(已排序)大於新元素,將該元素移到下一位
* 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置
* 將新元素插入到該位置後
* 重複步驟2~5*/
public class InsertSort { public static int[] sort(int[] arr){ int n=arr.length; for(int i=1;i<n;i++){ int num=arr[i]; //當前位置前一個位置 int j=i-1; while(j>=0 && arr[j]>num){ arr[j+1]=arr[j]; j--; } arr[j+1]=num; PrintArray.printArray(arr); System.out.println(); } return arr; } }
三、希爾排序
/*希爾排序,也叫遞減增量排序,是插入排序的一種更高效的改進版本。希爾排序是不穩定的排序算法。
* 希爾排序是基於插入排序的如下兩點性質而提出改進方法的
* 插入排序在對幾乎已經排好序的數據操做時,效率高,便可以達到線性排序的效率
* 但插入排序通常來講是低效的,由於插入排序每次只能將數據移動一位
* 希爾排序經過將比較的所有元素分爲幾個區域來提高插入排序的性能。這樣可讓一個元素能夠一次性地朝最終位置前進一大步。
* 而後算法再取愈來愈小的步長進行排序,算法的最後一步就是普通的插入排序,可是到了這步,需排序的數據幾乎是已排好的了(此時插入排序較快)。
* 假設有一個很小的數據在一個已按升序排好序的數組的末端。若是用複雜度爲O(n^2)的排序(冒泡排序或直接插入排序),可能會進行n次的
* 比較和交換才能將該數據移至正確位置。而希爾排序會用較大的步長移動數據,因此小數據只需進行少數比較和交換便可到正確位置。
* */
public static void shellSort(int[] arr){ for(int r=arr.length/2;r>=1;r=r/2){ int temp; int j = 0; for(int i=r;i<arr.length;i=i+1){ temp=arr[i]; j=i-r; while(j>=0&&temp<arr[j]){ arr[j+r]=arr[j]; j=j-r; } arr[j+r]=temp; } } for(int a:arr) System.out.print(a+" "); System.out.println(); }
四、選擇排序
* 選擇排序也是一種簡單直觀的排序算法。它的工做原理很容易理解:初始時在序列中找到最小(大)元素,放到序列
* 的起始位置做爲已排序序列;而後,再從剩餘未排序元素中繼續尋找最小(大)元素,放到已排序序列的末尾。以此
* 類推,直到全部元素均排序完畢。
*
* 注意選擇排序與冒泡排序的區別:
* 冒泡排序經過依次交換相鄰兩個順序不合法的元素位置,從而將當前最小(大)元素放到合適的位置;而選擇排序每遍
* 歷一次都記住了當前最小(大)元素的位置,最後僅需一次交換操做便可將其放到合適的位置*/
public static int[] sort(int[] arr){ int n=arr.length; for(int i=0;i<n-1;i++){ int minNum=i; for(int j=i+1;j<n;j++){ if(arr[minNum]>arr[j]){ minNum=j; } } int temp=arr[i]; arr[i]=arr[minNum]; arr[minNum]=temp; } return arr; }
五、快速排序
*快速排序,顧名思義,是一種速度快,效率高的排序算法。
快排原理:
在要排的數(好比數組A)中選擇一箇中心值key(好比A[0]),經過一趟排序將數組A分紅兩部分,
其中以key爲中心,key右邊都比key大,key左邊的都key小,而後對這兩部分分別重複這個過程,
直到整個有序。
整個快排的過程就簡化爲了一趟排序的過程,而後遞歸調用就好了。
一趟排序的方法:
1,定義i=0,j=A.lenght-1,i爲第一個數的下標,j爲最後一個數下標
2,從數組的最後一個數Aj從右往左找,找到第一小於key的數,記爲Aj;
3,從數組的第一個數Ai 從左往右找,找到第一個大於key的數,記爲Ai;
4,交換Ai 和Aj
5,重複這個過程,直到 i=j
6,調整key的位置,把A[i] 和key交換
public static int[] sort(int[] arr,int l,int r){ int size=arr.length; if(l<r){ int i=l,j=r,x=arr[l]; while(i<j){ while(i<j&&arr[j]>x) j--; if(i<j) arr[i++]=arr[j]; while(i<j&&arr[i]<x) i++; if(i<j) arr[j--]=arr[i]; } arr[i]=x; sort(arr, l, i-1); sort(arr, i+1, r); } return arr; }