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

参考资料

posted @ 2018-10-17 17:16  二许  阅读(290)  评论(2编辑  收藏  举报