1. 程式人生 > >非比較排序:計數排序、桶排序、基數排序

非比較排序:計數排序、桶排序、基數排序

一:什麼是非比較排序 眾所周知,排序有很多種辦法,其中無非就是比較陣列中的值,另一種就是一種分配的思想,類似於一個蘿蔔一個坑,這也就是非比較排序。二:有哪些非比較排序呢? 可以分為三大類 計數排序 、 基數排序 、 桶排序 。這是比較常見的三種排序方式,當然核心思想都是 一個蘿蔔一個坑。三:具體實現 1:計數排序 顧名思義,計數排序的核心思想就是統計待排序陣列中,每個數出現的次數,使用另一個數組來記錄致謝資料,等遍歷一遍待排序陣列之後,所有的資料的出現次數都記錄了下來,再根據記錄的陣列進行還原。 這裡記錄陣列的大小為待排序陣列的最大值減去最小值,當某個元素出現一次,則在固定的下標出執行+1。 時間複雜度分析:遍歷待排序陣列 o(n) 第二遍遍歷記錄陣列 o(range) 還原陣列o(n) 故時間複雜度是o(n+range+n) Java程式碼實現如下
  //計數排序
public static void CountingSorting(int[] array)
{
    int max=array[0];
    int min=array[0];
    //找到陣列中的範圍
    for (int i = 0; i < array.length; i++) {
        if (array[i]>max)
        {
            max=array[i];
        }
        if (array[i]<min)
        {
            min=array[i];
        }
    }
    //構建統計用的陣列
    int[] tempory=new int[max-min+1];
    System.out.println(tempory.length+"--"+max+"---"+min);
    for (int i = 0; i < array.length; i++) {
        tempory[array[i]-min]++;
    }
    //寫回到原陣列
    int j=0;
    for (int i = 0; i < tempory.length; i++) {
        while (tempory[i]>0)
        {
            array[j++]=i+min;
            tempory[i]--;
        }
    }
    System.out.println(Arrays.toString(array));
}


2:基數排序是 簡單來說就是根據待排序序列的位來決定的,分別設定10個桶,然後分別對待排序的數進行取個位 十位,白位等等,放到對應的桶之中,每經歷一遍,依次從桶之中拿出資料,再對新的待排序列進行操作,這時候就是取百分位了,每次都會上升一個數量級。 Java程式碼
//基數排序
public static void CardinalitySort(int[] array)
{
    //陣列實現
    //先找到陣列中的元素的最大值,確定最大的位數
    int max=array[0];
    for (int i = 0; i < array.length;i++) {
        if (array[i]>max)
        {
            max=array[i];
        }
    }
    //計算位數
    int time=0;
    while (max>0)
    {
        max/=10;
        time++;
    }
    //建立10個佇列
    ArrayList<Integer>[] list=new ArrayList[10];
    for (int i = 0; i < 10; i++) {
            list[i]=new ArrayList<Integer>();
    }
    //開始迴圈
    for (int j = 0; j < time; j++)
    {
        for (int i = 0; i <array.length ; i++)
        {
            list[  array[i] %   (int)Math.pow(10, j+1)  /  (int)Math.pow(10, j) ]  .add(array[i]);
          if (j!=0)
          {
              Integer s=new Integer(array[i]);
              list[array[i] % (int) Math.pow(10, j) / (int) Math.pow(10, j - 1)].remove(s);
          }
        }
        int temp2=0;
            for (int i = 0; i < 10; i++)
            {
                for (int k = 0; k < list[i].size(); k++)
                {
                    array[temp2++]=list[i].get(k);
                }
            }
    }

    System.out.println(Arrays.toString(array));
}


2:桶排序桶排序比較類似於上兩個排序方式,不過桶類似於分治法,講一個大的待排序陣列分為多個桶內,再對多個桶中的序列進行排序。 實現程式碼:
//桶排序
//這裡桶之中的資料,我們呼叫快速排序進行排序
public static void BucketSort(int[] array)
{
    //先找到範圍
    int max=0,min=0;
    for (int i = 0; i <array.length; i++) {
        if (array[i]>max)
        {
            max=array[i];
        }
        if (array[i]<min)
        {
            min=array[i];
        }
    }
    int range=max-min;
    //分為幾個桶這裡取range/10 最小桶從min開始  到最大桶的max
    int bucketNum=range/10;
    int [][] bucket=new int[10][array.length];
    //記錄桶之中的資料量
    int[] BucteDatetnum=new int[10];
    //這裡放入桶之中
    for (int i = 0; i <array.length ; i++) {
        int index=(array[i]-min)/10;
        System.out.println("index"+"=="+index);
        bucket[index] [BucteDatetnum[index]] =array[i];
        BucteDatetnum[index]++;
    }
    //分別對每個桶進行快速排序
    for (int i = 0; i <10 ; i++) {
        QuickSort(bucket[i],0,BucteDatetnum[i]);
        System.out.println(Arrays.toString(bucket[i]));
    }
}