• 排序算法


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

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

    冒泡排序

    假设我们有一个数组{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

  • 相关阅读:
    输入和输出--java的NIO
    Java的NIO
    Java的nio
    输入和输出--java序列化机制
    输入和输出--javase中的路径
    输入和输出--重定向标准输入和输出
    输入和输出--RandomAccessFile类
    输入和输出--IO流
    输入和输出--File类
    无废话XML--DOM4J
  • 原文地址:https://www.cnblogs.com/yxth/p/10918867.html
Copyright © 2020-2023  润新知