排序算法

排序算法众所周知的比较简单,因此就在这里用一篇文章进行描述一下。

排序算法常用的有两种,一个是冒泡排序,一个是插入排序。

 

冒泡排序

假设我们有一个数组{1,5,7,9,2,4,8}。

所谓冒泡,就是不断地用前一个元素和后一个元素进行比较,如果满足条件就不处理,不满足条件,则会向气泡一样,不断地向后冒。

比如我们数组中的第一个和第二个元素比较,1<5,不做处理。此时数组{1,5,7,9,2,4,8}

然后我们再比较第二个和第二个元素,5<7,不做处理。此时数组{1,5,7,9,2,4,8}

……

我们再比较第四个和第五个元素,9>2,此时需要将9和2调换位置,数组变成{1,5,7,2,9,4,8}

……

以此类推,由于我们数组中9是最大值,因此它会不断地和后面的元素进行交换位置,就像气泡一样,不断地向后冒。最终的数组变成{1,5,7,2,4,8,9}

这时候我们进行了第一遍的循环,得出了数组中的最大元素9。然后我们再对数组的0到length-2重复比较,以此类推可以得出数组中第二大的元素。第一次的循环长度是从0到6,第二次的循环长度只要从1到5。以此类推第三次我们可以得出数组中第三大的元素,循环长度只要从1到4。第四次是1到3,第五次是1到2。由此,我们的整个数组的排序结束。

总结:

假设有一个长度为n的数组,

第一次从第0位与第1位的比较开始,一直比较到它的第n-2位与n-1位。

第二次从第0位与第1位的比较开始,一直比较到它的第n-3位与n-2位。

……

第n-1次从第0位与第1位的比较开始,一直比较到它的第n-1-(n-1)位与n-(n-1)位。即第0位与第1位。

由此排序结束,一共执行了n-1次循环,得出排序后的数组。

代码实现

    public int[] sort(int[] ints) {
        int n = ints.length;
        // 一共会执行n-1次循环。
        for (int i = 0; i < n - 1; i++) {
            // 每次循环从第0位与第一位比较开始,一直比较到第n-1-(n-1)与第n-(n-1)的比较。这里的i=n-1
            for (int j = 0; j < n - 1 - i; j++) {
                //如果前一个数大于后一个数,则交换位置。否则不变
                if (ints[j] > ints[j+1]) {
                    int tmp = ints[j+1];
                    ints[j + 1] = ints[j];
                    ints[j] = tmp;
                }
            }
        }
        return ints;
    }

客户端调用代码

    public static void main(String[] args) {
        int[] ints = {1,5,7,9,2,4,8};
        Main4 m = new Main4();
        m.sort(ints);
        System.out.println(StringUtils.join(ints,','));
    }

输出结果:

1,2,4,5,7,8,9

 

插入排序

插入排序同样也是用前一个元素和后一个元素不断地进行比较,如果满足条件,则不进行处理,不满足条件,就将当前元素和前面的每一个元素进行比较,找到可以插入的位置后将元素插入,并将后面的元素后移一位。

假设我们有一个数组{1,5,7,9,2,4,8}。

第一次比较,1<5,不作处理。

第二次比较,5<7,不作处理。

……

第四次比较,9>2,提出元素2出来,与前面的三位再逐一比较。

  第4.1次比较,1<2,不作处理。

  第4.2次比较,5>2,因此将元素2放在元素2的位置上,同时后面的元素5,7,9全部后移一位。此时数组{1,2,5,7,9,4,8}

第五次比较,9>4,提出元素4出来,再与前面的4位逐一比较。

  第5.1次比较,1<4,不作处理。

  第5.2次比较,2<4,不作处理。

  第5.3次比较,5>4,因此将元素4放在元素5的位置上,同时后面的元素5,7,9全部后移一位。此时数组{1,2,4,5,7,9,8}

 

第六次比较,9>8,提出元素8出来,再与前面的5位进行比较。最后可得出数组{1,2,4,5,7,8,9}

总结:

  一个长度为n的数组,从第一位与第二位比较开始,一直到第n-2位与n-1位比较结束,一共会比较n-1次。其间如果判断出元素i大于元素i+1,则会元素i+1与前面的0到i位元素依次比较,找到第一个大于元素i+1的元素位置m,将元素i+1存放在m,同时对m到i位置上元素后移一位。

代码实现:

    public int[] sort2(int[] ints) {
        int n = ints.length;
        // 一共要循环比较n-1次
        for (int i = 0; i < n - 1; i++) {
            // 如果第i个数比第i+1个数大,则将i+1与前面0到i位上的数进行比较。
            if (ints[i] > ints[i + 1]) {
                // 从0开始,一直比较到i。
                for (int j = 0; j <= i; j++) {
                    // 如果遇见了比i+1位上的数大的位置j,将i+1位上的元素存放在j位上,同时对j到i位的元素依次后移一位
                    if (ints[j] > ints[i + 1]) {
                        int tmp = ints[i + 1];
                        // 对j到i位上的依次后移。这里是倒着移动。
                        for (int k = i; k >= j; k--) {
                            ints[k + 1] = ints[k];
                        }
                        // 移动完成后,将第i+1位元素存放在j位上。并跳出循环。继续进行最外面的n-1次循环比较。
                        ints[j] = tmp;
                        break;
                    }
                }
            }
        }
        return ints;
    }

客户端调用

    public static void main(String[] args) {
        int[] ints = {1,5,7,9,2,4,8};
        Main4 m = new Main4();
        m.sort2(ints);
        System.out.println(StringUtils.join(ints,','));
    }

输入结果:

1,2,4,5,7,8,9

 

二分法

二分法用来在有序数组中快速地查找某一个元素的位置。每一次可以去除掉一半的元素。

假如有数组int[] ints={1,2,4,5,7,8,9},长度为7。

我们要从中找到元素7的位置。

第一次我们取数组的中间元素(0+6)/2=3,ints[3]=5。判断5<7,得出7所在的位置大于3。去除掉数组的左半部分。剩余{1,2,4,5,7,8,9

第二次再取中间元素(3+1+6)/2=5,int[5]=8。判断8>7,得出7所在的位置小于5。这时候,结合两次判断的范围,得出7的取值大于3,小于5,因此就只剩下位置4。

返回7所在的位置下标:4

结论:

  我们假设有一个有序数组,长度为n。求它的某一个元素的值。每一次去掉可选范围的一半。最多会计算log(n)次。

代码实现:

    public int search(int[] ints, int num) {
        int tmp = -1;
        int begin = 0;
        int end = ints.length;
        int middle = 0;
        while (begin < end) {
            middle = (begin + end) >> 1;
            if (num == ints[middle]) {
                return middle;
            } else if (num < ints[middle]) {
                // 范围在左边,取左部分数组
                end = middle - 1;
            } else {
                // 范围在右边,取右部分数组
                begin = middle + 1;
            }
        }
        if (num == ints[begin]) {
            return begin;
        }
        return tmp;
    }

客户端调用

    public static void main(String[] args) {
        int[] ints = {1,5,7,9,2,4,8};
        Main4 m = new Main4();
        // 先会数组排序
        m.sort2(ints);
        System.out.println(StringUtils.join(ints,','));
        // 查找元素1的位置
        System.out.println(m.search(ints, 1));
        // 查找元素2的位置
        System.out.println(m.search(ints, 2));
    }

输出结果:

0,1

 

posted @ 2019-05-24 16:30  一响贪欢  阅读(174)  评论(0编辑  收藏  举报