高级排序

一、希尔排序

       希尔排序因计算机科学家Donald L. Shell得名,他在1959年发现了希尔排序算法。希尔排序基于插入排序,但是通过n-增量排序,大大地提高了插入排序的执行效率。希尔排序使用的间隔序列除了n=3n+1这样的间隔序列,也可以使用其他的间隔序列,不过必须保证一个最终条件n=1。

package com.xwiam.algorithms.advancesort;

/**
 * 希尔排序
 */
public class ShellSort {

    private long[] instance;
    private int nElems;

    public ShellSort(int maxSize) {
        instance = new long[maxSize];
        nElems = 0;
    }

    public void insert(long value) {
        instance[nElems++] = value;
    }

    public void display() {
        for (int i = 0;i < nElems;i++) {
            System.out.print(instance[i] + " ");
        }
        System.out.println();
    }

    public void sort() {
        int inner, outer;
        long temp;
        int n = 1;
        while (n <= nElems / 3) {
            n = n * 3 + 1;
        }
        while (n > 0) {
            for (outer = n;outer < nElems;outer++) {
                temp = instance[outer];
                inner = outer;
                while (inner > n - 1 && instance[inner - n] > temp) {
                    instance[inner] = instance[inner - n];
                    inner -= n;
                }
                instance[inner] = temp;
            }
            n = (n - 1) / 3 ;
        }
    }

    public static void main(String[] args) {
        int maxSize = 10;

        ShellSort shellSort = new ShellSort(maxSize);
        for (int i = 0;i < maxSize;i++) {
            long n = (int) (Math.random() * 99);
            shellSort.insert(n);
        }
        shellSort.display();
        shellSort.sort();
        shellSort.display();
    }
}

希尔排序的效率

迄今为止,除了一些特殊的 情况下,还没有人能够从理论上分析希尔排序的效率。有各种各样基于试验的评估,估计它的时间级从O(N3/2)到O(N/7/6)。

二、快速排序

在大多数情况下,对于内存排序来说,快速排序是最快的。对于硬盘文件的排序,其他的排序算法可能更改好。快速排序基于分治算法,所以执行时间为O(N*logN)。

1、选择数组最右端的数据作为划分枢纽的快速排序,适用于随机排序的数组。如果数组是有序的或者逆序的,快速排序的执行时间会从O(N*logN)变为O(N2)。因为划分数组的时候基本都是n-1和1,最优的划分是划分后左右数组的大小相等或者接近。

package com.xwiam.algorithms.advancesort;

/**
 * 快速排序
 */
public class QuickSort1 {

    private long[] instance;
    private int nElems;

    public QuickSort1(int maxSize) {
        instance = new long[maxSize];
        nElems = 0;
    }

    public void insert(long value) {
        instance[nElems++] = value;
    }

    public void display() {
        for (int i = 0;i < nElems;i++) {
            System.out.print(instance[i] + " ");
        }
        System.out.println();
    }

    public void quickSort() {
        recQuickSort(0, nElems - 1);
    }

    private void recQuickSort(int left, int right) {
        if (right - left <= 0) {
            return;
        } else {
            long pivot = instance[right];
            int partition = partition(left, right, pivot);
            recQuickSort(left, partition - 1);
            recQuickSort(partition + 1, right);
        }

    }

    private int partition(int left, int right, long pivot) {
        int leftPtr = left - 1;
        int rightPtr = right;
        while (true) {
            while (instance[++leftPtr] < pivot) {
            }
            while (rightPtr > 0 && instance[--rightPtr] > pivot) {
            }
            if (leftPtr >= rightPtr) {
                break;
            } else {
                swap(leftPtr, rightPtr);
            }
        }
        swap(leftPtr, right);
        return leftPtr;
    }

    private void swap(int left, int right) {
        long temp = instance[right];
        instance[right] = instance[left];
        instance[left] = temp;
    }

    public static void main(String[] args) {
        int maxSize = 10;
        QuickSort1 quickSort1 = new QuickSort1(maxSize);
        for (int i = 0;i < maxSize;i++) {
            long n = (int) (Math.random() * 99);
            quickSort1.insert(n);
        }
        quickSort1.display();
        quickSort1.quickSort();
        quickSort1.display();
    }
}

2、使用三数据项取中划分方法,取数组中最左,最右和中间的数值排序后取中间值,作为枢纽值,适用于数据基本有序的数组。

package com.xwiam.algorithms.advancesort;

/**
 * 快速排序+插入排序
 */
public class QuickSort2 {

    private long[] instance;
    private int nElems;

    public QuickSort2(int maxSize) {
        instance = new long[maxSize];
        nElems = 0;
    }

    public void insert(long value) {
        instance[nElems++] = value;
    }

    public void display() {
        for (int i = 0;i < nElems;i++) {
            System.out.print(instance[i] + " ");
        }
        System.out.println(" ");
    }

    public void quickSort() {
        if (nElems < 10) {
            insertSort();
        } else {
            recQuickSort(0, nElems - 1);
        }
    }

    private void insertSort() {
        int inter, outer;
        long insertValue;
        for (outer = 0;outer < nElems;outer++) {
            insertValue = instance[outer];
            inter = outer;
            while (inter > 0 && instance[inter - 1] > insertValue) {
                instance[inter] = instance[inter - 1];
                inter--;
            }
            instance[inter] = insertValue;
        }
    }

    private void recQuickSort(int left, int right) {
        if (right - left <= 0) {
            return;
        } else {
            long pivot = median(left, right);
            int partition = partition(left, right, pivot);
            recQuickSort(left, partition - 1);
            recQuickSort(partition + 1, right);
        }

    }

    private long median(int left, int right) {
        int mid = (left + right) / 2;
        if (instance[left] > instance[mid]) {
            swap(left, mid);
        }
        if (instance[left] > instance[right]) {
            swap(left,right);
        }
        if (instance[mid] > instance[right]) {
            swap(mid, right);
        }
        swap(mid, right);
        return instance[right];
    }

    private int partition(int left, int right, long pivot) {
        int leftPtr = left -1;
        int rightPtr = right;
        while (true) {
            while (instance[++leftPtr] < pivot) {
            }
            while (instance[--rightPtr] > pivot) {
            }
            if (leftPtr >= rightPtr) {
                break;
            } else {
                swap(leftPtr, rightPtr);
            }
        }
        swap(leftPtr, right);
        return leftPtr;
    }

    private void swap(int left, int mid) {
        long temp = instance[mid];
        instance[mid] = instance[left];
        instance[left] = temp;
    }

    public static void main(String[] args) {
        int maxSize = 10;
        QuickSort2 quickSort2 = new QuickSort2(maxSize);
        for (int i = 0;i < maxSize;i++) {
            long n = (int) (Math.random() * 99);
            quickSort2.insert(n);
        }
        quickSort2.display();
        quickSort2.quickSort();
        quickSort2.display();
    }


}

快速排序的效率:

快速排序的时间复杂度为O(N*logN)。数据随机的数组的划分枢纽可以选择数组最右端的值。数据基本有序的数组的划分枢纽可以选择三数据项取中划分方法。目的都是保证划分后的数组大小左右相等或者相近。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值