zoukankan      html  css  js  c++  java
  • 20172323 2018-2019-1 《程序设计与数据结构》第五周学习总结

    20172323 2018-2019-1 《程序设计与数据结构》第五周学习总结

    教材学习内容总结

    本周学习了第六章排序与查找


    一些概念

    • 静态方法可以通过类名来激活,不用特意实例化该类的一个对象调用该静态类的方法。在方法声明中,通过使用static修饰符就可以把它声明为静态的
    • 创建泛型方法,只需在方法头前的返回类型前插入一个泛型声明即可。泛型声明必须在返回类型之前,这样泛型才可作为返回类型的一部分
    public static <T extends Comparable<T>> boolean
      linearSearch (T[] data, int min, int max, T target)
    

    查找

    • 在某个项目组中寻找某一指定目标元素,或确定该指定目标不存在,是为查找。进行查找的项目组被称为查找池
    • 线性查找法:从头开始依次比较每一个值,直到找到目标元素,或者得出不存在该目标值的结论,这种方式称为线性查找(linear search)
    • 二分查找(折半查找):当查找池中的项目组是已排序的,那么利用二分查找将会更有效率。
      • 二分查找的思路: 二分查找从排序列表的中间开始查找,如果中间元素不是目标元素,根据两个元素的大小关系,再判断从列表的前一半或是后一般进行查找。每次的查找都是从当前一串数字的中间元素开始的。直到最后找到该元素或是没有找到抛出一个信息。
      • 二分查找的每次比较都会删除一半的可行候选项,当查找池中有偶数个待查找值时,选择的是两个中间值的第一个。
      • 二分查找的复杂度是对数级的,这使得它对于大型查找池非常有效率。线性查找具有线性时间复杂度O(n),二分查找具有时间复杂度O(log2n)。

    排序

    • 基于某一标准,将某一项目组按照某个规定排序排列

    • 选择排序法

      • 反复寻找当前列表的最小值,然后将其放在列表的前端。
    • 插入排序法

      • 将数字插入前端已排序的列表的合适位置直至排序完成。
    • 冒泡排序法

      • 反复比较相邻元素的大小关系进行移位操作直至排序完成
    • 快速排序法

      • 选择一个列表元素进行分区元素,然后对两个分区进行递归排序直至排序完成(一个分区只含有一个元素2)。
      • 排序时两个分区同时进行查找,一旦两边都找到一个元素,将两者进行互换
    • 归并排序法

      • 将列表递归式分成两半直至每一子列表都含有一个元素,然后再归并到一个排序顺序中完成排序
    • 基数排序法

      • 基数排序基于队列处理

    教材学习中的问题和解决过程

    • 问题1:选择排序的代码实现中出现了public static <T extends Comparable<? super T>> void selectionSort (T[] data)之中<? super T>表示的是什么意思
    • 问题1解决方案:查阅资料在网上找到了一个通俗易懂的回答,大致上把<? super T>三个部分都讲得比较清楚了。按照我的理解,在这里?代表的是通配符,这一整串代表的是一个下界通配符,用在此处代表Comparable接口中的泛型元素都是T或者T的父类,这样就放松了存入数组的类型限制,但是引起的缺点就是往外读取元素就会变得困难,可能使元素类型信息丢失。

    • 问题2:几种排序方法时间复杂度的比较
    • 问题2解决方案
    排序方法 时间复杂度
    选择排序 O(n^2)
    插入排序 O(n^2)
    冒泡排序 O(n^2)
    快速排序 O(n*log2n)
    归并排序 O(nlog2n)
    基数排序 O(n)

    三种顺序排序方法都使用了内外两层循环进行排序操作,所以时间复杂度都为nxn-->O(n^2);
    快速排序和归并排序两种对数排序在排序中采取了递归的方法,因此在元素比较中只用到了大约nlog2n次比较,时间复杂度为O(log2n);还有一种特殊的基数排序,因为在排序过程中不涉及到元素之间的比较,只需要将元素在队列之间进行移动操作,操作时只用遍历数据即可,因此可以用c*n来表示(c是常数),所以时间复杂度为O(n)。

    代码调试中的问题和解决过程

    • 问题1:PP9.2中间隔排序的思路有些混乱,为什么每次迭代完成之后i要减少某个大于1的数量直至i的值小于1.
    • 问题1解决方案:在网上没能找到关于间隔排序的资料,所以不太懂原理,应该也和冒泡排序差不太多吧,就按照题目的要求拼好了代码,可运行出来的结果排序似乎并没有完成。

    假设现在有一个长度为6的数组,第一次的i为3,每一次迭代后i减少的值为2,那么在第一次迭代中,第一个元素与第三个元素进行比较,第二个元素与第四个元素进行比较,第三个元素与第五个元素进行比较,第四个元素与第六个元素进行比较,第一次迭代结束,i的值为1,第一个元素与第二个元素进行比较...相邻元素分别进行比较,迭代结束,i的值为-1小于1,此时循环结束,排序完成。

    如果每次i的值减少1

    与题目给的信息恰恰想反,反倒是每次减一时能得出正确的排序,多次修改代码中的间隔值,发现i每次减一时排序都能正确完成但是减二、减三时只能是在部分间隔值的情况下才能排序完成


    • 问题2:PP9.3如何用代码实现总的比较次数和总执行时间的计数
    • 问题2解决方案
      计时
      最开始应用的代码如下
    Date da = new Date();
    long s1 = da.getTime();
    ...//具体运行的代码
    long s2 = System.currentTimeMills();
    System.out.println(s2 - s1);
    

    代码开始运行时记录当前时间,代码结束前再记录一下当前时间,最后s2-s1即为运行时间,思路是没有问题,可是运行结果出来就有点小瑕疵,如图

    运行时间全为0且没带单位,我觉得系统并没有错,可能真是运行时间太短吧,小于一秒的计算机就自动四舍五入归为0了(?),我是这样认为的,所以我又寻找到另一种比较精密计量时间的方法
    以毫秒为单位计算的

    long startTime = System.currentTimeMillis();//获取当前时间
    doSomeThing();
    long endTime = System.currentTimeMillis();
    System.out.println("程序运行时间:"+(endTime-startTime)+"ms");
    
    

    以纳秒为单位计算的

    long startTime = System.nanoTime();//获取当前时间
    doSomeThing();
    long endTime = System.nanoTime();
    System.out.println("程序运行时间: "+(end-start)+"ns"); 
    

    好似万事俱备,运行一下试试,问题还是出现了,毫秒计时依然为0额。
    此时我又找到了Date.getTime的说明
    Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object
    ,显然这个方法同样是以毫秒为单位来计量代码运行的时间的,之前什么四舍五入的解释就有问题了,在网上寻找答案也只得到一些毫不沾边的东西,有点一筹莫展,后来我再仔细一瞅,发现纳秒计时的方法似乎没有出错啊,于是改成纳秒计时,然后就运行成功???有点莫名其妙。

    原以为计时在稀里糊涂之中就可以全部解决了,把五大排序法中分别加上s1、s2,然后运行一下,这次又是归并排序的计时出现了些问题,如图

    debug一下,错误应该出在忽略了递归上面,就是计算机每执行一次mergeSort的方法,就得重新开始计时一次,所以最后的结果会输出很多个归并排序的计时,参照快速排序的方法,相当于在归并排序的外面加一层壳专门用来计时,其他也想不出更好的办法了,最终结果如图


    比较次数

    • 对于选择排序、插入排序和冒泡排序,其内层循环都为比较相邻两元素的大小,外层控制存储的位置,所以只需在内层写入一个计数的变量count,每执行一次内层循环count+1.
    • 对于快速排序和归并排序,只要进行了一次compareTo操作count就需要加一,无论是否满足while循环的条件,因此while循环内外都应该有语句count++。

    代码托管

    上周考试错题总结

    上周没有错题哦

    结对及互评

    • 博客中值得学习的或问题:

      • 谭鑫的博客一直保持很高的水准,特别是问题的总结和解决能力都值得学习,能看出来是在用心学习
      • 方艺雯的博客教材学习内容总结认真详细,并配有图示和自己的理解,点个赞
    • 基于评分标准,我给谭鑫的博客打分:8分。得分情况如下:
      正确使用Markdown语法(加1分):
      模板中的要素齐全(加1分)
      教材学习中的问题和解决过程, 三个问题加3分
      代码调试中的问题和解决过程, 三个问题加3分

    • 基于评分标准,我给方艺雯的博客打分:8分。得分情况如下:、
      正确使用Markdown语法(加1分):
      模板中的要素齐全(加1分)
      教材学习中的问题和解决过程, 两个问题加2分
      代码调试中的问题和解决过程, 三个问题加3分
      排版精美加1分

    • 本周结对学习情况

      • 20172305
      • 20172314
      • 结对学习内容
        • 排序与查找
        • PP9.4中的比较次数经过反复讨论得到了比较一致的答案
    • 上周博客互评情况

    其他

    这周在代码学习上还是遇到了一些小的问题,在资料缺乏的情况下,自己动手写代码的能力、分析问题的能力有了一些加强,但还是稍显欠缺,需要继续努力

    学习进度条

    代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
    目标 5000行 30篇 400小时
    第一周 0/0 1/1 8/8
    第二周 470/470 1/2 12/20
    第三周 685/1155 2/4 10/30
    第四周 2499/3654 2/6 12/42
    第六周 1218/4872 2/8 10/52

    参考资料

  • 相关阅读:
    11.7表单事件 定时器
    11.5真11.6 函数调用 数组字符串的定义和方法
    11.2 面向对象 解析
    11.1 js数据类型 作用域 原型链
    10.31js中级作用域链和this
    定时器
    生出对象的方式
    学习this
    字符串
    全局方法
  • 原文地址:https://www.cnblogs.com/Lewandodoski/p/9805039.html
Copyright © 2011-2022 走看看