20182310第八周学习总结

20182310 2019-2020-1 《数据结构与面向对象程序设计》第八周学习总结

教材学习内容总结

1.泛型
之前涉及过通过继承实现多态,而Object则是所有类型的父类,因此只要将一个数组指向Object类型,那么该数组理论上就可以保存所有类型的数据了,这是一种极端情况
但是,当使用了Object后,容易出现兄弟类型之间转换的问题,编译不会报错,但是运行时会出错。
泛型:可以定义一个类,可以保存数据及操作,但只有当实例化时才确定类型(一般用T来表示泛型)

class Box<T>
{
    T类型对象的声明与操作代码
}

当要使用Box定义的数据时,通过实例化来实现它的具体类型,来替代T

Box box1=new Box;
Box box2=new Box;
...
2.线性查找法
线性查找法就是从头开始查找,与每一个列表中的元素进行比较,直到找到该目标元素或查找到末尾还没找到。
以下的方法实现了一个线性查找。该方法返回一个布尔值,若是true,便是找到该元素,否则为false,表示没找到。

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;
    }

二分查找法
二分查找是从排序列表(查找池是已排序的)的中间开始查找,而不是从一端或者另一端的开始的。通过比较,确定可行候选项就又减少了一半的元素量,以相同的方式继续查找,直到最后找到目标元素或者不再存在可行候选项。
二分查找的关键在于每次比较都会删除一半的可行候选项。
以下的方法实现了一个二分查找,其中的最大索引和最小索引定义了用于查找(可行候选项)的数组部分。


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;
    }
}

注意:在该算法中,midpoint = (min + max) / 2,当min+max所得数值是基数的时候,会自动转化成int类型,直接忽略小数部分,也就是确定中点索引时选择的是两个中间值的第一个(小一点的)。
查找算法的比较
对于线性查找和二分查找,最好的情形都是目标元素恰好是我们考察的第一个元素,最坏的情形也都是目标不在该组中。因此,线性查找的时间复杂度为O(n),二分查找的时间复杂度为O(log2(n))。
当n比较大时,即元素特别多的时候,二分查找就会大大提高效率。而当n比较小的时候,线性查找更简单好调试且不需要排序,因此也在小型问题上常用线性查找。
3.排序
排序:基于某一标准,将某一组项目按照某个规定顺序排列。
顺序排序:通常使用一对嵌套循环对n个元素进行排序,需要大约n^2次比较。
对数排序:对n个元素进行排序通常大约需要nlog2(n)次比较。
常见的三种顺序排序:
①选择排序、②插入排序、③冒泡排序;
常见的两种对数排序:
①快速排序、②归并排序
选择排序:通过反复地找到某个最小(或者最大)元素,并把它放置到最后的位置来给元素排序。
插入排序:通过反复地把某个元素插入到之前已经排序的子列表中,实现元素的排序。
冒泡排序:通过反复的比较相邻元素并交换他们,来给元素排序。
快速排序:通过把未排序元素分隔成两个分区,然后递归地给每个分区排序。
快速排序的平均时间复杂度为O(nlogn)。在所有平均时间复杂度为O(nlogn)的算法中,快速排序的平均性能是最好的。

4.在JavaAPI中的ArrayList类和LinkedList类是由不同的底层结构实现的列表。
ArrayList类和LinkedList类都实现了java.util.List接口。List接口中的一些方法如图所示:

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

  • 问题1:Queue接口两种方法add和offer在异常类处理上有何不同。

  • 问题1解决方案add操作可以确保队列中有给定的元素。如果给定元素没有添加到队列中,该操作将抛出一个异常。
    offer操作把给定元素插入到队列中,如果插入成功,返回true,否则返回false。

  • 问题2:ASL的含义

  • 问题2解决方案:平均查找长度(Average Search Length,ASL):需和指定key进行比较的关键字的个数的期望值,称为查找算法在查找成功时的平均查找长度。用于衡量算法的效率。

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

  • 问题1:关于null
  • 问题1解决方案:null值不是任何对象的实例, 所以下面这个例子返回了false,无论这个变量声明的是什么类型。
    String s = null;
    if ( s instanceof String ) 强制上传后,:wq保存,然后重新git push即可。
  • 问题2:用链表实现有序列表添加操作时候的空指针异常。
  • 问题2解决方案:
public void add(T element) {
    if (!(element instanceof Comparable))
        throw new NonComparableElementException("OrderedList");

    Comparable<T> comparableElement = (Comparable<T>)element;

    LinearNode<T> current = head;
    LinearNode<T> previous = null;
    LinearNode<T> node = new LinearNode<>(element);


    while (( current != null) && (comparableElement.compareTo(current.getElement()) > 0))
    {
        previous = current;
        current = current.getNext();
    }

    if (previous == null )
    {
        head = node;
    }
    else {
        previous.setNext(node);
    }

    node.setNext(current);

    count++;
    modCount++;
}

有序列表的插入代码,在运行调试之后,报错位置在这里。

while ( comparableElement.compareTo(current.getElement()) > 0 && current != null )

这是一开始的错误代码。发现,在进行while判断的时候,是先进行compareTo的比较大小操作,而非判断current是否为空。所以,当current为空的时候,就直接出现了空指针异常。
所以只需要把两个条件相互颠倒一下即可。

代码托管

上周考试错题总结

上周没有进行考试,所以没有错题。

结对及互评

评分标准

  • 博客中值得学习的或问题:
    • 学习:在总结问题时有附上详细的图片,而我总是忘记截图,代码中出现的问题也能及时自己发现错误来源。
    • 问题:教材学习内容总结不够详细。
  • 代码中值得学习的或问题:无
  • 基于评分标准,我给本博客打分:15分。得分情况如下:
  1. 正确使用Markdown语法(加1分):

  2. 模板中的要素齐全(加1分)

  3. 教材学习中的问题和解决过程, 一个问题加1分()

  4. 代码调试中的问题和解决过程, 一个问题加1分()

  5. 本周有效代码超过300分行的(加2分)

  6. 其他加分:

    • 感想,体会不假大空的加1分
    • 排版精美的加一分
    • 进度条中记录学习时间与改进情况的加1分
    • 有动手写新代码的加1分
    • 课后选择题有验证的加1分
    • 错题学习深入的加1分
    • 点评认真,能指出博客和代码中的问题的加1分
    • 结对学习情况真实可信的加1分

点评过的同学博客和代码

其他(感悟、思考等,可选)

最近学习的都是数据结构的知识,相对应的代码量也变得多了起来,作业和课堂实践也变多了。但是博客还是应该要认真完成,同时我发现自己的码云仓库有点乱需要整理。继续努力吧。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 10000行 30篇 400小时
第一周 155/200 2/2 20/20 初步掌握linux命令、java小程序和jdb调试
第二 三周 470/625 2/4 20/40 学会scanner定义的使用,类的定义
第四周 1444/2069 2/4 20/60 下载安装IDEA及其插件,学会TDD调试,编写测试代码
第五周 1917/3986 2/8 20/80 简单的学会客户端和服务器的编写
第六周 1324/5310 1/9 20/100 Java封装,继承,多态
第七周 2795/8105 3/12 40/140 栈,链表
第八周 1135/9240 1/13 40/180 选择排序等各种排序,查找等
posted @ 2019-11-04 13:44  tursws  阅读(209)  评论(4编辑  收藏  举报