排序算法 java版本

冒泡排序

package com.test;

/**
 * 冒泡排序
 *
 * 時間複雜度爲:o(n`2)  空間複雜度爲o(1)
 *
 * 最好最壞複雜度都是o(n`2)
 *
 * 說明:
 * 對當前還未排序的所有數,自上而下對相鄰的兩個數依次進行比較和調整,
 * 讓較大的數日後面移動 , 讓較小的數往前面移動
 *
 * 算法比較穩定 爲兩兩比較 不存在跳躍
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaBubble {

    public static void main(String[] args){
        int[] a = {1,2,6,5,4,3,23,43,123,432};
        sort(a);
    }


    public static void sort(int[] arr){

        int tmp = 0;
        for ( int i = 0 ; i < arr.length - 1 ; i++ ){
            for (int j = 0 ; j < arr.length - 1 - i ; j++){
                if (arr[j] > arr[j+1]){
                    tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }

        for (int a : arr){
            System.out.print(a + " ");
        }

    }
}


基數排序

package com.test;

import java.util.ArrayList;
import java.util.List;

/**
 * 基數排序
 *
 * 時間複雜度爲o(n+k)
 * 最好最壞都同樣
 *
 * 說明:
 * 將全部待比較數值(正整數)統一爲一樣的數位長度,數位較短的數前面補零。
 * 而後,從最低位開始,依次進行一次排序。
 * 這樣從最低位排序一直到最高位排序完成之後,數列就變成一個有序序列
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaCount {

    public static void main(String[] args){

        int[] array ={1,3,6,2,5,87,54,32,21,22,33,44,11};
        sort(array);
        for (int a : array){
            System.out.print(a + " ");
        }
    }

    public static 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++;
                }
            }
        }
    }
}

快速排序

package com.test;

/**
 * 快速排序
 *
 * 時間複雜度爲o(nlogn) 空間複雜度爲o(logn)
 *
 * 最壞O(n^2) 當劃分不均勻時候 逆序and排好序都是最壞狀況
     最好O(n) 當劃分均勻
     partition的時間複雜度: O(n)一共須要logn次partition
 *
 *說明:
 * 選擇一個基準元素,一般選擇第一個元素或者最後一個元素,經過一趟掃描,將待排序列分紅兩部分,
 * 一部分比基準元素小,一部分大於等於基準元素,此時基準元素在其排好序後的正確位置,而後再用一樣的方法遞歸地排序劃分的兩部分。
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaFast {

    public static void main(String[] args){
        int[] aa = {1,4,6,2,5,8,21,43,22,44,33};

        quick(aa);

        for (int a : aa){
            System.out.print(a + " ");
        }
    }

    public static void quick(int[] arr){
        if (arr.length > 0){
            quickSort(arr , 0 ,arr.length - 1);
        }
    }

    public static void quickSort(int[] arr , int low , int high){
        if (low < high){
            int middle = getMiddle(arr , low ,high);    //將list一份爲二
            quickSort(arr , low , middle - 1);          //對低字表進行遞歸排序
            quickSort(arr , middle + 1 , high);         //對高字表進行遞歸排序
        }
    }

    public static int getMiddle(int[] arr , int low , int high){
        int tmp = arr[low];             //數組的第一個做爲中軸
        while (low < high){
            while (low < high && arr[high] >= tmp){
                high--;
            }
            arr[low] = arr[high];       //比中軸小的記錄移到低端
            while (low < high && arr[low] <= tmp){
                low++;
            }
            arr[high] = arr[low];       //比中軸大的記錄移到高端
        }
        arr[low] = tmp;                 //中軸記錄到尾
        return low;                     //返回中軸記錄
    }
}

希爾排序

package com.test;

/**
 * 希爾排序
 *
 * 時間複雜度o(n`1.2)
 *
 * 說明:
 * 算法先將要排序的一組數按照某個增量d(n/2 , m爲要排序的個數)分爲若干組 , 每組中記錄的下標相差d,
 * 對每組中所有元素進行直接插入排序。而後再用一個較小的增量(d/2)對它進行分組,在每組中再進行插入排序。
 * 當增量減小到1的時候,進行直接插入排序後。排序完成。
 *
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaHill {

    public static void main(String[] args){
        int[] arr = {1,8,4,2,6,12,34,21,33,55,11,88,33};
        sort(arr);

    }

    public static void sort(int[] arr){
        double d1 = arr.length;
        int tmp = 0 ;
        while (true) {
            d1 = Math.ceil(d1/2);
            int d = (int) d1;
            for (int x = 0 ; x < d ; x++){
                for (int i = x+d ; i < arr.length ; i+=d){
                    int j = i -d;
                    tmp = arr[i];
                    while (j >=0 && tmp <arr[j]){
                        arr[j+d] = arr[j];
                        j -=d;
                    }
                    arr[j+d] = tmp;
                }
            }
            if (d == 1){
                break;
            }
        }

        for (int a : arr){
            System.out.print(a + " ");
        }

    }
}

插入排序

package com.test;

/**
 * 插入排序
 * 時間複雜度 o(n`2)  控件複雜度 o(1)
 *
 * 最好爲n  最壞複雜度爲n`2
 *
 * 說明:
 * 從頭開始排序  若是後面有比前面小的直接插入其中
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaInsert {

    public static void main(String[] args){
        int[] a = {1,2,6,5,4,3,23,43,123,432};
        sortWhile(a);
    }

    /**
     * 這一種使用的是兩層for循環進行排序
     * @param arr
     */
    public static void sort(int[] arr){

        int tmp = 0;
        for (int i = 0 ; i < arr.length ; i++) {
            for (int j = i-1 ; j >= 0 ; j--){
                if (arr[j+1] < arr[j]){
                    tmp = arr[j+1];
                    arr[j+1] = arr[j];
                    arr[j] = tmp;
                }
            }
        }

        for (int a : arr){
            System.out.print(a + " ");
        }


    }

    /**
     * 本循環與上面的差很少  只不過是使用了while循環
     * @param arr
     */
    public static void sortWhile(int[] arr){

        int tmp = 0;
        for (int i = 1 ; i < arr.length ; i++) {
            int j = i-1;
            while (arr[j+1] < arr[j]){
                tmp = arr[j+1];
                arr[j+1] = arr[j];
                arr[j] = tmp;
                j--;
            }
        }

        for (int a : arr){
            System.out.print(a + " ");
        }


    }
}

歸併排序

package com.test;

import java.util.Arrays;

/**
 * 歸併排序
 *
 * 時間複雜度爲o(nlogn) 空間複雜度爲 o(n) + o(logn)
 *
 * 說明:
 * 把兩個(或者兩個以上)的有序表合併成一個新的有序表 , 把待排序序列分爲若干個序列 , 每一個子序列都是有序的
 * 而後再把有序的子序列合併爲總體有序序列
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaMerge {

    public static void main(String[] args){
        int[] data = {1,2,3,5,21,43,65,87,22,33,44,55,99};
        sort(data , 0 , data.length-1);
    }

    public static void sort(int[] data , int left , int right){
        if (left < right){
            int center = (right + left)/2;
            System.out.println("11 : "+left + " " + center + " " + right);
            sort(data, left, center);
            System.out.println("22 : "+left + " " + center + " " + right);
            sort(data, center + 1, right);
            System.out.println("33 : "+left + " " + center + " " + right);
            merge(data , left ,center , right);
        }
    }

    public static void merge(int[] data , int left , int center , int right){
//        System.out.println(left + " " + center + " " + right);
        int[] tmpArr = new int[data.length];
        int mid = center+1;
        //記錄中間數組的索引
        int third = left;
        int tmp = left;
        while (left <= center && mid <= right){
            //從兩個數組中取出最小的放入中間數組
            if (data[left] <= data[mid]){
                tmpArr[third++] = data[left++];
            }else {
                tmpArr[third++] = data[mid++];
            }
        }
        //剩餘部分依次放入中間數組
        while (mid <= right){
            tmpArr[third++] = data[mid++];
        }
        while (left <= center){
            tmpArr[third++] = data[left++];
        }
        //將中間數組中的內容複製回原數組
        while (tmp <= right){
            data[tmp] = tmpArr[tmp++];
        }
        System.out.println(Arrays.toString(data));


    }
}

選擇排序

package com.test;

/**
 * 選擇排序  時間複雜度爲o(n`2)  空間複雜度爲o(1)
 *
 * 沒有最好最壞的狀況  排序時間都是同樣的
 *
 * 說明:
 * 從頭開始排序 從後面選擇最小的與第一個交換     而後再從後面選擇最小的與第二個進行交互
 *
 * 知道交換到倒數第二個與倒數第一個進行交換
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaSelect {

    public static void main(String[] args){

        int[] arr ={1,4,7,3,22,65,44,22,88,54,76,31,32};
        sort(arr);

    }

    public static void sort(int[] arr){
        for (int i = 0 ; i < arr.length -1 ; i++){
            int min = i;
            int tmp;
            for (int j = i+1 ; j < arr.length ; j++){
                if (arr[j] < arr[min]){
                    min = j;
                }
            }
            if (min != i){
                tmp = arr[min];
                arr[min] = arr[i];
                arr[i] = tmp;
            }
        }
        for (int a : arr){
            System.out.print(a + " ");
        }

    }
}

堆排序

package com.test;

import java.util.Arrays;

/**
 * 堆排序
 *
 * 時間複雜度o(nlogn)  空間複雜度o(1)
 *
 * 沒有最好與最壞的區別 時間複雜度都是o(nlogn) 不是很穩定的算法
 *
 * 說明:
 *具備n個元素的序列(h1,h2,...,hn),當且僅當知足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)時稱之爲堆。
 * 在這裏只討論知足前者條件的堆。由堆的定義能夠看出,堆頂元素(即第一個元素)必爲最大項(大頂堆)。徹底二叉樹能夠很直觀地表示堆的結構。
 * 堆頂爲根,其它爲左子樹、右子樹。初始時把要排序的數的序列看做是一棵順序存儲的二叉樹,調整它們的存儲序,使之成爲一個堆,
 * 這時堆的根節點的數最大。而後將根節點與堆的最後一個節點交換。而後對前面(n-1)個數從新調整使之成爲堆。
 * 依此類推,直到只有兩個節點的堆,並對它們做交換,最後獲得有n個節點的有序序列。
 * 從算法描述來看,堆排序須要兩個過程,一是創建堆,二是堆頂與堆的最後一個元素交換位置。
 * 因此堆排序有兩個函數組成。一是建堆的滲透函數,二是反覆調用滲透函數實現排序的函數。
 *
 *
 * 對於大數據的處理呢,若是對100億條數據選擇Topk數據,選擇快速排序好仍是堆排序好?
 * 答案是隻能用堆排序。
 * 堆排序只須要維護一個k大小的空間,即在內存開闢k大小的空間。而快速排序須要開闢能存儲100億條數據的空間
 *
 * Created by abing on 2015/11/26.
 */
public class SuanFaStack {

    public static void main(String[] args){
        int[] a = {3,1,4,6,2,43,21,65,22,44,88,11};

        headSort(a);

        for (int i : a){
            System.out.print(i + " ");
        }

    }


    public static void headSort(int[] arr){
        int arrlength = arr.length;
        for (int i = 0 ; i < arrlength - 1 ; i++){
            buildMaxHeap(arr, arrlength - 1 - i);
            swap(arr, 0, arrlength - 1 - i);
            System.out.println(Arrays.toString(arr));
        }
    }

    public static void swap(int[] arr , int i , int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    public static void buildMaxHeap(int[] data , int lastIndex){
        for (int i = (lastIndex-1)/2 ; i >= 0 ; i--){
            int k = i;
            while (k*2 + 1 <= lastIndex){
                int biggerIndex = 2*k + 1;
                if (biggerIndex < lastIndex){
                    if (data[biggerIndex] < data[biggerIndex+1]){
                        biggerIndex++;
                    }
                }

                if (data[k] < data[biggerIndex]){

                    swap(data , k , biggerIndex);
                    k = biggerIndex;
                }else {
                    break;
                }

            }

        }
    }
}
相關文章
相關標籤/搜索