1.提出了双链表问题。本节不讲太多知识,主要围绕优化。想象一下,对于单链表的addLast()方法publicvoidaddLast(intx){size+=1;IntNodep=哨兵;while(p.next!=null){p=p.next;}p.next=newIntNode(x,null);}可以看出,每增加一个新的结束节点之前,我们都要遍历到当前结束节点。时间复杂度为O(n)。有没有办法实现O(1)?优化1添加一个变量last,它始终指向最后一个节点,类似于C语言中的尾指针publicclassSLList{privateIntNodelast;publicvoidaddLast(intx){last.next=newIntNode(x,null);最后一个=最后一个。下一个;尺寸+=1;}...}这样做之后,添加最后一个节点addLast()和找到最后一个节点getLast()的值的时间复杂度可以优化为O(1),但是对于removeLast(),即为删除尾节点,复杂度还是O(n),因为当我要删除尾节点时,需要找到倒数第二个节点,将其next赋值给NULL,这还是需要从头遍历整个链表.优化2.考虑给每个节点增加一个prev指针字段,指向它的前一个节点。这样,对于一个节点,它不仅可以访问它的上一个节点,还可以访问下一个节点,即双链表publicclassIntNode{publicIntNodeprev;公共整数项;publicIntNodenext;}经过优化,当我们需要删除最后一个节点时,只需要last.prev.next=null删除最后一个节点即可,时间复杂度降低为O(1)。随之而来的问题是,当一个链表中的所有节点都被删除,只剩下sentinel节点时,sentinel和last一起指向sentinel节点。也就是说last有时会指向一个普通的节点,删除的时候只哨兵节点指向哨兵节点,所以我们可能需要加入很多特殊的判断条件,优化起来比较麻烦。3那么我们可以考虑增加两个哨兵节点,一个在头部,一个在尾部。众所周知,sentinel节点数据字段我们不关心(图中??),sentinel节点就是标记节点的作用另一种方法是循环双链表,共享同一个sentinel节点,如图图中Summary2.Generic我们的IntNode代码定义是publicclassIntNode{publicIntNodeprev;公共整数项;接下来是公共IntNode;这意味着如果我们尝试使用字符串DLListd2=newDLList("hello");d2.addLast("world");我们只能将整数添加到链表节点的数据字段中。那么显然编译器会报错。一个直接的方法就是把所有的int都改成String,但是如果我想生成Double类型的节点怎么办?重新改一遍岂不是很麻烦,所以Java提供了一种叫做泛型的语法,我们只需要在类名(类名)后面加上
