1、直接插入排序
插入排序是一種最簡單直觀的排序算法,它的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。
public static void InsertSort(int[] array){
if(array == null || array.length == 0)
return ;
for(int i = 0;i < array.length; i++){
int value = array[i];
int j;
for( j = i - 1; j >= 0; j--){
if(value < array[j]){
array[j + 1] = array[j];
}else{
break;
}
}
array[j + 1] = value;
}
}
2、 希爾排序
希爾排序示意圖
希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。
希爾排序是基於插入排序的以下兩點性質而提出改進方法的:
插入排序在對幾乎已經排好序的數據操作時, 效率高, 即可以達到線性排序的效率
但插入排序一般來說是低效的, 因爲插入排序每次只能將數據移動一位
希爾排序的基本思想是:先將整個待排序的記錄序列分割成爲若干子序列,對所有的子序列同時分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。
算法步驟:
1)選擇一個增量序列t1,t2,…,tk,其中ti>tj,tk=1;
2)按增量序列個數k,對序列進行k 趟排序;
3)每趟排序,根據對應的增量ti,將待排序列分割成若干長度爲m 的子序列,分別對各子表進行直接插入排序。僅增量因子爲1 時,整個序列作爲一個表來處理,表長度即爲整個序列的長度。
public static void ShellSort(int[] array){
if(array == null || array.length == 0)
return ;
for(int gap = (array.length/2); gap > 0; gap/=2){
for(int i = gap; i < array.length; i++)
for(int j = i-gap; j>=0 && array[j]>array[j+gap]; j -= gap) {
int temp = array[j];
array[j] = array[j+gap];
array[j+gap] = temp;
}
}
}
3、直接選擇排序
步驟:每次從未排序序列中選擇最小(最大)元素放在已排序序列的尾部
public static void SelectSort(int[] array){
if(array == null || array.length == 0)
return ;
for(int i = 0;i < array.length; i++){
int minindex = array[i];
for(int j = i; j < array.length; j++){
if(array[j] < minindex)
minindex = j;
}
if(minindex != i){
int temp = array[i];
array[i] = array[minindex];
array[minindex] = temp;
}
}
}
4、堆排序
堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。
同時,我們對堆中的結點按層進行編號,將這種邏輯結構映射到數組中就是下面這個樣子
該數組從邏輯上講就是一個堆結構,我們用簡單的公式來描述一下堆的定義就是:
大頂堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小頂堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
算法步驟:
1)創建一個堆H[0..n-1]
2)把堆首(最大值)和堆尾互換
3)把堆的尺寸縮小1,並調用shift_down(0),目的是把新的數組頂端數據調整到相應位置
4) 重複步驟2,直到堆的尺寸爲1
//本函數功能是:根據數組array構建大根堆
//從第i個元素開始向下調整
public static void adjustHeap(int []arr,int i,int length){
for(int k=i*2+1;k<length;k=k*2+1){//從i結點的左子結點開始,也就是2i+1處開始
if(k+1<length && arr[k]<arr[k+1]){//如果左子結點小於右子結點,k指向右子結點
k++;
}
if(arr[k] >arr[i]){//如果子節點大於父節點,將子節點值賦給父節點(不用進行交換)
int temp = arr[i];
arr[i] = arr[k];
i = k;
arr[k] = temp;
}else{
break;
}
}
}
//堆排序算法
public static void HeapSort(int array[]){
//1.構建大頂堆,目的只是保證堆頂元素值最大
//保證堆從上到下大致有序看,任意從節點到葉子節點的路徑上元素是有序的
for(int i=array.length/2-1;i>=0;i--){
//從第一個非葉子結點(即array.length/2 - 1)從下至上,從右至左調整結構
adjustHeap(array,i,array.length);
}
//2.調整堆結構+交換堆頂元素與末尾元素,
for(int j=array.length-1;j>0;j--){
array[j] = array[0] ^ array[j];//將堆頂元素與末尾元素進行交換
array[0] = array[0] ^ array[j];
array[j] = array[0] ^ array[j];
adjustHeap(array,0,j);//重新對堆進行調整
}
}
5、冒泡排序
冒泡排序(Bubble Sort)也是一種簡單直觀的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因爲越小的元素會經由交換慢慢“浮”到數列的頂端。
public static void BubbleSort(int[] array){
if(array == null || array.length == 0)
return ;
for(int i = array.length - 1;i > 0; i--){
for(int j = 0 ;j < i;j++ ){
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
6、 快速排序
快速排序是由東尼·霍爾所發展的一種排序算法。在平均狀況下,排序 n 個項目要Ο(n log n)次比較。在最壞狀況下則需要Ο(n2)次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他Ο(n log n) 算法更快,因爲它的內部循環(inner loop)可以在大部分的架構上很有效率地被實現出來。
快速排序使用分治法(Divide and conquer)策略來把一個串行(list)分爲兩個子串行(sub-lists)。
public static void Qsort(int[] array,int start,int end) {
if(array == null || array.length == 0)
return ;
if(start > end)
return ;
else{
int i = start;
int j = end;
int flag = array[end];
while(i < j){
while(array[i] <= flag && i<j){
i++;
}
if(array[i] > flag && j > i){
array[j] = array[i];
array[i] = flag;
j--;
}
while(array[j] >= flag && j>i){
j--;
}
if(array[j] < flag && i<j){
array[i] = array[j];
array[j] = flag;
i++;
}
}
array[i] = flag;
Qsort(array,start,i - 1);
Qsort(array,i + 1,end);
}
}
7、歸併排序
歸併排序(Merge sort)是建立在歸併操作上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。
算法步驟:
申請空間,使其大小爲兩個已經排序序列之和,該空間用來存放合併後的序列
設定兩個指針,最初位置分別爲兩個已經排序序列的起始位置
比較兩個指針所指向的元素,選擇相對小的元素放入到合併空間,並移動指針到下一位置
重複步驟3直到某一指針達到序列尾
將另一序列剩下的所有元素直接複製到合併序列尾
public static void MergeSort(int[] copy,int[] array,int start,int end){
if(array == null || array.length == 0)
return ;
if(start >= end)
return ;
int middle = (end - start )/2;
MergeSort(copy,array,start,start + middle);
MergeSort(copy,array,start + middle + 1,end);
int i = start + middle;
int j = end;
int index = end;
while(i >= start && i <= (start + middle) && j >= (start + middle + 1) && j <= end){
if(copy[i] > copy[j]){
array[index--] = copy[i--];
}else{
array[index--] = copy[j--];
}
}
while(i >= start && i <= (start + middle) && index >= start){
array[index--] = copy[i--];
}
while(j >= (start + middle + 1) && j <= end && index >= start){
array[index--] = copy[j--];
}
for(int m = start;m <= end;m++){
copy[m] = array[m];
}
}
8、基數排序 (即桶排序)
典型的以空間換時間,時間複雜度爲線性時間