標籤:
1. 插入排序
原理:遍曆到第N個元素的時候前面的N-1個元素已經是排序好的了,那麼就尋找前面的N-1個元素把這第N個元素放在合適的位置,如此下去直到遍曆完序列的元素為止。
演算法的複雜度也是簡單的,排序第一個需要1的複雜度,排序第二個需要2的複雜度,因此整個的複雜度就是
1 + 2 + 3 + …… + N = O(N ^ 2)的複雜度。
// 插入排序void InsertSort(int array[], int length){ int i, j, key; for (i = 1; i < length; i++) { key = array; // 把i之前大於array的資料向後移動 for (j = i - 1; j >= 0 && array[j] > key; j--) { array[j + 1] = array[j]; } // 在合適位置安放當前元素 array[j + 1] = key; }}
2.shell排序
原理:將序列分成子序列,然後分別對子序列進行排序,最後將子序列組合起來。每次排序把序列的元素按照某個增量分成幾個子序列,對這幾個子序列進行插入排序,然後不斷的縮小增量擴大每個子序列的元素數量,直到增量為一的時候子序列就和原先的待排列序列一樣了,此時只需要做少量的比較和移動就可以完成對序列的排序了。
// shell排序void ShellSort(int array[], int length){ int temp; // 增量從數組長度的一半開始,每次減小一倍 for (int increment = length / 2; increment > 0;increment /= 2) for (int i = increment; i < length; ++i) { temp = array; // 對一組增量為increment的元素進行插入排序 for (int j = i; j >= increment; j -= increment) { // 把i之前大於array的資料向後移動 if (temp < array[j - increment]) { array[j] = array[j - increment]; } else { break; } } // 在合適位置安放當前元素 array[j] = temp; }}
3.冒泡排序
原理:每次遍曆完序列都把最大(小)的元素放在最前面,然後再對剩下的序列重複前面的一個過程,每次遍曆完之後待排序序列就少一個元素,當待排序序列減小為只有一個元素的時候排序就結束了。因此,複雜度在最壞的情況下是O(N ^ 2) 冒泡排序是穩定的,不會改變相同元素的相對順序。
void Swap( int * a, int * b) { int temp; temp = * a; * a = * b; * b = temp;} // 冒泡排序 void BubbleSort( int array[], int length) { // 記錄一次遍曆中是否有元素的交換,總是與相鄰的元素比較,並向前移 bool exchange; for ( int i = 0 ; i<length;++ i) { exchange= false ; for ( int j=i+1 ; j< length;++j) { if (array[j] < array) { exchange= true ; Swap( & array[j], & array); } } // 如果這次遍曆沒有元素的交換,那麼排序結束 if ( false == exchange) break ; }}
4.快速排序
原理:選定一個樞紐元素,對待排序序列進行分割,分割之後的序列一個部分小於樞紐元素,一個部分大於樞紐元素,再對這兩個分割好的子序列進行上述的過程。
假設輸入的數組中有k個小於軸值的結點,於是這些結點被放到數組最左邊的k個位置上,而大於軸值得被放到數組最右邊的n-k個位置上。
// 對一個給定範圍的子序列選定一個樞紐元素,執行完函數之後返回分割元素所在的位置,// 在分割元素之前的元素都小於樞紐元素,在它後面的元素都大於這個元素int Partition(int array[], int low, int high){ // 採用子序列的第一個元素為樞紐元素 int pivot = array[low]; while (low < high) { // 從後往前在後半部分中尋找第一個小於樞紐元素的元素 while (low < high && array[high] >= pivot) { --high; } // 將這個比樞紐元素小的元素交換到前半部分 Swap(&array[low], &array[high]); // 從前往後在前半部分中尋找第一個大於樞紐元素的元素 while (low < high && array[low] <= pivot) { ++low; } // 將這個比樞紐元素大的元素交換到後半部分 Swap(&array[low], &array[high]); } // 返回樞紐元素所在的位置 return low;}// 快速排序void QuickSort(int array[], int low, int high){ if (low < high) { int n = Partition(array, low, high); QuickSort(array, low, n); QuickSort(array, n + 1, high); }}
5. 歸併排序
原理:把待排序序列分成相同大小的兩個部分,依次對這兩部分進行歸併排序,完畢之後再按照順序進行合并
// 歸併排序中的合并演算法void Merge(int array[], int start, int mid, int end){ int temp1[10], temp2[10]; int n1, n2; n1 = mid - start + 1; n2 = end - mid; // 拷貝前半部分數組 for (int i = 0; i < n1; i++) { temp1 = array[start + i]; } // 拷貝後半部分數組 for (int i = 0; i < n2; i++) { temp2 = array[mid + i + 1]; } // 把後面的元素設定的很大 temp1[n1] = temp2[n2] = 1000; // 逐個掃描兩部分數組然後放到相應的位置去 for (int k = start, i = 0, j = 0; k <= end; k++) { if (temp1 <= temp2[j]) { array[k] = temp1; i++; } else { array[k] = temp2[j]; j++; } }}// 歸併排序void MergeSort(int array[], int start, int end){ if (start < end) { int i; i = (end + start) / 2; // 對前半部分進行排序 MergeSort(array, start, i); // 對後半部分進行排序 MergeSort(array, i + 1, end); // 合并前後兩部分 Merge(array, start, i, end); }}
6.選擇排序
原理 : 每一趟從待排序的資料元素中選出最小(或最大)的一個元素, 順序放在已排好序的數列的最後,直到全部待排序的資料元素排完。 選擇排序是不穩定的排序方法。
第i次是選擇數組中第i小的記錄,並將該記錄放到數組的第i個位置。
package sort.select;import java.util.Random;/** * @author liangge * */public class Main {public static void main(String[] args) {Random ran = new Random();int[] sort = new int[10];for (int i = 0; i < 10; i++) {sort[i] = ran.nextInt(50);}System.out.print("排序前的數組為");for (int i : sort) {System.out.print(i + " ");}selectSort(sort);System.out.println();System.out.print("排序後的數組為");for (int i : sort) {System.out.print(i + " ");}}/** * 選擇排序 * @param sort */private static void selectSort(int[] sort){for(int i =0;i<sort.length-1;i++){for(int j = i+1;j<sort.length;j++){if(sort[j]<sort[i]){int temp = sort[j];sort[j] = sort[i];sort[i] = temp;}}}}}
7.堆排序
堆的定義:
n個關鍵字序列Kl,K2,…,Kn稱為堆,若且唯若該序列滿足如下性質(簡稱為堆性質):
(1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤)
若將此序列所儲存的向量R[1……n]看做是一棵完全二叉樹的儲存結構,則堆實質上是滿足如下性質的完全二叉樹:樹中任一非葉結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。
堆的這個性質使得可以迅速定位在一個序列之中的最小(大)的元素。
堆排序演算法的過程如下:1)得到當前序列的最小(大)的元素 2)把這個元素和最後一個元素進行交換,這樣當前的最小(大)的元素就放在了序列的最後,而原先的最後一個元素放到了序列的最前面 3)的交換可能會破壞堆序列的性質(注意此時的序列是除去已經放在最後面的元素),因此需要對序列進行調整,使之滿足於上面堆的性質。重複上面的過程,直到序列調整完畢為止。
// array是待調整的堆數組,i是待調整的數組元素的位置,length是數組的長度void HeapAdjust(int array[], int i, int nLength){ int nChild, nTemp; for (nTemp = array; 2 * i + 1 < nLength; i = nChild) { // 子結點的位置是 父結點位置 * 2 + 1 nChild = 2 * i + 1; // 得到子結點中較大的結點 if (nChild != nLength - 1 && array[nChild + 1] > array[nChild]) ++nChild; // 如果較大的子結點大於父結點那麼把較大的子結點往上移動,替換它的父結點 if (nTemp < array[nChild]) { array = array[nChild]; } else // 否則退出迴圈 { break; } } // 最後把需要調整的元素值放到合適的位置 array = nTemp;}// 堆排序演算法void HeapSort(int array[], int length){ // 調整序列的前半部分元素,調整完之後第一個元素是序列的最大的元素 for (int i = length / 2 - 1; i >= 0; --i) { HeapAdjust(array, i, length); } // 從最後一個元素開始對序列進行調整,不斷的縮小調整的範圍直到第一個元素 for (int i = length - 1; i > 0; --i) { // 把第一個元素和當前的最後一個元素交換, // 保證當前的最後一個位置的元素都是在現在的這個序列之中最大的 Swap(&array[0], &array); // 不斷縮小調整heap的範圍,每一次調整完畢保證第一個元素是當前序列的最大值 HeapAdjust(array, 0, i); }}
排序演算法java實現