算法——排序:初级排序算法,选择、插入、希尔排序

排序算法模板

public abstract class Sort {
    // 排序代码
    public abstract void sort(Comparable[] a);
    // 辅助函数:比较元素
    protected static boolean less(Comparable c1, Comparable c2) {
        return c1.compareTo(c2) < 0;
    }
    // 辅助函数:交换元素
    protected static void exch(Comparable[] a, int i, int j) {
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    // 打印数组
    protected static void show(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();
    }
    // 是否有序
    protected static boolean isSorted(Comparable[] a) {
        for (int i = 1; i < a.length; i++) {
            if (less(a[i], a[i - 1])) {
                return false;
            }
        }
        return true;
    }
}

选择排序

从数组中找出最小的元素和数组第一个元素交换位置,然后从剩下的元素中找出最小的和数组第二个元素交换,。。。直到将整个数组排序。也就是,从未排序的部分选择最小的,和当前位置交换,始终保持左侧已排序部分有序且不再参与交换,因此内层循环不会循环到左侧已排序部分,即下面代码中始终有 j > i。

/**
 * 选择排序
 * 在未排序的部分找出最小的,并和当前位置交换
 */
public class Selection extends Sort {
    @Override
    public void sort(Comparable[] a) {
        if (a == null || a.length < 2) {
            return;
        }
        Comparable min = a[0];
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = i + 1; j < a.length; j++) {
                if (less(a[j], a[i])) {
                    exch(a, i, j);
                }
            }
        }
    }
}

插入排序

将当前索引位置的元素插入左侧已排序部分的合适位置,直到当前位置达到最右端。当前位置与目标位置之间的元素会被向右移动,因此内循环是从当前位置向左遍历到目标位置,始终有 j <= i。
插入排序特别适合于部分有序或近似有序的数组。

/**
 * 插入排序
 * 将元素插入已排序部分合适的位置
 */
public class Insertion extends Sort {
    @Override
    public void sort(Comparable[] a) {
        if (a == null || a.length < 2) {
            return;
        }
        for (int i = 1; i < a.length; i++) {
            for (int j = i; j > 0; j--) {
                if (less(a[j], a[j - 1])) {
                    exch(a, j, j - 1);
                }
            }
        }
    }
    @Override
    public void sort(Comparable[] a) {
        if (a == null || a.length < 2) {
            return;
        }
        int i, j;
        for (i = 1; i < a.length; i++) {
            // 方式二:将较大元素向右移动,而不是每次都交换,更快
            Comparable index = a[i];
            for (j = i - 1; j >= 0 && less(index, a[j]); j--) {
                a[j + 1] = a[j];
            }
            a[j + 1] = index;
        }
    }
}

希尔排序

使数组中任意间隔为h的元素都是有序的(即h有序数组)。即一个h有序数组就是h个互相独立的有序数组编织在一起组成的一个数组。当h比较大时,基于插入排序,元素的移动间隔就可以很远,

/**
 * 希尔排序
 * 基于插入排序,移动步长为h
 */
public class Shell extends Sort {
    @Override
    public void sort(Comparable[] a) {
        if (a == null || a.length < 2) {
            return;
        }
        int h = 1;
        while (h < a.length / 3) {
            h = h * 3 + 1;
        }
        while (h >= 1) {
            for (int i = h; i < a.length; i++) {
                for (int j = i; j >= h && less(a[j], a[j - h]); j -= h) {
                    exch(a, j, j - h);
                }
                show(a);
            }
            h = h / 3;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值