算法 - 选择排序

 一种最简单的排序算法是这样的:首先,找到数组中最小的那个元素,其次,将它和数组中的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次,在剩下的元素中找到最小元素,将它与数组的第二个元素交换位置。如此反复,直到将整个数组排序。这种方法就叫做选择排序,因为它在不断的选择剩余元素中的最小者。

选择排序是种很容易理解和实现的简单排序算法,它有两个很鲜明的特点。

运行时间和输入无关。为了找出最小的元素而扫描遍数组并不能为下一遍扫描提供什么信息,这种性质在某些情况下是缺点,因为使用选择排序的人可能会惊讶地发现,一个已经有序的数组或是主键全部相等的数组和一个元素随机排列的数组所用的排序时间竟然一样长! 我们将会看到,其他算法会更善于利用输人的初始状态。

数据移动是最少的。每次交换都会改变两个数组元素的值,因此选择排序用了N次交换一交换次数和数组的大小是线性关系。我们将研究的其他任何算法都不具备这个特征(大部分的增长数量级都是线性对数或是平方级别)。 

以下是实现代码:

public class Selection
{

    static int compareCount = 0;
    static int changeCount = 0;
    static int loopCount = 0;

    public static boolean less(Comparable v, Comparable w){
        compareCount++;
        return v.compareTo(w) < 0;
    }

    public static void exch(Comparable[] a, int i, int j)
    {
        Comparable t = a[i];
        a[i] = a[j];
        a[j] = t;
        changeCount++;
    }

    //在单行中打印数组
    public static void show(Comparable[] a)
    {
        for (int i = 0; i < a.length; i++)
        {
            if (i == a.length - 1)
                System.out.print(a[i]);
            else
                System.out.print(a[i] + ",");
        }
    }

    //测试数组元素是否有序
    public static boolean isSorted(Comparable[] a)
    {
        for (int i = 1; i < a.length; i++)
        {
            if (less(a[i], a[i-1])) return false;
        }
        return true;
    }

    public static void sort(Comparable[] a)
    {
        //将a[]按升序排序
        int N = a.length;

        for (int i = 0; i < N; i++)
        {   //将a[i]和a[i+1..N]中最小的元素交换
            int min = i;        //最小元素的索引
            for (int j = i + 1; j < N; j++)
            {
                if (less(a[j], a[min]))    min = j;
            }
            exch(a, i, min);
            System.out.print("第" + (i + 1) + "次排序," + "交换的位置索引:" + i + "\t[" );
            show(a);
            System.out.println("]");
        }
    }

    public static void main(String[] args){
        Integer[] a = {4,5,2,9,6,3,7,1,8,0};
        System.out.print("\t\t\t\t\t\t[");
        show(a);
        System.out.println("]");
        sort(a);
        assert isSorted(a);
        System.out.println("一共交换了:" + changeCount + "次,比较了:" + compareCount + "次");
    }

}

红色标注的是交换的元素

                                                    [4,5,2,9,6,3,7,1,8,0]
第1次排序,交换的位置索引:0      [0,5,2,9,6,3,7,1,8,4]
第2次排序,交换的位置索引:1      [0,1,2,9,6,3,7,5,8,4]
第3次排序,交换的位置索引:2      [0,1,2,9,6,3,7,5,8,4]
第4次排序,交换的位置索引:3      [0,1,2,3,6,9,7,5,8,4]
第5次排序,交换的位置索引:4      [0,1,2,3,4,9,7,5,8,6]
第6次排序,交换的位置索引:5      [0,1,2,3,4,5,7,9,8,6]
第7次排序,交换的位置索引:6      [0,1,2,3,4,5,6,9,8,7]
第8次排序,交换的位置索引:7      [0,1,2,3,4,5,6,7,8,9]
第9次排序,交换的位置索引:8      [0,1,2,3,4,5,6,7,8,9]
第10次排序,交换的位置索引:9    [0,1,2,3,4,5,6,7,8,9]
一共交换了:10次,比较了:45次

 

 

以上内容摘抄自 《算法(第四版)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值