算法——排序之二

归并排序、快速排序、堆排序

    /**
     * 归并排序是建立在归并操作上的一种有效的排序算法。
     * 该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
     * 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
     * 若将两个有序表合并成一个有序表,称为2-路归并。
     * <p>
     * 算法描述:
     * 1.把长度为n的输入序列分成两个长度为n/2的子序列;
     * 2.对这两个子序列分别采用归并排序;
     * 3.将两个排序好的子序列合并成一个最终的排序序列。
     *
     * @param randomInts
     */
    private static int[] mergeSort(int[] randomInts) {
        int length = randomInts.length;

        if (length < 2) {
            return randomInts;
        }

        int middleIndex = (int) Math.floor(length / 2);
        int[] left = Arrays.copyOfRange(randomInts, 0, middleIndex);
        int[] right = Arrays.copyOfRange(randomInts, middleIndex, length);

        return merge(mergeSort(left), mergeSort(right));
    }

    private static int[] merge(int[] left, int[] right) {

        int leftIndex, rightIndex, resultIndex;
        int leftLength, rightLength;
        leftIndex = rightIndex = resultIndex = 0;
        leftLength = left.length;
        rightLength = right.length;

        int[] result = new int[leftLength + rightLength];

        while (leftIndex < leftLength && rightIndex < rightLength) {
            result[resultIndex++] = left[leftIndex] < right[rightIndex] ? left[leftIndex++] : right[rightIndex++];
        }

        if (leftIndex < leftLength) {
            System.arraycopy(left, leftIndex, result, resultIndex, leftLength - leftIndex);
        } else if (rightIndex < rightLength) {
            System.arraycopy(right, rightIndex, result, resultIndex, rightLength - rightIndex);
        }

        return result;
    }

    private static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    private static int partition(int[] a, int left, int right) {
        int pivot = left;
        int index = pivot + 1;

        for (int i = index; i <= right; i++) {
            if (a[pivot] > a[i]) {
                swap(a, i, index);
                index++;
            }
        }

        swap(a, index - 1, pivot);

        return index - 1;
    }

    /**
     * 快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,
     * 其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
     *
     * 算法描述
     * 快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:
     * 1.从数列中挑出一个元素,称为 “基准”(pivot);
     * 2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
     *   在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
     * 3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
     * @param randomInts
     * @param left
     * @param right
     */
    private static void quickSort(int[] randomInts, int left, int right) {
        if (left < right) {
            int partitionIndex = partition(randomInts, left, right);
            quickSort(randomInts, left, partitionIndex - 1);
            quickSort(randomInts, partitionIndex + 1, right);
        }
    }

    private static void buildMaxHeap(int[] a) {
        int length = a.length;

        for (int i = (int) Math.floor(length / 2); i >= 0; i--) {
            heapAdjust(a, 0, length);
        }
    }

    private static void heapAdjust(int[] a, int parentIndex, int length) {
        int leftIndex = parentIndex * 2 + 1;
        int rightIndex = parentIndex * 2 + 2;
        int largest = parentIndex;

        if (leftIndex < length && a[leftIndex] > a[largest]) {
            largest = leftIndex;
        }

        if (rightIndex < length && a[rightIndex] > a[largest]) {
            largest = rightIndex;
        }

        if (largest != parentIndex) {
            swap(a, largest, parentIndex);
            heapAdjust(a, largest, length);
        }
    }

    /**
     * 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。
     * 堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
     *
     * 算法描述:
     * 1.将初始待排序关键字序列(R1,R2….Rn)构建成大顶堆,此堆为初始的无序区;
     * 2.将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,……Rn-1)和新的有序区(Rn),且满足R[1,2…n-1]<=R[n];
     * 3.由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,……Rn-1)调整为新堆,
     *   然后再次将R[1]与无序区最后一个元素交换,得到新的无序区(R1,R2….Rn-2)和新的有序区(Rn-1,Rn)。
     *   不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
     * @param a
     */
    private static void heapSort(int[] a) {

        buildMaxHeap(a);

        int length = a.length;

        for (int i = length - 1; i > 0; i--) {
            swap(a, 0, i);
            length--;
            heapAdjust(a, 0, length);
        }

    }

参考文档

十大经典排序算法(动图演示)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值