簡單演算法之9種排序
阿新 • • 發佈:2018-11-19
甭管什麼,筆者就喜歡湊個9。這次,關於排序的演算法還是9種,小結一下。排序的演算法,儘管有很多的方法例子,但這次是自己總結的,挺有意思演算法希望大家喜歡。直接上程式碼樓,以下演算法,都經過筆者親測,並修改使之有效(貼上可用)。
package com.css.java.learning.massbag; import java.util.Arrays; /**演算法: * 排序相關小結 * @author Red_ant * 20181119 */ public class OrderMethod { /*1、氣泡排序 * 通過相鄰兩個元素比較的方式,依次選出合適的元素放到 * 陣列的第i位。 */ public static int[] bubbleSort(int[] nums){ int num = 0; for (int i = 0; i < nums.length -1; i++) { for (int j = 0; j < nums.length - 1 - i; j++) {//兩兩比較,符合條件的元素居於前面 if(nums[j] > nums[j + 1]){ num = nums[j]; nums[j] = nums[j + 1]; nums[j + 1] = num; } } } return nums; } /*2、選擇排序 * 每一趟從待排序列,選擇最小的元素放到已排序好的序列末尾,剩下的為待排序序列, * 重複上述步驟,直至完成。 */ public static int[] selectSort(int[] nums){ int num = 0; for (int i = 0; i < nums.length -1; i++) { int index = i; for (int j = i + 1; j < nums.length; j++) {//選擇合適的元素,直接放到陣列的第i位 if(nums[index] > nums[j]){ index = j; } if(index != i){ num = nums[i]; nums[i] = nums[index]; nums[index] = num; } } } return nums; } /*3、選擇排序:堆排序 * 堆排序是一種樹形結構選擇排序 * 堆排序需要兩個過程,建立堆,堆頂與堆最後一個元素交換位置。所以堆排序有兩個函式組成: * 建堆的***函式,反覆呼叫***函式實現排序的函式 * 基本思路: * 將序列建成一個堆,根據升序降序選擇大頂堆或小頂堆 * 將堆頂元素與末尾元素交換,將最大元素沉到陣列末端 * 重新調整結構,使其滿足堆定義,然後繼續交換堆頂元素與當前末尾元素,反覆執行調整+交換步驟,直到整個序列有序。 */ public static int[] HeapSorts(int[] nums){ //建立大頂 for (int i = nums.length/2 - 1; i >= 0; i--) { //從第一個非葉子節點從下至上,從右至左調整結構 suitHeap(nums, i, nums.length); } //調整堆結構,交換堆頂元素與 末尾元素 for (int j = nums.length - 1; j > 0; j--) { exchangeNum(nums, 0, j);//交換堆頂元素與末尾元素 suitHeap(nums, 0, j); } return nums; } private static void exchangeNum(int[] nums, int i, int i2) { int index = nums[i]; nums[i] = nums[i2]; nums[i2] = index; } private static void suitHeap(int[] nums, int i, int length) { int index = nums[i];//取出當前元素 for (int j = i*2 + 1; j < length; j = j*2+1) { //從i節點的左節點開始,即2i+1處 if(j+1 < length && nums[j] < nums[j+1]){ //如果,左子節點小於右子節點,j指向右子節點 j++; } if(nums[j] > index){ //如果子節點大於父節點,將子節點賦值給父節點 nums[i] = nums[j]; i = j; }else{ break; } } nums[i] = index;//將index值放到最終位置 } /*4、java Arrays排序 * 該方法是Arrays類的靜態方法,在需要對陣列進行排序時,非常好用 */ public static int[] ArraySort(int[] nums){ Arrays.sort(nums); return nums; } /*5、插入排序:直接插入排序 * 將陣列分為兩部分,將後部分元素逐一與前部分元素比較 * 然後依據比較結果進行移動元素 */ public static int[] insertSort(int[] nums){ //從頭部第一個當做已經排序好的,把後面的一個一個的插入到已經排序好的列表中 for (int i = 1; i < nums.length; i++) { int j; int index = nums[i];//index為待插入的元素 for (j = i; j > 0 && index < nums[j - 1]; j--) { nums[j] = nums[j -1]; } nums[j] = index; } return nums; } /*6、插入排序:希爾排序 * 建堆,對頂與堆的最後一個元素進行排序 * 希爾排序是插入排序的一種,先取一個小於n的整數作為第一個增量,把檔案的全部記錄分組。 * 所有距離為d1的倍數的記錄放在同一個組中,先在各組內進行直接插入排序。實際上是一種分組插入排序的方法。 */ public static int[] shellSrot(int[] nums){ int index = nums.length/2; while (index >= 1) { for (int i = index; i < nums.length; i++) { if(nums[i] < nums[i - index]){ int j; int x = nums[i];//當前待插入的元素 nums[i] = nums[i - index]; for (j = i - index; j >= 0 && x < nums[j]; j = j-index) { nums[j + index] = nums[j]; } nums[j + index] = x;//插入元素 } } index = index/2; } return nums; } /*7、交換排序:快速排序 * 基本思想: * A選擇一個基準元素,通常選擇第一個元素或最後一個元素 * B通過一趟排序將待排序的記錄分割成獨立的兩部分:記錄均值比基準元素值小,元素值比基準元素值大 * C此時基準元素在排序好的正確位置 * D分別對這兩部分記錄,用同樣的方法繼續進行排序,直到整個序列有序。 */ public static int[] quickSort(int[] nums, int...is){ int low,hight; if(is.length == 0){ low = 0; hight = nums.length - 1; }else{ low = is[0]; hight = is[1]; } if(low < hight){//判斷,讓遞迴函式退出,否則無限迴圈 int middle = getMiddle(nums, low, hight); quickSort(nums, 0, middle - 1);//基準元素小 quickSort(nums, middle + 1, hight);//比基準元素大 } return nums; } //獲取,均值 private static int getMiddle(int[] nums, int low, int hight) { int index = nums[low];//選擇基準元素 while (low < hight) { //從hight開始,找出比基準小的,與low換位置 while (low < hight && nums[hight] >= index) { hight--; } nums[low] = nums[hight]; //從low開始找比基準大,放到之前hight空出來的位置上 while (low < hight && nums[low] <= index) { low++; } nums[hight] = nums[low]; } //此時low = hight是基準元素的位置,也是空缺的位置 nums[low] = index; return low; } /* * 8、歸併排序 * 基本思想: * 歸併排序是,將兩個或兩個以上有序表合併成一個新的有序表。 * 即把待排序的序列分為若干個子序列,每個子序列是有序的,然後再把有序序列合併成整體有序序列 */ public static int[] mergeSort(int[] nums){ sortmerge(nums, 0, nums.length - 1); return nums; } private static void sortmerge(int[] nums, int i, int j) { if(i >= j){ return; } //找出中間索引 int middle = (i + j)/2; //對左邊陣列進行遞迴 sortmerge(nums, i, middle); //對右邊陣列進行遞迴 sortmerge(nums, middle + 1, j); //合併陣列 merge(nums, i, middle, j); } private static void merge(int[] nums, int i, int middle, int j) { //建立臨時中間量陣列 int[] tmpArr = new int[nums.length]; //右陣列第一個元素索引 int mid = middle + 1; //記錄臨時陣列索引 int second = i; //快取左側陣列第一個元素的索引 int tmp = i; while (i <= middle && mid <= j) { //從兩個陣列中取出最小的放到臨時陣列中 if(nums[i] <= nums[mid]){ tmpArr[second++] = nums[i++]; }else{ tmpArr[second++] = nums[mid++]; } } //剩餘部分依次放入臨時陣列 while (mid <= j) { tmpArr[second++] = nums[mid++]; } while (i <= middle) { tmpArr[second++] = nums[i++]; } //將臨時陣列中內容,拷貝到原陣列中 while (tmp <= j) { nums[tmp] = tmpArr[tmp++]; } } /*9、基數排序(桶) * 將陣列中的所有元素按照元素中最長的位數進行統一格式,不足位數的前面補充0 * 然後,一次比較每一位的數字,得到最終的比較結果 * 基本思想: * A遍歷找出最大的數(確定最大的數是幾) * B開闢臨時陣列,用於中間過程的計算 * C用一個count陣列統計原陣列中某一位(從低位向高位統計)相同的資料出現的次數; * D用一個start陣列計算原陣列中某一位(從最低位向最高位計算)相同資料出現的位置; * E將桶中資料從小到大用臨時陣列收集起來; * F重複(3)(4)(5)直到所有位都被統計並計算過,用臨時陣列收集起來; * G將臨時陣列拷回到原陣列中; */ public static int[] radixSort(int[] nums) { int exp; // 指數。當對陣列按各位進行排序時,exp=1;按十位進行排序時,exp=10;... int max = getMax(nums); // 陣列a中的最大值 // 從個位開始,對陣列a按"指數"進行排序 for (exp = 1; max/exp > 0; exp *= 10) { countSort(nums, exp); } return nums; } //獲取陣列中最大的元素 private static int getMax(int[] nums) { int i, max; max = nums[0]; for (i = 1; i < nums.length; i++) if (nums[i] > max) max = nums[i]; return max; } /* * 對陣列按照"某個位數"進行排序(桶排序) * 引數說明: * exp -- 指數。對陣列a按照該指數進行排序。 * (01) 當exp=1表示按照"個位"對陣列a進行排序 * (02) 當exp=10表示按照"十位"對陣列a進行排序 * (03) 當exp=100表示按照"百位"對陣列a進行排序 */ private static void countSort(int[] a, int exp) { int[] output = new int[a.length]; // 儲存"被排序資料"的臨時陣列 int[] buckets = new int[10]; // 將資料出現的次數儲存在buckets[]中 for (int i = 0; i < a.length; i++) buckets[(a[i] / exp) % 10]++; // 更改buckets[i]。目的是讓更改後的buckets[i]的值,是該資料在output[]中的位置。 for (int i = 1; i < 10; i++) buckets[i] += buckets[i - 1]; // 將資料儲存到臨時陣列output[]中 for (int i = a.length - 1; i >= 0; i--) { output[buckets[(a[i] / exp) % 10] - 1] = a[i]; buckets[(a[i] / exp) % 10]--; } // 將排序好的資料賦值給a[] for (int i = 0; i < a.length; i++) { a[i] = output[i]; } // 用完清空 output = null; buckets = null; } public static void main(String[] args) { int[] nums = {1221,232,1242,24,12,4,1,43,14,4,21,4,14,4,1,41,2}; //nums = bubbleSort(nums);冒泡 //nums = selectSort(nums);選擇 //nums = ArraySort(nums);陣列 //nums = insertSort(nums);插入 //nums = shellSrot(nums);希爾 //nums = HeapSorts(nums);選擇排序:堆排序 //nums = quickSort(nums);快速 //nums = mergeSort(nums);歸併 nums = radixSort(nums); for (int k = 0; k < nums.length; k++) { System.err.println("排序之後的"+nums[k]); } } }