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

本文详细介绍了几种常见的排序算法,包括选择排序、插入排序和希尔排序。通过具体的代码实现展示了每种算法的工作原理及其特点。

排序算法模板

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;
        }
    }
}
已经博主授权,源码转载自 https://pan.quark.cn/s/a4b39357ea24 常见问题解答 网页打开速度慢或者打不开网页? 受到多种因素的影响,对于非会员用户我们无法提供最优质的服务。 如果您希望得到最棒的体验,请至大会员页面("右上角菜单 → 大会员")根据说明操作。 请注意:受制于国际网络的诸多不确定性,我们无法对任何服务的可靠性做出任何保证。 如果出现了网络连接相关的问题,我们建议您先等待一段时间,之后再重试。 如果您在重试后发现问题仍然存在,请联系我们,并说明网络问题持续的时间。 图片下载后无法找到? 打开"右上角菜单 → 更多 → 修改下载路径",在弹出的对话框中可以看到当前图片的保存路径。 此外,由于网络因素,在保存图片之后,等待屏幕下方出现"已保存到..."后,才能在本地找到图片。 如何更改图片保存的目录? 请参见"右上角菜单 → 更多 → 修改下载路径"。 翻页不方便? 在点进某个图片后,通过在图片上向左或向右滑动,即可翻页查看下一个作品。 如何保存原图/导出动图? 长按图片/动图,在弹出的菜单中选择保存/导出即可。 输入账号密码后出现"进行人机身份验证"? 此为pixiv登陆时的验证码,请按照要求点击方框或图片。 在pxvr中注册pixiv账号后,收到验证邮件,无法访问邮件中的验证链接? 请复制邮件中的链接,打开pxvr中的"右上角菜单 → 输入地址"进行访问。 能否自动将页面内容翻译为汉语? 很抱歉,pxvr暂不提供语言翻译服务。 图片下载类型是否可以选择? 能否批量下载/批量管理下载? 已支持批量下载多图作品中的所有原图:找到一个多图作品,进入详情页面后,点击图片进入多图浏览模式,长按任意一张图片即可看到批量下载选项。 关于上述其他功能,我们...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值