1. 程式人生 > >Java常用的九種排序方法及程式碼實現

Java常用的九種排序方法及程式碼實現

 

  1. package com.algorithm.Demo;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.List;
  5. public class SortRecoder {
  6.     public static void main(String[] args) {
  7.         SortRecoder SR = new SortRecoder();
  8.         int[] a={49,38,65,97,76,13,27,49,78,34,12,64,5,4,18,23,34,15,35,25,53};
  9.         System.out.println(" --1.直接插入排序--");
  10.         SR.insertSort(a);
  11.         System.out.println(" --2.希爾排序--");
  12.         SR.sheelSort(a);
  13.         System.out.println(" --3.簡單選擇排序--");
  14.         SR.selectSort(a);
  15.         System.out.println(" --4.堆排序--");
  16.         SR.heapSort(a);
  17.         System.out.println(" --5.氣泡排序--");
  18.         SR.bubbleSort(a);
  19.         System.out.println(" --6.快速排序--");
  20.         SR.FastSort(a,0,a.length-1);
  21.         SR.printAll(a);
  22.         System.out.println(" --7.歸併排序--");
  23.         SR.mergingSort(a,0,a.length-1);
  24.         SR.printAll(a);
  25.         System.out.println(" --8.基數排序--");
  26.         SR.radixSort(a);
  27.         System.out.println(" --9.類方法排序--");
  28.         SR.ArraySort(a);
  29.     }
  30.     // 列印完整序列
  31.     public void printAll(int[] list) {
  32.         for (int value : list) {
  33.             System.out.print(value+"  ");
  34.         }
  35.         System.out.println();
  36.     }
  37.     //1.直接插入排序
  38.     //將大於要插入值的數整體後移一個單位 ,將需要插入的小數值向前移一位。
  39.     public void insertSort(int[] a){
  40.         for(int i=1;i<a.length;i++){
  41.             int insertNum=a[i];//要插入的數 38,65,97,76,13,27...
  42.             int j=i-1;
  43.             //依次比較更換位置
  44.             for(;j>=0&&insertNum<a[j];j--){ //將大於要插入值的數整體後移一個單位  ,j減少1。
  45.                 a[j+1]=a[j];
  46.             }
  47.             a[j+1]=insertNum;//將需要插入的數放在要插入的位置。
  48.         }
  49.         this.printAll(a);
  50.     }
  51.     //2.希爾排序(最小增量排序)  --對於直接插入排序問題,資料量巨大時。
  52.     //  演算法先將要排序的一組數按某個增量d(n/2,n為要排序數的個數)分成若干組,
  53.     //  每組中記錄的下標相差d.對每組中全部元素進行直接插入排序,然後再用一個較小的增量(d/2)對它進行分組,
  54.     //  在每組中再進行直接插入排序。當增量減到1時,進行直接插入排序後,排序完成。
  55.     public  void sheelSort(int[] a){
  56.         int d  = a.length;
  57.         while (d!=0) {
  58.             d=d/2;
  59.             for (int x = 0; x < d; x++) {//分的組數
  60.                 for (int i = x + d; i < a.length; i += d) {//組中的元素,從第二個數開始
  61.                     int j = i - d;//j為有序序列最後一位的位數
  62.                     int temp = a[i];//要插入的元素 
  63.                     for (; j >= 0 && temp < a[j]; j -= d) {
  64.                         a[j + d] = a[j];//向後移動d位
  65.                     }
  66.                     a[j + d] = temp;
  67.                 }
  68.             }
  69.         }
  70.         this.printAll(a);
  71.     }
  72.     //3.簡單選擇排序    --常用於取序列中最大最小的幾個數時。
  73.     //遍歷整個序列,將最小的數放在最前面。遍歷剩下的序列,將最小的數放在最前面。
  74.     public void selectSort(int[] a) {
  75.         int length = a.length;
  76.         for (int i = 0; i < length; i++) {//迴圈次數
  77.             int key = a[i];
  78.             int position=i;
  79.             for (int j = i + 1; j < length; j++) {//選出最小的值和位置
  80.                 if (a[j] < key) {
  81.                     key = a[j];
  82.                     position = j;
  83.                 }
  84.             }
  85.             a[position]=a[i];//交換位置
  86.             a[i]=key;
  87.         }
  88.         this.printAll(a);
  89.     }
  90.     //4.堆排序  --是一種樹形選擇排序,是對直接選擇排序的有效改進。
  91.     //將根節點與最後一個節點交換,然後斷開最後一個節點。重複第一、二步,直到所有節點斷開。根節點是最小值
  92.     public void heapSort(int[] a){
  93.         int arrayLength=a.length;
  94.         //迴圈建堆  
  95.         for(int i=0;i<arrayLength-1;i++){
  96.             //建堆  
  97.             buildMaxHeap(a,arrayLength-1-i);
  98.             //交換堆頂和最後一個元素  
  99.             swap(a,0,arrayLength-1-i);
  100.            //System.out.println(Arrays.toString(a));
  101.         }
  102.         this.printAll(a);
  103.     }
  104.     private void swap(int[] data, int i, int j) {
  105.         int tmp=data[i];
  106.         data[i]=data[j];
  107.         data[j]=tmp;
  108.     }
  109.     //對data陣列從0到lastIndex建大頂堆  
  110.     private void buildMaxHeap(int[] data, int lastIndex) {
  111.         //從lastIndex處節點(最後一個節點)的父節點開始  
  112.         for(int i=(lastIndex-1)/2;i>=0;i--){
  113.             //k儲存正在判斷的節點  
  114.             int k=i;
  115.             //如果當前k節點的子節點存在  
  116.             while(k*2+1<=lastIndex){
  117.                 //k節點的左子節點的索引  
  118.                 int biggerIndex=2*k+1;
  119.                 //如果biggerIndex小於lastIndex,即biggerIndex+1代表的k節點的右子節點存在  
  120.                 if(biggerIndex<lastIndex){
  121.                     //若果右子節點的值較大  
  122.                     if(data[biggerIndex]<data[biggerIndex+1]){
  123.                         //biggerIndex總是記錄較大子節點的索引  
  124.                         biggerIndex++;
  125.                     }
  126.                 }
  127.                 //如果k節點的值小於其較大的子節點的值  
  128.                 if(data[k]<data[biggerIndex]){
  129.                     //交換他們  
  130.                     swap(data,k,biggerIndex);
  131.                     //將biggerIndex賦予k,開始while迴圈的下一次迴圈,重新保證k節點的值大於其左右子節點的值  
  132.                     k=biggerIndex;
  133.                 }else{
  134.                     break;
  135.                 }
  136.             }
  137.         }
  138.     }
  139.     //5.氣泡排序
  140.     //自上而下對相鄰的兩個數依次進行比較和調整,讓較大的數往下沉,較小的往上冒
  141.     public void bubbleSort(int[] a){
  142.         int temp;
  143.         for(int i=0;i<a.length;i++){
  144.             for(int j=0;j<a.length-i-1;j++){
  145.                 if(a[j]>a[j+1]){
  146.                     temp=a[j];
  147.                     a[j]=a[j+1];
  148.                     a[j+1]=temp;
  149.                 }
  150.             }
  151.         }
  152.         this.printAll(a);
  153.     }
  154.     //6.快速排序   --要求時間最快時。
  155.     //選擇第一個數為p,小於p的數放在左邊,大於p的數放在右邊。遞迴的將p左邊和右邊的數都按照第一步進行,直到不能遞迴
  156.     public void FastSort(int[] a,int low,int high){
  157.         int start = low;
  158.         int end = high;
  159.         int key = a[low];
  160.         while(end>start){
  161.             //從後往前比較
  162.             while(end>start&&a[end]>=key)  //如果沒有比關鍵值小的,比較下一個,直到有比關鍵值小的交換位置,然後又從前往後比較
  163.                 end--;
  164.             if(a[end]<=key){
  165.                 int temp = a[end];
  166.                 a[end] = a[start];
  167.                 a[start] = temp;
  168.             }
  169.             //從前往後比較
  170.             while(end>start&&a[start]<=key)//如果沒有比關鍵值大的,比較下一個,直到有比關鍵值大的交換位置
  171.                start++;
  172.             if(a[start]>=key){
  173.                 int temp = a[start];
  174.                 a[start] = a[end];
  175.                 a[end] = temp;
  176.             }
  177.         //此時第一次迴圈比較結束,關鍵值的位置已經確定了。左邊的值都比關鍵值小,右邊的值都比關鍵值大,但是兩邊的順序還有可能是不一樣的,進行下面的遞迴呼叫
  178.         }
  179.         //遞迴
  180.         if(start>low) FastSort(a,low,start-1);//左邊序列。第一個索引位置到關鍵值索引-1
  181.         if(end<high) FastSort(a,end+1,high);//右邊序列。從關鍵值索引+1到最後一個
  182.     }
  183.     //7.歸併排序  --速度僅次於快排
  184.     //選擇相鄰兩個陣列成一個有序序列。 然後再把相鄰有序子序列合併為整體有序序列。重複執行,直到全部組成一個有序序列
  185.     public void mergingSort(int[] data, int left, int right) {
  186.         if(left<right){
  187.             //找出中間索引  
  188.             int center=(left+right)/2;
  189.             //對左邊陣列進行遞迴  
  190.             mergingSort(data,left,center);
  191.             //對右邊陣列進行遞迴  
  192.             mergingSort(data,center+1,right);
  193.             //合併  
  194.             merge(data,left,center,right);
  195.         }
  196.     }
  197.     public void merge(int[] data, int left, int center, int right) {
  198.         int [] tmpArr=new int[data.length];
  199.         int mid=center+1;
  200.         //third記錄中間陣列的索引  
  201.         int third=left;
  202.         int tmp=left;
  203.         while(left<=center&&mid<=right){
  204.             //從兩個陣列中取出最小的放入中間陣列  
  205.             if(data[left]<=data[mid]){
  206.                 tmpArr[third++]=data[left++];
  207.             }else{
  208.                 tmpArr[third++]=data[mid++];
  209.             }
  210.         }
  211.         //剩餘部分依次放入中間陣列  
  212.         while(mid<=right){
  213.             tmpArr[third++]=data[mid++];
  214.         }
  215.         while(left<=center){
  216.             tmpArr[third++]=data[left++];
  217.         }
  218.         //將中間陣列中的內容複製回原陣列  
  219.         while(tmp<=right){
  220.             data[tmp]=tmpArr[tmp++];
  221.         }
  222.         //System.out.println(Arrays.toString(data));  
  223.     }
  224.     //8.基數排序   --用於大量數,很長的數進行排序時。
  225.     //將所有待比較數值統一為同樣的數位長度,數位較短的數前面補零。然後,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以後,數列就變成一個有序序列。
  226.     public void radixSort (int[] array) {
  227.         //首先確定排序的趟數;     
  228.         int max = array[0];
  229.         for (int i = 1; i < array.length; i++) {
  230.             if (array[i] > max) {
  231.                 max = array[i];
  232.             }
  233.         }
  234.         int time = 0;
  235.         //判斷位數;     
  236.         while (max > 0) {
  237.             max /= 10;
  238.             time++;
  239.         }
  240.         //建立10個佇列;     
  241.         List<ArrayList> queue = new ArrayList<ArrayList>();
  242.         for (int i = 0; i < 10; i++) {
  243.             ArrayList<Integer> queue1 = new ArrayList<Integer>();
  244.             queue.add(queue1);
  245.         }
  246.         //進行time次分配和收集;     
  247.         for (int i = 0; i < time; i++) {
  248.             //分配陣列元素;     
  249.             for (int j = 0; j < array.length; j++) {
  250.                 //得到數字的第time+1位數;   
  251.                 int x = array[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
  252.                 ArrayList<Integer> queue2 = queue.get(x);
  253.                 queue2.add(array[j]);
  254.                 queue.set(x, queue2);
  255.             }
  256.             int count = 0;//元素計數器;     
  257.             //收集佇列元素;     
  258.             for (int k = 0; k < 10; k++) {
  259.                 while (queue.get(k).size() > 0) {
  260.                     ArrayList<Integer> queue3 = queue.get(k);
  261.                     array[count] = queue3.get(0);
  262.                     queue3.remove(0);
  263.                     count++;
  264.                 }
  265.             }
  266.         }
  267.         this.printAll(array);
  268.     }
  269.     //9.類方法降序排列
  270.     public void ArraySort(int[] a){
  271.         Arrays.sort(a);
  272.         //this.printAll(a);
  273.         for(int i=0,j=a.length-1;i<j;i++,j--){
  274.             int temp=a[i];
  275.             a[i]=a[j];
  276.             a[j]=temp;
  277.         }
  278.         this.printAll(a);
  279.     }
  280. }