排序算法java实现
1. 插入排序
原理:遍歷到第N個元素的時候前面的N-1個元素已經是排序好的了,那么就查找前面的N-1個元素把這第N個元素放在合適的位置,如此下去直到遍歷完序列的元素為止。
? ? 算法的復雜度也是簡單的,排序第一個需要1的復雜度,排序第二個需要2的復雜度,因此整個的復雜度就是
? ? 1 + 2 + 3 + …… + N = O(N ^ 2)的復雜度。
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.快速排序?
原理:選定一個樞紐元素,對待排序序列進行分割,分割之后的序列一個部分小于樞紐元素,一個部分大于樞紐元素,再對這兩個分割好的子序列進行上述的過程?!?/p>
假設輸入的數組中有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. 歸并排序
原理:把待排序序列分成相同大小的兩個部分,依次對這兩部分進行歸并排序,完畢之后再按照順序進行合并
兩個(或兩個以上)有序表合并成一個新的有序表,即把待排序的序列分成若干個子序列,每個子序列都是有序的,然后把有序子序列合并成整體有序序列,這個過程也稱為2-路歸并.歸并排序的一種穩定排序,即相等元素的順序不會改變.時間復雜度為O(nlogn),空間復雜度為log(n)
// 歸并排序中的合并算法 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≤)
滿足Key[i]>=Key[2i+1]&&key>=key[2i+2]稱為大頂堆,滿足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]稱為小頂堆。由上述性質可知大頂堆的堆頂的關鍵字肯定是所有關鍵字中最大的,小頂堆的堆頂的關鍵字是所有關鍵字中最小的
若將此序列所存儲的向量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 + 1nChild = 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);} }時間復雜度:
? ? ? ? ?平均情況?最好情況?最壞情況?
歸并排序?O(nlogn)?O(nlogn)?O(nlogn)?
快速排序?O(nlogn)?O(nlogn)?O(n2)?
希爾排序?O(n1.5)?O(n)?O(n1.5)?
插入排序?O(n2)?O(n)?O(n2)?
選擇排序?O(n2)?O(n2)?O(n2)?
堆排序:時間復雜度O(nlogn)?
選擇排序:時間復雜度O(n2)?
冒泡排序:時間復雜度O(n2)?
總結
以上是生活随笔為你收集整理的排序算法java实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下ip命令用法
- 下一篇: hdu 4049 Tourism Pla