自己动手写分布式搜索引擎
上QQ阅读APP看书,第一时间看更新

1.4.2 排序

如何得到一个排好序的词表?首先看一下如何对整数数组排序,然后再看一下如何对字符串数组排序。

排序可以看成是减少逆序的过程。通过交换值来消除逆序。检查任意两个位置的元素,如果是逆序,就交换这两个位置中的值。

        int[] scores = { 1, 6, 3, 8, 5 }; // 待排序的数组


        // 比较任意两个数,将小数放在前面,大数放在后面
        for (int i = 0; i < scores.length; i++) {
            for (int j = 0; j < scores.length; j++) {
                //如果是逆序,就交换这两个数
                if (i<j && scores[i] > scores[j]) { //同时满足两个条件
                    int temp = scores[j];
                    scores[j] = scores[i];
                    scores[i] = temp;
                }
            }
        }

这种随意消除逆序的方法并不能保证最后得到一个完全有序的数组。对于已经排好序的数组来说,最大的元素位于数组尾部。对于子数组来说,也是如此。也就是说,第二大的元素位于数组倒数第二的位置,第三大的元素位于数组倒数第三的位置,依次类推。冒泡排序正是基于这样的事实。

设想有一瓶汽水,溶解在水中的气体不断上浮,最后实现水气分离。每次让最重的一个元素沉到底。以后就不用再管它了。通过让轻的气泡不断上浮,从而达到有序。

将一个最重的元素沉底,顺便减少逆序。

        int[] scores = { 1, 6, 3, 8, 5 }; //待排序的数组
        for (int j = 0; j < scores.length -1 ; j++) {
                //循环不变式是:scores[j]存储了数组从开始一直到j为止的最大的一个数
                //比较相邻的两个数,将小数放在前面,大数放在后面
                if (scores[j] > scores[j + 1]) {
                    int temp = scores[j];
                    scores[j] = scores[j + 1];
                    scores[j + 1] = temp;
                }
        }

完整的冒泡排序。

        int[] scores = { 1, 6, 3, 8, 5 }; //待排序的数组


        for (int i = 0; i < scores.length -1; i++) { //每次搞定一个最大的元素
            // 最底下已经排好序,所以逐渐减少循环次数
            for (int j = 0; j < scores.length -1- i; j++) {
                //比较相邻的两个数,将小数放在前面,大数放在后面
                if (scores[j] > scores[j + 1]) {
                    int temp = scores[j];
                    scores[j] = scores[j + 1];
                    scores[j + 1] = temp;
                }
            }
        }
        System.out.println("排序后的结果:");
        for (int i = 0; i < scores.length; i++) {
            System.out.println(scores[i]);
        }

两层循环,内层循环执行一遍后,让1个数沉底。如果数组中有n 个元素,则外层循环执行n -1遍。也就是说通过n -1次循环让n -1个元素沉底。

想象在和很多人喝酒,要把这些人都招待好。i用来表示找每个人喝,j表示这个人每次要喝很多杯才能喝好。

首先看一下如何比较两个字符串的大小,然后再看一下如何对字符串数组排序。比较两个对象用compareTo()方法。字符串也是对象,所以也可以用compareTo()方法比较两个字符串的大小。

        String a = "北京";
        String b = "广州";
        System.out.print(a.compareTo(b)); //因为a小于b,所以返回负数

对字符串数组排序。

        String[] words = {"北京", "广州", "上海"};


        for (int i = 0; i < words.length -1; i++) {
            // 最底下已经排好序,所以逐渐减少循环次数
            for (int j = 0; j < words.length -1- i; j++) {
                if (words[j].compareTo(words[j + 1])>0) {
                    String temp = words[j];
                    words[j] = words[j + 1];
                    words[j + 1] = temp;
                }
            }
        }

如果数组中的元素很多,则快速排序更快。所要搜索的词往往很多,所以应该使用快速排序。