十大排序演算法Java實現

_Git發表於2018-01-03

演算法不光是要會寫,更重要的是要理解記住它的思想

氣泡排序

外層迴圈是表示的內層迴圈需要對比的次數,內層迴圈每結束一次都會得出未排列出的部分的最大值 時間複雜度是O(n^2),空間複雜度是O(1),重要的是flag標誌是在內層迴圈結束後會做一次判斷,如果整個內層迴圈都未曾改變flag的值,說明陣列已經是有序的

    /**
     * 氣泡排序
     *
     * @param a
     */
    private void bubbleSort(int[] a) {
        //選出最大的元素需要length-1次比較
        for (int i = a.length - 1; i > 0; i--) {
            boolean flag = false;
            for (int j = 0; j < i; j++) {
                if (a[j] > a[j + 1]) {
                    int tmp = a[j + 1];
                    a[j + 1] = a[j];
                    a[j] = tmp;
                    flag = true;
                }
            }
            //沒有交換說明已經成序
            if (!flag)
                break;
        }
        System.out.println("氣泡排序結果:" + Arrays.toString(a));
    }
複製程式碼

選擇排序

    /**
     * 選擇排序
     *
     * @param a
     */
    private void selectSort(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < a.length; j++) {
                if (a[min] > a[j])
                    min = j;
            }
            if (min != i) {
                int tmp = a[min];
                a[min] = a[i];
                a[i] = tmp;
            }
        }
        System.out.println("選擇排序結果:" + Arrays.toString(a));
    }
複製程式碼

插入排序

/**
     * 插入排序
     *
     * @param a
     */
    private void insertSort(int[] a) {
        for (int i = 1; i < a.length; i++) {
            int j;
            for (j = i - 1; j >= 0; j--) {
                //找到第一個比a[i]小的索引
                if (a[j] < a[i])
                    break;
            }
            if (j != i - 1) {
                //每個元素向後移動一位
                for (int k = i - 1; k > j; k--) {
                    a[k + 1] = a[k];
                }
                a[j + 1] = a[i];
            }
        }
        System.out.println("插入排序結果:" + Arrays.toString(a));
    }

複製程式碼

桶排序

    /**
     * 桶排序
     *
     * @param a
     */
    private void bucketSort(int[] a) {
        int max = 0;
        for (int i : a) {
            if (i > max)
                max = i;
        }
        //初始化水桶max+1個
        int[] buckets = new int[max + 1];
        for (int i = 0; i < a.length; i++) {
            buckets[a[i]]++;
        }
        int index = 0;
        for (int i = 0; i < buckets.length; i++) {
            int key = buckets[i];
            while (key-- > 0) {
                a[index++] = i;
            }
        }
        System.out.println("桶排序結果:" + Arrays.toString(a));
    }
複製程式碼

快速排序

/*************************快速排序*****************************/
    private void quickSort(int[] a) {
        quickSort(a, 0, a.length - 1);
        System.out.println("快速排序結果:" + Arrays.toString(a));
    }

    private void quickSort(int[] a, int left, int right) {
        if (left < right) {
            int head = left;
            int tail = right;
            int x = a[head];
            while (head < tail) {
                while (head < tail && a[tail] > x)
                    tail--;
                if (head < tail)
                    a[head++] = a[tail];
                while (head < tail && a[head] > x)
                    head++;
                if (head < tail)
                    a[tail--] = a[head];
            }
            a[head] = x;
            quickSort(a, left, head - 1);
            quickSort(a, head + 1, right);
        }
    }
複製程式碼

堆排序

/****************************堆排序*****************************/
    private void heapSort(int[] a) {
        for (int i = a.length / 2 - 1; i >= 0; i--) {
            maxHeapSort(a, i, a.length - 1);
        }
        for (int i = a.length - 1; i > 0; i--) {
            //a[0]為最大元素,至於末尾
            int tmp = a[0];
            a[0] = a[i];
            a[i] = tmp;
            maxHeapSort(a, 0, i - 1);
        }
        System.out.println("堆排序結果:" + Arrays.toString(a));
    }

    /**
     * 利用最大堆找出最大的元素
     *
     * @param a
     * @param start
     * @param end
     */
    private void maxHeapSort(int[] a, int start, int end) {
        int c = start;
        //左孩子
        int left;
        int tmp = a[c];
        for (left = 2 * c + 1; left <= end; c = left, left = 2 * left + 1) {
            //選擇左右孩子中較大的一個
            if (left < end && a[left] < a[left + 1])
                left++;
            if (tmp >= a[left])
                break;
            else {
                a[c] = a[left];
                a[left] = tmp;
            }
        }
    }

複製程式碼

希爾排序

    /**
     * 希爾排序,用步長再插入
     *
     * @param a
     */
    private void shellSort(int[] a) {
        int n = a.length;
        //步長每次除以2
        for (int gap = n / 2; gap > 0; gap = gap / 2) {
            //對每組進行插入排序
            for (int i = 0; i < gap; i++) {
                shellSort(a, i, gap);
            }
        }
        System.out.println("希爾排序結果:" + Arrays.toString(a));
    }

    private void shellSort(int[] a, int start, int gap) {
        //這裡純粹是一個插入排序
        for (int j = start + gap; j < a.length; j = j + gap) {
            int k;
            for (k = j - gap; k >= start; k = k - gap) {
                if (a[k] < a[j])
                    break;
            }
            if (k != j - gap) {
                for (int i = j - gap; i > k; i = i - gap) {
                    a[i + 1] = a[i];
                }
                a[k + gap] = a[j];
            }
        }
    }
複製程式碼

基數排序

    /***************************基數排序**************************/
    private void radixSort(int[] a) {
        int max = 0;
        for (int i : a) {
            if (max < i)
                max = i;
        }
        for (int exp = 1; max / exp > 0; exp *= 10) {
            radixSort(a, exp);
        }
        System.out.println("基數排序結果:" + Arrays.toString(a));
    }

    private void radixSort(int[] a, int exp) {
        int[] output = new int[a.length];
        int[] buckets = new int[10];
        for (int i = 0; i < a.length; i++) {
            buckets[(a[i] / exp) % 10]++;
        }
        for (int i = 1; i < 10; i++) {
            buckets[i] += buckets[i - 1];
        }
        for (int i = a.length - 1; i >= 0; i--) {
            int index = (a[i] / exp) % 10;
            output[buckets[index] - 1] = a[i];
            buckets[index]--;
        }
        for (int i = 0; i < output.length; i++) {
            a[i] = output[i];
        }
    }
複製程式碼

歸併排序

/**************************歸併排序***************************/
    private void mergeSort(int[] a) {
        mergeSort(a, 0, a.length - 1);
        System.out.println("歸併排序結果:" + Arrays.toString(a));
    }

    private void mergeSort(int[] a, int start, int end) {
        if (start < end) {
            int mid = (end + start) / 2;
            mergeSort(a, start, mid);
            mergeSort(a, mid + 1, end);
            merge(a, start, mid, end);
        }
    }

    private void merge(int[] a, int start, int mid, int end) {
        int[] output = new int[end - start + 1];
        int index = 0;
        int i = start;
        int j = mid + 1;
        while (i <= mid && j <= end) {
            if (a[i] < a[j])
                output[index++] = a[i++];
            if (a[j] < a[i])
                output[index++] = a[j++];
            while (i <= mid) {
                output[index++] = a[i++];
            }
            while (j <= end) {
                output[index++] = a[j++];
            }
        }
        for (int k = 0; k < output.length; k++) {
            a[start + k] = output[k];
        }
    }
複製程式碼

計數排序

    /**
     * 計數排序
     *
     * @param a
     */
    private void countSort(int[] a) {
        //找出最大值和最小值
        int min = a[0], max = a[0];
        for (int i : a) {
            if (min > i)
                min = i;
            if (max < i)
                max = i;
        }
        //初始化桶
        int[] buckets = new int[max - min + 1];
        for (int i = 0; i < a.length; i++) {
            buckets[a[i] - min]++;
        }
        //這裡和基數排序一樣
        for (int i = 1; i < max - min + 1; i++) {
            buckets[i] += buckets[i - 1];
        }
        int[] output = new int[a.length];
        for (int i = a.length - 1; i >= 0; i--) {
            output[buckets[a[i] - min] - 1] = a[i];
            buckets[a[i] - min]--;
        }
        for (int i = 0; i < output.length; i++) {
            a[i] = output[i];
        }
        System.out.println("計數排序結果:" + Arrays.toString(a));
    }

複製程式碼

測試用例

   private static final int[] SORT_ARRAY = {43, 64, 21, 6565, 3424, 22, 6523, 345, 89, 68, 162, 528};

    public static void main(String[] args) {
        Sort sort = new Sort();
        sort.bubbleSort(SORT_ARRAY);
        sort.selectSort(SORT_ARRAY);
        sort.insertSort(SORT_ARRAY);
        sort.bucketSort(SORT_ARRAY);
        sort.quickSort(SORT_ARRAY);
        sort.heapSort(SORT_ARRAY);
        sort.shellSort(SORT_ARRAY);
        sort.radixSort(SORT_ARRAY);
        sort.mergeSort(SORT_ARRAY);
        sort.countSort(SORT_ARRAY);
    }
複製程式碼

測試結果

氣泡排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
選擇排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
插入排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
桶排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
快速排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
堆排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
希爾排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
基數排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
歸併排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
計數排序結果:[21, 22, 43, 64, 68, 89, 162, 345, 528, 3424, 6523, 6565]
複製程式碼

時間複雜度與空間複雜度分析對比

十大排序演算法Java實現

相關文章