排序

先定义一个排序对象,用于测试稳定性。

package sort;

import java.util.Random;

public class SortObj {
    private int value;
    private String name;

    public SortObj(int v) {
        this.value = v;
        this.name = String.valueOf(v);
    }
    public SortObj(int v, String n) {
        this.value = v;
        this.name = n;
    }
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public int hashCode() {
        return value;
    }
    @Override
    public boolean equals(Object obj) {
        if(null == obj) {
            return false;
        }
        if(!(obj instanceof SortObj)) {
            return false;
        }
        else {
            return this.value == ((SortObj)obj).getValue();
        }
    }

    public static SortObj[] genArr() {
        Random r = new Random(3);
        int size = 10;
        SortObj[] arr = new SortObj[size];
        for(int i=0; i<size; i++) {
            arr[i] = new SortObj(r.nextInt());
        }
        return arr;
    }
    public static SortObj[] genArr(int size) {
        Random r = new Random(50);
        SortObj[] arr = new SortObj[size];
        for(int i=0; i<size; i++) {
            arr[i] = new SortObj(r.nextInt());
        }
        return arr;
    }
    public boolean isLarger(SortObj sortObj) {
        return this.value > sortObj.getValue();
    }
    public boolean isSmaller(SortObj sortObj) {
        return this.value < sortObj.getValue();
    }
    @Override
    public String toString() {
        return name + ": " + String.valueOf(value);
    }
}

插入排序(Insert Sort)

基本思路是,遍历数组,认为左边的元素已经排序,将后面的元素从右往左比较,找到对应的位置,进行插入操作。
类似于插入扑克牌,左手的牌已经排好序,右手摸牌,插到左手的牌中。

    //Insert directly.
    public static SortObj[] insertSort(SortObj[] objArr) {
        if (null == objArr) {
            return null;
        }
        SortObj[] r = clone(objArr);
        if (r.length == 1) {
            return r;
        }
        int k;
        SortObj s;
        for (int i = 1; i < r.length; i++) {
            s = r[i];
            k = i - 1;
            while (k >= 0 && r[k].isLarger(s)) {
                r[k + 1] = r[k];
                k--;
            }
            r[k + 1] = s;
        }
        return r;
    }

可以利用二分法进行比较,减少比较次数。

希尔排序(Shell Sort)
基本原理:给定数组,选取步长,以步长为间隔将给定数组抽象地分解为若干子数组并在子数组内部进行插入排序,然后不断将步长缩短并循环上一步至步长为1,此时即为普通的插入排序。

代码诠释(严格按照原理)

public static SortObj[] shellSort(SortObj[] objArr) {
        if (null == objArr) {
            return null;
        }
        SortObj[] r = clone(objArr);
        if (r.length == 1) {
            return r;
        }
        int h = 0;
        while ((h * 3 + 1) < r.length) {
            h = h * 3 + 1;
        }
        SortObj s;
        while (h > 0) {
            for (int i = 0; i < h; i++) { // Loop sub arrays.
                for (int j = i + h; j < r.length; j += h) { // Insert sort for
                                                            // sub array.
                    for (int k = i; k < j; k += h) { // Loop inside sub array.
                                                        // Perform an insert
                                                        // sort.
                        if (r[k].isLarger(r[j])) { // Found the position that
                                                    // current element should be
                                                    // placed in the sub array
                            s = r[j];
                            for (int l = j; l > k; l -= h) {
                                r[l] = r[l - h];
                            }
                            r[k] = s;
                        }
                    }
                }
            }
            h = (h - 1) / 3;
        }
        return r;
    }

可以将分组合并的顺序做调整,缩减代码。缩减代码后:

    //Mainly shorten code. Same algorithm of restrictedShellSort method.
    //One nested loop less than the restricted one.
    public static SortObj[] optimizedShellSort(SortObj[] objArr) {
        if (null == objArr) {
            return null;
        }
        SortObj[] r = clone(objArr);
        if (r.length == 1) {
            return r;
        }
        // The DI.
        int h = 0;
        while ((h * 3 + 1) < r.length) {
            h = h * 3 + 1;
        }
        while (h > 0) {
            for (int i = h; i < r.length; i++) {
                int p = i - h;
                SortObj s = r[i];
                while (p >= 0 && r[p].isLarger(s)) {
                    r[p + h] = r[p];
                    p -= h;
                }
                r[p + h] = s;
            }
            h = (h - 1) / 3;
        }
        return r;
    }

归并排序

归并排序基本思路是将两个已经排好序的数组合并成一个排序数组,利用指针同时遍历两个数组,取出两个数值,将数值较小的数放在结果内,然后该指针向后移动一位,另外一个指针不变,直至其中一个数组达到末尾,而后将另一数组的剩下元素复制到结尾。
此方法一般使用递归算法,将无序数组拆递归分成两个无序数组,直至数组长度为1时,认为该数组已经排好序,不再拆分,开始递归回调。

递归算法实现代码:

    public static SortObj[] recursiveMergeSort(SortObj[] objArr) {
        if (null == objArr) {
            return null;
        }
        SortObj[] r = clone(objArr);
        if (r.length == 1) {
            return r;
        }
        int lLen = r.length / 2;
        int rLen = r.length - lLen;

        SortObj[] left = new SortObj[lLen];
        SortObj[] right = new SortObj[rLen];
        for (int i = 0; i < lLen; i++) {
            left[i] = r[i];
        }
        for (int i = 0; i < rLen; i++) {
            right[i] = r[lLen + i];
        }
        left = recursiveMergeSort(left);
        right = recursiveMergeSort(right);
        int m = 0, n = 0;
        for (; m < left.length && n < right.length;) {
            if (left[m].isLarger(right[n])) {
                r[m + n] = right[n];
                n++;
            } else {
                r[m + n] = left[m];
                m++;
            }
        }
        for (; m < left.length; m++) {
            r[m + n] = left[m];
        }
        for (; n < right.length; n++) {
            r[m + n] = right[n];
        }
        return r;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值