数据结构第二季 Day02 插入排序

1、插入排序的英文名称是什么?插入排序的两大步骤思想?(重要)

  • 插入排序(Insertion Sort):插入排序非常类似于扑克牌的排序
  • 执行流程:
  • ①在执行过程中,插入排序会将序列分为 2 部分:头部是已经排好序的,尾部是待排序的
  • ②从头开始扫描每一个元素:当每扫描到一个元素,就将它插入到头部合适的位置,使得头部数据依然保持有序
image.png

2、在做循环的时候,什么时候使用 while,什么时候使用 for?

  • 当遍历需要取出和索引有关的数据时,使用 for 循环。
  • 当遍历只需要满足某个条件时,和索引无关时,使用 while 循环。

3、插入排序代码实现(版本一,默写出来)?

    protected void sort() {
        for (int begin = 1; begin < array.length; begin++) {
            int curIndex = begin;
            while (curIndex > 0 && cmp(curIndex, curIndex -1) < 0) {
                swap(curIndex, curIndex - 1);
                curIndex--;
            }
        }
    }

4、什么是逆序对?逆序对越少,插入排序的效率越高吗?

  • 逆序对: 数组中存在逆序的元素两两组合,就是逆序对。
  • 逆序对越少,插入排序的效率越高,甚至速度比 O(nlogn) 级别还快。

5、思考:插入排序可以优化①吗?

  • 可以,可以从减少交互次数的方面进行一次优化。
image.png

6、排序优化①代码实现?

    protected void sort() {
        for (int begin = 1; begin < array.length; begin++) {
            T element = array[begin];
            int curIndex = begin;
            while (curIndex > 0 && cmp(element, array[curIndex - 1]) < 0) {
                array[curIndex] = array[curIndex -1];
                curIndex--;
            }
            array[curIndex] = element;
        }
    }

7、二分搜索元素(Binary Search)的前提是什么?理论步骤是什么?最坏时间复杂度是多少?(重要)

  • 前提是:数组是有序的
  • 假设在[begin, end]范围内搜索某个元素v,mid = (begin + end) / 2 , m 是 mid 索引所在的值
  • 如果 v < m,去 [begin, mid) 范围内二分搜索
  • 如果 v > m,去 [mid+1, end) 范围内二分搜索
  • 如果 v==m,直接返回 mid
  • 最坏时间复杂度是 O(logn)
image.png
image.png

8、实例练习,用二分搜索元素法,查找下面元素

image.png
image.png

9、二分搜索代码的实现?(要能默写出来)

    //递归实现
    static int binarySearch(Integer[] array ,int begin, int end, Integer distValue) {
        if (begin == end) return -1; //没找到
        int mid = (begin + end) >> 1;
        int midValue = array[mid];
        if (distValue < midValue) { //去左边找
            return binarySearch(array,begin, mid, distValue);
        } else if (distValue > midValue) { //去右边找
            return binarySearch(array,mid + 1, end, distValue);
        } else {
            return mid;
        }
    }
    //非递归实现
    static int binarySearch2(Integer[] array, Integer distValue) {
        if (array == null || array.length == 0) return -1; //没找到
        int begin = 0;
        int end = array.length;
        while (begin < end) {
            int mid = (begin + end) >> 1;
            int midValue = array[mid];
            if (distValue < midValue) { //去左边找
                end = mid;
            } else if (distValue > midValue) { //去右边找
                begin = mid + 1;
            } else {
                return mid;
            }
        }
        return -1;
    }

10、如何用二分查找的思想,找元素插入位置呢(重要)?

image.png
image.png

11、上面二分搜索的实例应用,能帮助理解,一定要能理解到位!!!!

image.png

image.png

image.png

image.png

image.png

12、二分查找优化插入排序的思想(版本二,从查找插入位置方面进行优化)?

    protected void sort() {
        for (int begin = 1; begin < array.length; begin++) {
            insert(searchInsertIndex(begin),begin);
        }
    }
    //遍历往后移动元素,移动完成插入目标元素
    private void insert(int source, int dest) {
        int insertIndex = searchInsertIndex(source);
        T insertValue = array[insertIndex];
        for (int i = dest; i > insertIndex ; i--) {
            array[i] = array[i - 1];
        }
        array[insertIndex] = insertValue;
    }
    //二分查找元素插入位置
    private int searchInsertIndex(int index) {
        int begin = 0;
        int end = index;
        while (begin < end) {
            int mid = (begin + end) >> 1;
            T midValue = array[mid];
            if (cmp(index, mid) < 0) { //去左边找
                end = mid;
            } else{ //去右边找
                begin = mid + 1;
            }
        }
        return begin;
    }
image.png

13、使用二分搜索后,插入排序的平均时间复杂度是多少?二分搜索优化了插入排序的哪个部分?

  • 平均时间复杂度依然是 O(n^2)
  • 需要注意的是,使用了二分搜索后,只是减少了比较次数O(logn),但是移动元素仍然是 O(n) 级别

你可能感兴趣的:(数据结构第二季 Day02 插入排序)