算法
選擇排序、快速排序、希爾排序、堆排序不是穩定的排序算法,java
冒泡排序、插入排序、歸併排序、基數排序是穩定的排序算法算法
有一個已經 有序 的數據序列,要求在這個已經排好的數據序列中插入一個數,但要求插入後此數據序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,插入排序的基本操做就是將一個數據插入到已經排好序的有序數據中,從而獲得一個新的、個數加一的有序數據,算法適用於少許數據的排序,時間複雜度爲 O(n^2)。是穩定的排序方法。數組
import java.util.Arrays; public class InsertSort { private static void insertSort(int[] arr) { int j; // 已排序列表下標 int t; // 待排序元素 for (int i = 1; i < arr.length; i++) { if (arr[i] < arr[i - 1]) { t = arr[i]; // 賦值給待排序元素 for (j = i - 1; j >= 0 && arr[j] > t; j--) { arr[j + 1] = arr[j]; // 從後往前遍歷已排序列表,逐個和待排序元素比較,若是已排序元素較大,則將它後移 } arr[j + 1] = t; // 將待排序元素插入到正確的位置 } } } public static void main(String[] args) { int[] ints = {5, 3, 4, 1, 2}; insertSort(ints); System.out.println(Arrays.toString(ints)); } }
void InsertSort(ElemType A[],int n){ int i,j; for(i=2;i<=n;i++) if(A[i]<A[i-1]){ A[0]=A[i]; //複製爲哨兵,A[0]不存放元素 for(j=i-1;A[0]<A[j];--j) A[j+1]=A[j]; //全部比待插入元素值大的都日後移一位,騰出空位 A[j+1]=A[0]; //複製到插入位置 } }
void InsertSort(ElemType A[],int n){ int i,j,low,high,mid; for(i=2;i<=n;i++){ //i記錄的是待插入的元素下標,也就是說i-1以前的元素都是有序的 A[0]=A[i]; //保存待插入的值 low=1;high=i-1; while(low<=high){ //折半查找 mid=(low+high)/2; if(A[mid].key>A[0].key) high=mid-1; else low=mid+1; } //找到了待插入的位置 接下來從後往前依次後移元素騰出位置 for(j=i-1;j>=high+1;--j)A[j+1]=A[j]; A[high+1]=A[0]; //由於此時high指向的是待插入位置的前一位 } }
void ShellSort (ElemType A[],int n){ int i,j; for(dk=n/2;dk>=1;dk=dk/2) //初始增量爲總長度的一半,以後依次除2且向下取整, //且最後一次要爲1 for(i=dk+1;i<=n;++i) if(A[i].key<A[i-dk].key){ //A[i].key是待插入的關鍵字,i-dk以前的都是有序的,如 //果待插入的比有序序列最後一個小, 則須要進行排序(進入if語句塊),若是大則不須要(跳出if語句塊) A[0]=A[i]; //待插入關鍵字暫存在A[0] for(j=i-dk;j>0&&A[0].key<A[j].key; j-=dk) //待插入關鍵字以前以dk爲增量的關鍵字只要比待插入關鍵字大的都日後移動dk位 A[j+dk]=A[j]; A[j+dk]=A[0]; //找到了待插入的位置,就將待插入關鍵字插入這個位置 } }
冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。 它重複地走訪過要排序的元素列, 依次比較兩個相鄰的元素 ,若是他們的順序(如從大到小、首字母從 A 到 Z)錯誤就把他們交換過來。走訪元素的工做是重複地進行直到沒有相鄰元素須要交換,也就是說該元素已經排序完成。 這個算法的名字由來是由於越大的元素會經由交換慢慢「浮」到數列的頂端(升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端同樣,故名「冒泡排序」。架構
import java.util.Arrays; public class BubbleSort { public static void sort(int[] arr) { for (int i = 0; i < arr.length-1; i++) { for (int j = 0; j < arr.length - i - 1; j++) { //若是當前元素比後一位元素大 交換位置 if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } public static void main(String[] args) { int[] ints = {5, 3, 4, 1, 2}; sort(ints); System.out.println(Arrays.toString(ints)); } }
快速排序(英語:Quicksort),又稱劃分交換排序(partition-exchange sort),簡稱快排,也是一種排序算法。最先由東尼·霍爾提出。在平均情況下,排序 n 個項目要 O(nlogn) 次比較。在最壞情況下則須要 O(n^2) 次比較,但這種情況並不常見。事實上,快速排序 O(nlogn) 一般明顯比其餘算法更快,由於它的內部循環(inner loop)能夠在大部分的架構上頗有效率地達成。ide
int Partition(ElemType A[],int low,int high){ //low是當前待排序的序列起始下標,high是末尾下標 ElemType pivot=A[low]; //第一個元素做爲樞軸 while(low<high){ while(low<high&&A[high]>=pivot) --high;//先從末尾往前找到第一個比樞軸小的元素 A[low]=A[high]; //用high的元素替換low的元素 while(low<high&&A[low]<=pivot) ++low; //再從開頭日後找到第一個比樞軸大的元素 A[high]=A[low]; //用low的元素替換high的元素 } A[low]=pivot; //樞軸元素存放到最終位置 return low; //返回存放樞軸的最終位置 } void QuickSort(ElemType A[],int low,int high){ if(low<high){ //low和high值要合法 int pivotpos=Partition(A,low,high); QuickSort(A,low,pivotpos-1); //分治遞歸左半部分 QuickSort(A,pivotpos+1,high); //分治遞歸右半部分 } }
import java.util.Arrays; public class QuickSort { public static void sort(int[] arr, int head, int tail) { if (head >= tail || arr == null || arr.length <= 1) { return; } //設置數組的起始位置 i 結束位置j 基準 pivot 爲數組的中間 int i = head, j = tail, pivot = arr[(head + tail) / 2]; while (i <= j) { //當數組小於基準 循環結束後 至關於i所處的位置的值爲大於基準的元素 while (arr[i] < pivot) { ++i; } //當數組大於基準 循環結束後 至關於j所處的位置的值爲小於於基準的元素 while (arr[j] > pivot) { --j; } //若是i<j 那麼則將交互i j對應位置的值 if (i < j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; //將指針繼續移動 ++i; --j; } else if (i == j) { //若是i=j 那麼說明本次排序已經結束 將i++ 若是這裏不使用i++ 那麼後面的sort(arr,i,tail)將改成arr(arr,i+1,tail) ++i; } } //繼續將數組分割 sort(arr, head, j); sort(arr, i, tail); } public static void main(String[] args) { int[] ints = {5, 3, 4, 1, 2}; sort(ints, 0, ints.length - 1); System.out.println(Arrays.toString(ints)); } }
void SelectSort(ElemType A[],int n){ for(i=0;i<n-1;i++){ //依次從後面序列中選擇當前最小的元素做爲第i個元素 最後一個元素不須要排序 min=i; //min存的是當前最小元素所在下標,初值設爲第i個 for(j=i+1;j<n;j++) //從第i個元素日後找,一直要找到最後一個元素 if(A[j]<A[min]) min=j; //若是這個值更小,則更新min值爲這個更小的元素所在下標 if(min!=i) { //若是第i個元素不是剩下元素最小的,則和最小的進行交換 ElemType temp=A[i]; A[i]=A[min]; A[min]=temp; } } }
void BuildMaxHeap(ElemType A[],int len){ for(int i=len/2;i>0;i--) AdjustDown(A,i,len); //由數組下標高處往低處 從第一個可能須要調整的非葉結點 // 開始檢查,直到根結點(注意根結點下標不是0,是從1開始存儲) } void AdjustDown(ElemType A[],int k,int len){ //A是存儲堆的數組,k是須要檢查的結點下標,len是堆中結點個數 A[0]=A[k]; //A[0]暫存這個須要檢查的結點值 for(i=2*k;i<=len;i*=2){ //從這個結點的左孩子開始往下比較, // 若是發生交換,對交換過的結點繼續和它的孩子比較 if(i<len&&A[i]<A[i+1])i++; //若是右孩子大一些,就只要考慮和右孩子比較 if(A[0]>=A[i]) break; //若是這個結點的值不小於它的較大孩子結點值 則不須要交換 else{ A[k]=A[i]; //若是這個結點的值小於它的較大孩子 //結點值則將較大的孩子結點值賦值給該結點 k=i; //i賦值給k也就是從i開始繼續往下檢查 直到全部結點檢查結束 } } A[k]=A[0]; //檢查到最後k的值就是最後一輪交換過的結點位置下標 將該結點換過去 }
歸併排序(MERGE-SORT)是創建在歸併操做上的一種有效的排序算法,該算法是採用分治法(
Divide and Conquer
)的一個很是典型的應用。將已有序的子序列合併,獲得徹底有序的序列;即先使每一個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。oop
申請空間,使其大小爲兩個已經排序序列之和,該空間用來存放合併後的序列ui
設定兩個指針,最初位置分別爲兩個已經排序序列的起始位置3d
比較兩個指針所指向的元素,選擇相對小的元素放入到合併空間,並移動指針到下一位置指針
重複步驟 3 直到某一指針到達序列尾code
將另外一序列剩下的全部元素直接複製到合併序列尾
import java.util.Arrays; public class MergeSort { public static void mergeSort(int[] arrays, int left, int right) { // 若是數組還能夠拆分 if (left < right) { //數組的中間位置 int middle = (left + right) / 2; //拆分左邊數組 mergeSort(arrays, left, middle); //拆分右邊數組 mergeSort(arrays, middle + 1, right); //合併 merge(arrays, left, middle, right); } } /** * 合併數組 */ public static void merge(int[] arr, int left, int middle, int right) { //申請合併空間 大小爲兩個已經排序序列之和 int[] temp = new int[right - left + 1]; //i 和 j爲兩個已經排好序的數組的起始位置 int i = left; int j = middle + 1; int k = 0; //排序 while (i <= middle && j <= right) { //將比較小的數組放入合併空間 if (arr[i] < arr[j]) { temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } //將左邊剩餘元素寫入合併空間 while (i <= middle) { temp[k++] = arr[i++]; } //將右邊剩餘的元素寫入合併空間 while (j <= right) { temp[k++] = arr[j++]; } //將排序後的數組寫回原來的數組 for (int l = 0; l < temp.length; l++) { arr[l + left] = temp[l]; } } public static void main(String[] args) { int[] ints = {5, 3, 4, 1, 2}; mergeSort(ints,0,ints.length-1); System.out.println(Arrays.toString(ints)); } }
ElemType *B=(ElemType *)malloc((n+1)*sizeof(ElemType)); //輔助數組B(動態分配內存) void Merge(ElemType A[],int low,int mid,int high){ //表A的兩段A[low…mid]和A[mid+1…high]各自有序,將它們合併成一個有序表 for(int k=low;k<=high;k++)B[k]=A[k]; //將A中全部元素複製到B中 for(int i=low,j=mid+1,k=i;i<=mid&&j<=high;k++){ k是歸併以後數組的下標計數器 if(B[i]<=B[j]) //比較B的左右兩段中的元素 A[k]=B[i++]; //將較小值複製到A中 else A[k]=B[j++]; } while(i<=mid) A[k++]=B[i++]; //若第一個表未檢測完,直接將剩下的部分複製過來 while(j<=high) A[k++]=B[j++]; //若第二個表未檢測完,直接將剩下的部分複製過來 }