IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 在归并排序中对小数组采用插入排序(算法导论课后思考题) -> 正文阅读

[数据结构与算法]在归并排序中对小数组采用插入排序(算法导论课后思考题)

算法导论课后习题及其实现

第二章课后思考题 2-1

在这里插入图片描述
在这里插入图片描述

  • a:插入排序的一般的时间复杂度为O( n 2 n^2 n2),在最坏情况下(输入的数组完全逆序)假设其运行的时间为 T = a n 2 + b n + c T=an^2+bn+c T=an2+bn+c(a,b,c为常数)。所以排序 n / k n/k n/k个长度为 k k k的数组需要的时间为 T k = n k ( a k 2 + b k + c ) = a n k + ( b + c k ) n T_k=\frac{n}{k}(ak^2+bk+c)=ank+(b+\frac{c}{k})n Tk?=kn?(ak2+bk+c)=ank+(b+kc?)n,所以其时间复杂度为O(nk)
  • b:合并两个长度为k的子表需要的时间为O(k),一共需要合并n/k个子表,所以需要的时间复杂度为O(n)。合并完成k个子表以后接下来需要合并n/2k个长度为2k的子表,所需要的时间复杂度依然为O(n)。一共需要合并lg(n/k)次才能完成排序。所以最终的时间复杂度为O(nlg(n/k))
  • c:(没太看明白他想问啥,就聊聊我的理解吧)修改后的算法的时间复杂度为O(nk+nlg(n/k))表明是插入排序过程(O(nk))和合并过程(O(nlg(n/k)))的结合。当 k = a n k=an k=an,a为一个常数时(即k的值是关于n的一个线性函数时)其时间复杂度变为O( n 2 n^2 n2)。当k为一个常数时,其时间复杂度大致可以表示为O(nlgn),其时间复杂度和普通归并排序相当,但当输入的规模变小时,由于常数项的影响选取合适的k值可以提升算法的运行效率。
  • d:经过c题的分析,当k选取为合适的常数时可以提升算法效率,具体k的取值要基于需求输入的规模。

算法效率测试

算法效率测试基于(leetcode:921 sortArray)平台完成

首先是插入排序的算法效率:

    //插入排序, 时间复杂度O(n^2) 空间复杂度O(1), 插入排序对完全有序的序列时间复杂度会降低到O(n)
    public int[] sortArray(int[] nums) {
        for (int i = 1; i < nums.length; i++) {
            int now = nums[i];
            int j = i;
            while (j>0 && now < nums[j - 1]){
                nums[j] = nums[j-1];
                nums[j-1] = now;
                j--;
            }
        }
        return nums;
    }

在这里插入图片描述
然后是归并排序的算法效率测试

    public int[] sortArray(int[] nums) {
        mergeSort(nums, 0, nums.length-1);
        return nums;
    }

    void mergeSort(int[] nums, int left, int right){
        if(left <right){
            int mid = (left+right)/2;
            mergeSort(nums, left, mid);
            mergeSort(nums, mid + 1, right);
            merge(nums, left, mid, right);
        }
    }

    // 对nums数组进行归并操作
    void merge(int[] nums, int left, int mid, int right){
        int[] newArray = new int[right - left + 1];
        int p1 = left;
        int p2 = mid+1;
        int p = 0;
        while (p1 <= mid && p2 <= right) {
            if(nums[p1] < nums[p2]){
                newArray[p] = nums[p1];
                p1++;
            }else {
                newArray[p] = nums[p2];
                p2++;
            }
            p++;
        }
        if(p1 <= mid){
            System.arraycopy(nums, p1, newArray, p, mid-p1+1);
        }
        if(p2 <= right){
            System.arraycopy(nums, p2, newArray, p, right-p2+1);
        }
        System.arraycopy(newArray, 0, nums, left, newArray.length);
    }

在这里插入图片描述
可以看见算法效率大大提升!从1692ms变为10ms
最后测试一下优化版本的归并插入排序这里我选取的k的值是8(随便选的没啥根据,如果兄弟们对k值的设置有想法的可以评论区分享)

 public int[] sortArray(int[] nums) {
        mergeInsertSort(nums, 0, nums.length-1);
        return nums;
    }

    //归并插入排序, 时间复杂度O(nlgn(n)) 空间复杂度O(1)
    void mergeInsertSort(int[] nums, int left, int right){
        if(right - left > 8){
            int mid = (left+right)/2;
            mergeInsertSort(nums, left, mid);
            mergeInsertSort(nums, mid + 1, right);
            merge(nums, left, mid, right);
            return;
        }
        insertionSort(nums, left, right);
    }
    //插入排序, 时间复杂度O(n^2) 空间复杂度O(1), 插入排序对完全有序的序列时间复杂度会降低到O(n)
    void insertionSort(int[] nums, int left, int right){
        for (int i = left+1; i <= right; i++) {
            int now = nums[i];
            int j = i;
            while (j>left && now < nums[j - 1]){
                nums[j] = nums[j-1];
                nums[j-1] = now;
                j--;
            }
        }
    }
    // 对nums数组进行归并操作
    void merge(int[] nums, int left, int mid, int right){
        int[] newArray = new int[right - left + 1];
        int p1 = left;
        int p2 = mid+1;
        int p = 0;
        while (p1 <= mid && p2 <= right) {
            if(nums[p1] < nums[p2]){
                newArray[p] = nums[p1];
                p1++;
            }else {
                newArray[p] = nums[p2];
                p2++;
            }
            p++;
        }
        if(p1 <= mid){
            System.arraycopy(nums, p1, newArray, p, mid-p1+1);
        }
        if(p2 <= right){
            System.arraycopy(nums, p2, newArray, p, right-p2+1);
        }
        System.arraycopy(newArray, 0, nums, left, newArray.length);
    }

在这里插入图片描述
可以看到执行速度提升了3ms

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:51:09  更:2021-07-11 16:53:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/8 13:24:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码