十大排序算法Java实现

315 阅读6分钟

算法不光是要会写,更重要的是要理解记住它的思想

冒泡排序

外层循环是表示的内层循环需要对比的次数,内层循环每结束一次都会得出未排列出的部分的最大值 时间复杂度是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]

时间复杂度与空间复杂度分析对比