国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java 排序算法

2019-11-06 09:33:32
字體:
來源:轉載
供稿:網友

排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存。我們這里說說八大排序就是內部排序。 日常操作中常見的排序方法有:插入排序、希爾排序、選擇排序、堆排序、冒泡排序、快速排序、歸并排序、基數排序等。

一、插入排序

1 原理

插入排序的工作原理是通過構建有序序列,對于未排序數據,在已排序序列中從后向前掃描,找到相應位置并插入。

每步將一個待排序的記錄,按其順序碼大小插入到前面已經排序的字序列的合適位置(從后向前找到合適位置后),直到全部插入排序完為止。

2 實現步驟

經常碰到這樣一類排序問題:把新的數據插入到已經排好的數據列中。 (1)將第一個數和第二個數排序,然后構成一個有序序列 (2)將第三個數插入進去,構成一個新的有序序列。 (3)對第四個數、第五個數……直到最后一個數,重復第二步。 這里寫圖片描述

3 實現邏輯

(1)首先設定插入次數,即循環次數,for(int i=1;i<length;i++),1個數的那次不用插入。 (2)設定插入數和得到已經排好序列的最后一個數的位數。insertNum和j=i-1。 (3)從最后一個數開始向前循環,如果插入數小于當前數,就將當前數向后移動一位。 (4)將當前數放置到空著的位置,即j+1。

4 代碼實現

public void insertSort(int[] numbers){ int size = numbers.length;//數組長度,將這個提取出來是為了提高速度。 int insertNum;//要插入的數 for(int i = 1;i<size ;i++){//插入的次數 insertNum=numbers[i];//要插入的數 int j=i-1;//已經排序好的序列元素個數 //序列從后到前循環,將大于insertNum的數向后移動一格 while(j>=0&&numbers[j]>insertNum){ numbers[j+1]=numbers[j];//元素移動一格 j--; } numbers[j+1]=insertNum;//將需要插入的數放在要插入的位置。 }}public void insertSort(int[] numbers){ int size = numbers.length;//數組長度,將這個提取出來是為了提高速度。 int insertNum= 0;//要插入的數 int j = 0; for(int i = 0 ; i < size ; i++){ insertNum = numbers[i];//要插入的數 //假如insertNum比前面的值小,則將前面的值后移 for(j = i ; j > 0 && insertNum < numbers[j-1] ; j--){ numbers[j] = numbers[j-1];//元素移動一格 } numbers[j] = insertNum;//將需要插入的數放在要插入的位置。 }}

二、希爾排序

1 原理

希爾排序是1959 年由D.L.Shell 提出來的,相對直接排序有較大的改進。希爾排序又叫縮小增量排序。

先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,待整個序列中的記錄“基本有序”時,再對全體記錄進行依次直接插入排序。

2 實現步驟

對于直接插入排序問題,數據量巨大時。 (1)將數的個數設為n,取奇數k=n/2,將下標差值為k的書分為一組,構成有序序列。 (2)再取k=k/2 ,將下標差值為k的書分為一組,構成有序序列。 (3)重復第二步,直到k=1執行簡單插入排序。 這里寫圖片描述

3 實現邏輯

(1)首先確定分的組數。 (2)然后對組中元素進行插入排序。 (3)然后將length/2,重復1,2步,直到length=0為止。

4 代碼實現

public void shellSort(int[] a){ int d = a.length; while (d!=0) { d=d/2; for (int x = 0; x < d; x++) {//分的組數 for (int i = x + d; i < a.length; i += d) {//組中的元素,從第二個數開始 int j = i - d;//j為有序序列最后一位的位數 int temp = a[i];//要插入的元素 for (; j >= 0 && temp < a[j]; j -= d) {//從后往前遍歷。 a[j + d] = a[j];//向后移動d位 } a[j + d] = temp; } } }}public static void shellSort(int[] data){ int j = 0; int temp = 0; //每次將步長縮短為原來的一半 for (int increment = data.length / 2; increment > 0; increment /= 2){ for (int i = increment; i < data.length; i++){ temp = data[i]; for (j = i; j >= increment; j -= increment){ //如想從小到大排只需修改這里 if(temp > data[j - increment]){ data[j] = data[j - increment]; }else{ break; } } data[j] = temp; } }}

三、選擇排序

1 原理

在要排序的一組數中,選出最小的一個數與第一個位置的數交換;然后在剩下的數當中再找最小的與第二個位置的數交換,如此循環到倒數第二個數和最后一個數比較為止。

常用于取序列中最大最小的幾個數時。

如果每次比較都交換,那么就是交換排序;如果每次比較完一個循環再交換,就是簡單選擇排序。

2 實現步驟

(1)遍歷整個序列,將最小的數放在最前面。 (2)遍歷剩下的序列,將最小的數放在最前面。 (3)重復第二步,直到只剩下一個數。 這里寫圖片描述

3 實現邏輯

(1)首先確定循環次數,并且記住當前數字和當前位置。 (2)將當前位置后面所有的數與當前數字進行對比,小數賦值給key,并記住小數的位置。 (3)比對完成后,將最小的值與第一個數的值交換。 (4)重復2、3步。

4 代碼實現

public void selectSort(int[] a) { int length = a.length; for (int i = 0; i < length; i++) {//循環次數 int key = a[i]; int position=i; for (int j = i + 1; j < length; j++) {//選出最小的值和位置 if (a[j] < key) { key = a[j]; position = j; } } a[position]=a[i];//交換位置 a[i]=key; }}public static void selectSort(int[] numbers){ int size = numbers.length; //數組長度 int temp = 0 ; //中間變量 for(int i = 0 ; i < size ; i++){ int k = i; //待確定的位置 //選擇出應該在第i個位置的數 for(int j = size -1 ; j > i ; j--){ if(numbers[j] < numbers[k]){ k = j; } } //交換兩個數 temp = numbers[i]; numbers[i] = numbers[k]; numbers[k] = temp; }}

四、堆排序

1 原理

具有n個元素的序列 (h1,h2,…,hn),當且僅當滿足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1) (i=1,2,…,n/2)時稱之為堆。

完全二叉樹可以很直觀地表示堆的結構。堆頂為根,其它為左子樹、右子樹。

堆排序是一種樹形選擇排序,是對直接選擇排序的有效改進。

2 實現步驟

(1)將序列構建成大頂堆。 (2)將根節點與最后一個節點交換,然后斷開最后一個節點。 (3)重復第一、二步,直到所有節點斷開。 這里寫圖片描述

3 實現邏輯

(1)初始時把要排序的數的序列看作是一棵順序存儲的二叉樹,調整它們的存儲序,使之成為一個堆,這時堆的根節點的數最大。 (2)將根節點與堆的最后一個節點交換。 (3)對前面(n-1)個數重新調整使之成為堆。 (4)依此類推,直到只有兩個節點的堆,并對 它們作交換,最后得到有n個節點的有序序列。 從算法描述來看,堆排序需要兩個過程,一是建立堆,二是堆頂與堆的最后一個元素交換位置。所以堆排序有兩個函數組成。一是建堆的滲透函數,二是反復調用滲透函數實現排序的函數。

4 代碼實現

public class HeapSort { public static void main(String[] args) { int[] a={49,38,65,97,76,13,27,49,78,34,12,64}; int arrayLength=a.length; //循環建堆 for(int i=0;i<arrayLength-1;i++){ //建堆 buildMaxHeap(a,arrayLength-1-i); //交換堆頂和最后一個元素 swap(a,0,arrayLength-1-i); System.out.PRintln(Arrays.toString(a)); } } //對data數組從0到lastIndex建大頂堆 public static void buildMaxHeap(int[] data, int lastIndex){ //從lastIndex處節點(最后一個節點)的父節點開始 for(int i=(lastIndex-1)/2;i>=0;i--){ //k保存正在判斷的節點 int k=i; //如果當前k節點的子節點存在 while(k*2+1<=lastIndex){ //k節點的左子節點的索引 int biggerIndex=2*k+1; //如果biggerIndex小于lastIndex,即biggerIndex+1代表的k節點的右子節點存在 if(biggerIndex<lastIndex){ //若果右子節點的值較大 if(data[biggerIndex]<data[biggerIndex+1]){ //biggerIndex總是記錄較大子節點的索引 biggerIndex++; } } //如果k節點的值小于其較大的子節點的值 if(data[k]<data[biggerIndex]){ //交換他們 swap(data,k,biggerIndex); //將biggerIndex賦予k,開始while循環的下一次循環,重新保證k節點的值大于其左右子節點的值 k=biggerIndex; }else{ break; } } } } //交換 private static void swap(int[] data, int i, int j) { int tmp=data[i]; data[i]=data[j]; data[j]=tmp; } }

五、冒泡排序

1 原理

冒泡排序是一種簡單的排序算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。

2 實現步驟

(1)將序列中所有元素兩兩比較,將最大的放在最后面。 (2)將剩余序列中所有元素兩兩比較,將最大的放在最后面。 (3)重復第二步,直到只剩下一個數。 這里寫圖片描述

3 實現邏輯

(1)設置循環次數。 (2)設置開始比較的位數,和結束的位數。 (3)兩兩比較,將最小的放到前面去。 (4)重復2、3步,直到循環次數完畢。

4 代碼實現

public void bubbleSort(int[] a){ int length=a.length; int temp; for(int i=0;i<a.length;i++){ for(int j=0;j<a.length-i-1;j++){ if(a[j]>a[j+1]){ temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } }}

六、快速排序

1 原理

通過一趟排序將待排序記錄分割成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分關鍵字小,則分別對這兩部分繼續進行排序,直到整個序列有序。

2 實現步驟

(1)選擇第一個數為p,小于p的數放在左邊,大于p的數放在右邊。 (2)遞歸的將p左邊和右邊的數都按照第一步進行,直到不能遞歸。 這里寫圖片描述

3 實現邏輯

(1)把整個序列看做一個數組,把第零個位置看做中軸,和最后一個比,如果比它小交換,比它大不做任何處理。 (2)交換了以后再和小的那端比,比它小不交換,比他大交換。這樣循環往復,一趟排序完成,左邊就是比中軸小的,右邊就是比中軸大的,然后再用分治法,分別對這兩個獨立的數組進行排序。

4 代碼實現

public static void quickSort(int[] numbers, int start, int end) { if (start < end) { int base = numbers[start]; // 選定的基準值(第一個數值作為基準值) int temp; // 記錄臨時中間值 int i = start, j = end; do { while ((numbers[i] < base) && (i < end)) i++; while ((numbers[j] > base) && (j > start)) j--; if (i <= j) { temp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = temp; i++; j--; } } while (i <= j); if (start < j) quickSort(numbers, start, j); if (end > i) quickSort(numbers, i, end); } }

快速排序是通常被認為在同數量級(O(nlog2n))的排序方法中平均性能最好的。但若初始序列按關鍵碼有序或基本有序時,快排序反而蛻化為冒泡排序。為改進之,通常以“三者取中法”來選取基準記錄,即將排序區間的兩個端點與中點三個記錄關鍵碼居中的調整為支點記錄。快速排序是一個不穩定的排序方法。

七、歸并排序

1 原理

歸并(Merge)排序法是將兩個(或兩個以上)有序表合并成一個新的有序表,即把待排序序列分為若干個子序列,每個子序列是有序的。然后再把有序子序列合并為整體有序序列。

速度僅次于快排,內存少的時候使用,可以進行并行計算的時候使用。

2 實現步驟

(1)選擇相鄰兩個數組成一個有序序列。 (2)選擇相鄰的兩個有序序列組成一個有序序列。 (3)重復第二步,直到全部組成一個有序序列。 這里寫圖片描述

3 實現邏輯

設r[i…n]由兩個有序子表r[i…m]和r[m+1…n]組成,兩個子表長度分別為n-i +1、n-m。 (1)j=m+1;k=i;i=i; //置兩個子表的起始下標及輔助數組的起始下標 (2)若i>m 或j>n,轉⑷ //其中一個子表已合并完,比較選取結束 (3)//選取r[i]和r[j]較小的存入輔助數組rf 如果r[i]<r[j],rf[k]=r[i]; i++; k++; 轉⑵ 否則,rf[k]=r[j]; j++; k++; 轉⑵ (4)//將尚未處理完的子表中元素存入rf 如果i<=m,將r[i…m]存入rf[k…n] //前一子表非空 如果j<=n , 將r[j…n] 存入rf[k…n] //后一子表非空 合并結束。

4 代碼實現

public static void mergeSort(int[] numbers, int left, int right) { int t = 1;// 每組元素個數 int size = right - left + 1; while (t < size) { int s = t;// 本次循環每組元素個數 t = 2 * s; int i = left; while (i + (t - 1) < size) { merge(numbers, i, i + (s - 1), i + (t - 1)); i += t; } if (i + (s - 1) < right) merge(numbers, i, i + (s - 1), right); } } private static void merge(int[] data, int p, int q, int r) { int[] B = new int[data.length]; int s = p; int t = q + 1; int k = p; while (s <= q && t <= r) { if (data[s] <= data[t]) { B[k] = data[s]; s++; } else { B[k] = data[t]; t++; } k++; } if (s == q + 1) B[k++] = data[t++]; else B[k++] = data[s++]; for (int i = p; i <= r; i++) data[i] = B[i]; }/** * 歸并排序 * 簡介:將兩個(或兩個以上)有序表合并成一個新的有序表 即把待排序序列分為若干個子序列,每個子序列是有序的。然后再把有序子序列合并為整體有序序列 * 時間復雜度為O(nlogn) * 穩定排序方式 * @param nums 待排序數組 * @return 輸出有序數組 */public static int[] sort(int[] nums, int low, int high) { int mid = (low + high) / 2; if (low < high) { // 左邊 sort(nums, low, mid); // 右邊 sort(nums, mid + 1, high); // 左右歸并 merge(nums, low, mid, high); } return nums;}/** * 將數組中low到high位置的數進行排序 * @param nums 待排序數組 * @param low 待排的開始位置 * @param mid 待排中間位置 * @param high 待排結束位置 */public static void merge(int[] nums, int low, int mid, int high) { int[] temp = new int[high - low + 1]; int i = low;// 左指針 int j = mid + 1;// 右指針 int k = 0; // 把較小的數先移到新數組中 while (i <= mid && j <= high) { if (nums[i] < nums[j]) { temp[k++] = nums[i++]; } else { temp[k++] = nums[j++]; } } // 把左邊剩余的數移入數組 while (i <= mid) { temp[k++] = nums[i++]; } // 把右邊邊剩余的數移入數組 while (j <= high) { temp[k++] = nums[j++]; } // 把新數組中的數覆蓋nums數組 for (int k2 = 0; k2 < temp.length; k2++) { nums[k2 + low] = temp[k2]; }}

八、基數排序

1 原理

基數排序已經不再是一種常規的排序方式,它更多地像一種排序方法的應用,基數排序必須依賴于另外的排序方法。基數排序的總體思路就是將待排序數據拆分成多個關鍵字進行排序,也就是說,基數排序的實質是多關鍵字排序。

多關鍵字排序的思路是將待排數據里德排序關鍵字拆分成多個排序關鍵字;第1個排序關鍵字,第2個排序關鍵字,第3個排序關鍵字……然后,根據子關鍵字對待排序數據進行排序。

用于大量數,很長的數進行排序時。

2 實現步驟

(1)將所有的數的個位數取出,按照個位數進行排序,構成一個序列。 (2)將新構成的所有的數的十位數取出,按照十位數進行排序,構成一個序列。 這里寫圖片描述

3 實現邏輯

最高位優先(Most Significant Digit first)法,簡稱MSD法: (1)先按k1排序分組,同一組中記錄,關鍵碼k1相等。 (2)再對各組按k2排序分成子組。 (3)之后,對后面的關鍵碼繼續這樣的排序分組,直到按最次位關鍵碼kd對各子組排序后。再將各組連接起來,便得到一個有序序列。 最低位優先(Least Significant Digit first)法,簡稱LSD法: (1)先從kd開始排序。 (2)再對kd-1進行排序。 (3)依次重復,直到對k1排序后便得到一個有序序列。

4 代碼實現

public void sort(int[] array) { //首先確定排序的趟數; int max = array[0]; for (int i = 1; i < array.length; i++) { if (array[i] > max) { max = array[i]; } } int time = 0; //判斷位數; while (max > 0) { max /= 10; time++; } //建立10個隊列; List<ArrayList> queue = new ArrayList<ArrayList>(); for (int i = 0; i < 10; i++) { ArrayList<Integer> queue1 = new ArrayList<Integer>(); queue.add(queue1); } //進行time次分配和收集; for (int i = 0; i < time; i++) { //分配數組元素; for (int j = 0; j < array.length; j++) { //得到數字的第time+1位數; int x = array[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i); ArrayList<Integer> queue2 = queue.get(x); queue2.add(array[j]); queue.set(x, queue2); } int count = 0;//元素計數器; //收集隊列元素; for (int k = 0; k < 10; k++) { while (queue.get(k).size() > 0) { ArrayList<Integer> queue3 = queue.get(k); array[count] = queue3.get(0); queue3.remove(0); count++; } } }}

參考文章: 一遍記住java常用的八種排序算法與代碼實現 八大排序算法Java java中常用的幾種排序算法 必須知道的八大種排序算法【java實現】(一) 冒泡排序、快速排序 必須知道的八大種排序算法【java實現】(二) 選擇排序,插入排序,希爾算法【詳解】 必須知道的八大種排序算法【java實現】(三) 歸并排序算法、堆排序算法詳解


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 天峨县| 日照市| 新郑市| 合水县| 泾川县| 武宣县| 新干县| 修文县| 阿城市| 明溪县| 塔城市| 饶平县| 杨浦区| 永春县| 当阳市| 荣昌县| 大城县| 香格里拉县| 石河子市| 迭部县| 银川市| 和田县| 宁强县| 运城市| 永靖县| 敖汉旗| 陇南市| 安泽县| 大埔区| 页游| 神池县| 喜德县| 盐山县| 策勒县| 精河县| 东乌珠穆沁旗| 浦北县| 扶余县| 东宁县| 苍溪县| 永登县|