2018-2019-20172329 《Java软件结构与数据结构》第五周学习总结

2018-2019-20172329 《Java软件结构与数据结构》第五周学习总结

教材学习内容总结

《Java软件结构与数据结构》第九章-排序与查找

1、查找

  • 一、查找概念简述:

(1)查找3是这样一个过程,即在某个项目组中寻找某一指定目标元素,或者肯定该组中并不存在该目标元素。对其进行查找的项目组有时也称为查找组。php

(2)查找方式的分类:线性查找,二分查找。html

(3)查找所要完成的目标:尽量高效的完成查找,从算法分析的角度而言,咱们但愿最小化比较操做的次数,一般,查找池里项目数目越多,为了寻找该目标而作出的比较操做次数就越多,所以该查找池中项目的树目定义了该问题的大小。java

  • 二、线性查找法:

(1)若是该查找池组织成了一个某类型的列表,那么完成该查找的一个简单方式就是从该列表头开始一次比较每个值,直到找到该目标元素为止。node

(2)具体的样式图:
git

(3)代码实现:web

public static <T>   
        boolean linearSearch(T[] data, int min, int max, T target)
    {
        int index = min;
        boolean found = false;

        while (!found && index <= max) 
        {
            found = data[index].equals(target);
            index++;
        }

        return found;
    }
  • 三、二分查找法:

(1)前提:查找池中的项目组是已排序的。算法

(2)具体过程:二分查找是从排序列表的中间开始查找,而不是从一端或另外一端开始。若是没有在那个中间元素找到目标元素则继续查找。数组

(3)具体详细的样式图:
网络

(4)特色:二分查找将利用了查找池是已排序的这一事实;二分查找的每次比较都会删除一半的可行候选项;结合了递归的思想。数据结构

(5)代码实现:

public static <T extends Comparable<T>>  
        boolean binarySearch(T[] data, int min, int max, T target)
    {  
        boolean found = false;
        int midpoint = (min + max) / 2;  // determine the midpoint

        if (data[midpoint].compareTo(target) == 0)
            found = true;

        else if (data[midpoint].compareTo(target) > 0)
        {
            if (min <= midpoint - 1)
                found = binarySearch(data, min, midpoint - 1, target);
        }
        
        else if (midpoint + 1 <= max)
            found = binarySearch(data, midpoint + 1, max, target);

        return found;
    }

(6)注:若是二分查找分为元素为奇数和偶数个两种样式,就具体的问题有具体的解决方式,若是线性表为一个偶数个的有序列表的时候,所采用的中点能够是中间两个值的任意一个。

  • 四、查找算法的比较:

(1)对于线性查找而言,最好的情形是目标元素恰好是咱们所考察项目组中的第一个项目。

(2)线性查找算法具备线性时间复杂度O(n),由于是依次每回查找一个元素,因此复杂度是线性的——直接与待查找元素数目成比例。

(3)二分查找算法广泛要快得多。最好的情形就是一次比较就找到了该目标——也就是说,目标元素恰好位于数组的中点。最坏的情形出如今元素不在该列表的时候,在这种情形下,在删除全部数据以前,咱们不得不进行大约log2n次比较。所以找到位于该查找池中某一元素的预期情形是大约(log2n)/2次比较。

(4)二分查找的复杂度是对数级的,这使得它对于大型查找池很是有效率。

2、排序

  • 一、排序概念简述

(1)排序是这样一个过程,即基于某一标准,要么以升序要么以降序将某一组项目按照某个规定顺序排列。

(2)基于效率排序算法分为两类:顺序排序和对数排序。

(3)在顺序排序里,有三种排序方式,分别为:选择排序、插入排序以及冒泡排序。

(4)在对数排序中,有两种排序方式:快速排序和归并排序。

  • 二、选择排序法

(1)选择排序算法经过反复地将某一特定值放到它在列表中的最终已排序位置,从而完成对某一列值的排序。

(2)算法实现原理图


  • 三、插入排序法

(1)插入排序算法经过反复地将某一特定值插入到该列某个已排序的子集中来完成对列表值的排序。

(2)算法实现原理图


  • 四、冒泡排序法

(1)冒泡排序法是另外一种使用了两个嵌套循环的顺序排序算法,经过重复地比较相邻元素且在必要时将它们互换,从而完成对某个列表的排序。

(2)算法实现原理图

  • 五、快速排序法

(1)快速排序算法经过将列表分区,而后对这两个分区进行递归式排序,从而完成对整个列表的排序。

(2)算法实现原理图

  • 六、归并排序法

(1)归并排序算法经过将列表递归式分为两半直至每一字列表都含有一个元素,而后将这些字列表归并到一个排序顺序中,从而完成对列表的排序。

(2)算法实现原理图


  • 七、基数排序法

(1)基数排序是基于队列处理的。

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

  • 问题1:在学习到二分查找的时候书中的例子考虑到的是奇数个变量,假如是偶数个变量,咱们将如何进行处理?
  • 问题1解决过程:包括在老师上课的时候也都讲过,偶数个的话,中间两位任意一个均可以,就这个任意一个均可以就让我有点费解,在看了书中的解释

    在二分查找实现中,肯定中点索引的计算丢弃了任何分数部分,所以它选择的是两个中间值的第一个。

就这个解释而言,并且当我仅仅看书看到这里的时候,理解起来确定仍是不容易的,因此我继续看了书后面的内容,在看到对数排序的归并排序中,发现其实现的原理很是类似,其中在归并排序的代码实现中,个人问题在其中也有所体现:

int mid = (min + max) / 2;
while (first1 <= last1 && first2 <= last2)
        {
            if (data[first1].compareTo(data[first2]) < 0)
            {
                temp[index] = data[first1];
                first1++;
            }
            else
            {
                temp[index] = data[first2];
                first2++;
            }
            index++;
        }

从上述的代码就能够看出,代码实现的过程其实就是分开比较,分类比较,先肯定一个数,比它的左边和右边。

  • 问题2:在学习选择排序法的过程当中,其中在那个Sorting类中有swap这个写好的方法,其做用就是交换两个数组位置的内容,可是在咱们以前学习单链表的时候,在交换节点的时候老是须要考虑各个方面的因素,那咱们能不能也写这样一个方法进行结点互换呢?

  • 问题2解决过程:由于链表中每个结点都是连接起来的,假如盲目的断掉某一个可能就会致使空指针的问题或者更严重就会致使后面全部数据的丢失,因此在以前学习的过程当中,在我学习的过程当中,都是用先赋值给一个临时结点,而后把后面的结点插入到前面结点以前,再用后面结点链接到它后面的后面那个结点,这样实现结点的交换,可是这仅仅只能实现于在相邻的两个结点,因此有没有一种方法,咱们能够实现相似于swap的方法呢?因此我首先在网络上寻找有没有讲解相似相关知识的博文以获得灵感。
    这是我所找到的一个博主本身画的一张图

其实回想一下以前本身写过的一个程序中,仿佛本身好像也用到了相关的知识,由于我以为交换无非就是首先须要找到要交换的元素,再计算它们之间须要进行寻找的次数,也就是它们之间的距离,经过这样几项元素,就能够大体写出伪代码了。
个人伪代码思路就是:(1)由于首先咱们须要定义三个形式参数(这里我没有考虑假如交换的元素在链表中出现了屡次,这个在接下来的时间里我会再继续解决的),三个形参分别为list node1 node2,其中node1 node2为须要交换的两个元素,首先要找到node1和node2,而后把node1插入到node2的后面,把node2插入到node1的前面,再删除以前的node1和node2。
由于问题提出的时间很短,代码实现正在初步造成中。

  • 问题3:在学习快速排序法的时候,有这样一个方法partition方法,在这个方法中,它最终返回的是一个整型的right,这个类的用处是什么呢?
  • 问题3解决方法:首先,这个方法的两个内层循环用于寻找位于错误分区的交换元素,第一个循环从左边扫描右边以寻找到大于分区元素的元素,第二个循环,从右边扫描左边以寻找到小于分区元素的元素,在寻找到以后,进行互换。

  • 问题4:就上一个问题继续,其中有这样一句代码int middle = (min + max) / 2; ,在上学期中,有学习过在计算机语言中,假如定义一个整型的变量,若是给它赋予一个double型的数字,好比小数,变量最终只取整形的部位,举个例子相似于这样

    在这个方法中,假如是这个样子,会不会对程序有影响?

  • 问题4解决方法:这个程序中,有考虑到如此的状况,因此并不会受影响。

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

  • 问题1:在作pp9.2的做业中,发现本身所编写的外循环老是走一遍就停下来了,以下:

  • 问题1解决方法:
    一开始觉得本身是否是哪里编写错了,就大改了一番,本身从新多写了一个循环,仿照冒泡排序的代码写了一个,错的更厉害了,最后发现本身的错因竟是变量的名称没有修改对。
    修改为以下就能够了。

  • 问题2:在写pp9.3的时候,再计算时间的时候,发现本身输出的一直是0毫秒?以下图

  • 问题2解决方法:由于询问了郭恺同窗,在今天也就是十月十四日的时候,郭凯同窗说他也遇到了一样的问题,多是由于毫秒太大使得只显示了实数位,将其改成纳秒的时候,问题也就随之解决了

    也就是说,当咱们计算毫秒的时候所用的语句是下面代码:

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("程序运行时间: "+(endTime-startTime)+"ns");

代码连接

上周考试错题总结

上周无错题,太秀了!

结对及互评

  • 本周结对学习状况
  • 博客中值得学习的或问题:
    • 内容详略得当;
    • 代码调试环节比较详细;
  • 基于评分标准,我给本博客打分:5分。得分状况以下:
  1. 正确使用Markdown语法(加1分):
  2. 模板中的要素齐全(加1分)
  3. 教材学习中的问题和解决过程, 一个问题加1分
  4. 代码调试中的问题和解决过程, 一个问题加1分

  • 博客中值得学习的或问题:
    • 内容详略得当;
    • 代码调试环节比较详细;
  • 基于评分标准,我给本博客打分:9分。得分状况以下:
  1. 正确使用Markdown语法(加1分):
  2. 模板中的要素齐全(加1分)
  3. 教材学习中的问题和解决过程, 一个问题加1分
  4. 代码调试中的问题和解决过程, 一个问题加1分

感悟

这周上了三节Java课,也发现了本身在学习当中的一些问题,但愿本身能够把握住如今能够学习的机会,不要在之后后悔莫及的时候反思本身没有在正确的时间作正确的事情。加油!
不忘初心,方得始终!

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积)
目标 5000行 30篇 400小时
第一周 0/0 1/1 6/6
第二周 1313/1313 1/2 20/26
第三周 901/2214 1/3 20/46
第四周 3635/5849 2/4 20/66
第五周 1525/7374 1/5 20/86

参考资料

蓝墨云班课
Java程序设计
Java计算程序代码执行时间的方法小结
Java实现-两两交换链表中的节点
Java数据结构和算法(九)——高级排序
数据结构常见的八大排序算法

相关文章
相关标签/搜索