List(CS61B学习记录)

  • 问题引入

上图中,赋给b海象的weight会改变a海象的weight,但x的赋值又不会改变y的赋值

Bits

要解释上图的问题,我们应该从Java的底层入手

相同的二进制编码,却因为数据类型不同,输出不同的值

变量的声明

基本类型

Java does not write anything into the reserved box when a variable is declared. In other words, there are no default values. As a result, the Java compiler prevents you from using a variable until after the box has been filled with bits using the = operator. For this reason, I have avoided showing any bits in the boxes in the figure above.

引用类型

When we declare a variable of any reference type (Walrus, Dog, Planet, array, etc.), Java allocates a box of 64 bits, no matter what type of object.

96位大于64位,这似乎有些矛盾:

在Java中:the 64 bit box contains not the data about the walrus, but instead the address of the Walrus in memory.

Gloden rule

练习

答案:B

解析:

  • 在调用方法(函数)时,doStuff方法中的int x与main方法中的int x 实际上处于两个不同的scope(调用方法时会new 一个scope,并将main方法中的x变量的位都传递给doStuff方法中的x变量,即值传递),所以x = x - 5实际上只作用于doStuff方法中的x,而不是main方法中的x。
  • 但对于引用类型来说,引用类型储存的是引用的地址,所以在进行值传递时传递的是对象的地址,所以doStuff方法中的int x与main方法中的walrus实际上指向相同的一个对象,这使得doStuff中执行的语句会作用于main方法中walrus指向的对象,所以反作用于main方法中的walrus

IntLists


使用递归求链表中元素的个数

java 复制代码
/** Return the size of the list using... recursion! */
public int size() {
    if (rest == null) {
        return 1;
    }
    return 1 + this.rest.size();
}

Exercise: You might wonder why we don't do something like if (this == null) return 0;. Why wouldn't this work?

Answer: Think about what happens when you call size. You are calling it on an object, for example L.size(). If L were null, then you would get a NullPointer error!

不使用递归求元素个数

java 复制代码
/** Return the size of the list using no recursion! */
public int iterativeSize() {
    IntList p = this;
    int totalSize = 0;
    while (p != null) {
        totalSize += 1;
        p = p.rest;
    }
    return totalSize;
}

求第n个元素

SLList

接下来我们对IntList进行改进,使链表看上去不那么naked

有了节点类,现在我们补充上链表类

java 复制代码
public class SLList {
    public IntNode first;

    public SLList(int x) {
        first = new IntNode(x, null);
    }
}

对比SLList和IntList,我们发现,在使用SLList时无需强调null

java 复制代码
IntList L1 = new IntList(5, null);
SLList L2  = new SLList(5);

addFirst() and getFirst()

java 复制代码
  /** Adds an item to the front of the list. */
    public void addFirst(int x) {
        first = new IntNode(x, first);
    }
    /** Retrieves the front item from the list. */
    public int getFirst() {
        return first.item;
}

private and nested class

java 复制代码
public class SLList {
    public class IntNode {
        public int item;
        public IntNode next;
        public IntNode(int i, IntNode n) {
            item = i;
            next = n;
        }
    }
    private IntNode first;

    public SLList(int x) {
        first = new IntNode(x, null);
    }
    /** Adds an item to the front of the list. */
    public void addFirst(int x) {
        first = new IntNode(x,first);
    }
    /** Retrieves the front item from the list. */
    public int getFirst() {
        return first.item;
    }
}

addLast() and Size()

java 复制代码
/** Adds an item to the end of the list. */
public void addLast(int x) {
    IntNode p = first;

    /* Advance p to the end of the list. */
    while (p.next != null) {
        p = p.next;
    }
    p.next = new IntNode(x, null);
}
java 复制代码
/** Returns the size of the list starting at IntNode p. */
private static int size(IntNode p) {
    if (p.next == null) {
        return 1;
    }

    return 1 + size(p.next);
}

优化低效的Size()方法

在改变链表的Size时直接记录下,就可以不需要在Size()方法中遍历链表了

java 复制代码
public class SLList {
    ... /* IntNode declaration omitted. */
    private IntNode first;
    private int size;

    public SLList(int x) {
        first = new IntNode(x, null);
        size = 1;
    }

    public void addFirst(int x) {
        first = new IntNode(x, first);
        size += 1;
    }

    public int size() {
        return size;
    }
    ...
}

空链表( The Empty List)

创建空链表很简单(对于SLList),但会导致addLast()方法报错

java 复制代码
public SLList() {
    first = null;
    size = 0;
}
java 复制代码
public void addLast(int x) {
    size += 1;
    IntNode p = first;
    while (p.next != null) {
        p = p.next;
    }

    p.next = new IntNode(x, null);
}

p指向null,故p.next会出现空指针异常

addLast()改进(使用分支)
java 复制代码
public void addLast(int x) {
    size += 1;

    if (first == null) {
        first = new IntNode(x, null);
        return;
    }

    IntNode p = first;
    while (p.next != null) {
        p = p.next;
    }

    p.next = new IntNode(x, null);
}
addLast()改进(更robust的做法)

对于存在很多特殊情况需要讨论 的数据结构,上面的方法就显得十分低效。

故我们需要考虑将其改进为一个具有普适性 的方法:将first改为sentinal.next
sentinal将会永远存在于链表的上位

java 复制代码
package lists.sslist;

public class SLList {
    public class IntNode {
        public int item;
        public IntNode next;
        public IntNode(int i, IntNode n) {
            item = i;
            next = n;
        }
    }

    private IntNode sentinel;
    private int size;

    public SLList() {
        sentinel = new IntNode(63,null);
        size = 0;
    }

    public SLList(int x) {
        sentinel = new IntNode(63,null);
        sentinel.next = new IntNode(x, null);
        size = 1;
    }

    /** Adds an item to the front of the list. */
    public void addFirst(int x) {
        sentinel.next = new IntNode(x, sentinel.next);
        size += 1;
    }

    /** Retrieves the front item from the list. */
    public int getFirst() {
        return sentinel.next.item;
    }

    /** Returns the number of items in the list. */
    public int size() {
        return size;
    }

    /** Adds an item to the end of the list. */
    public void addLast(int x) {
        IntNode p = sentinel;

        /* Advance p to the end of the list. */
        while (p.next != null) {
            p = p.next;
        }
        p.next = new IntNode(x, null);
    }

    /** Crashes when you call addLast on an empty SLList. Fix it. */
    public static void main(String[] args) {
        SLList x = new SLList();
        x.addLast(5);
    }
}
相关推荐
Red Red1 小时前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全
Natural_yz3 小时前
大数据学习17之Spark-Core
大数据·学习·spark
qq_172805593 小时前
RUST学习教程-安装教程
开发语言·学习·rust·安装
一只小小汤圆3 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
LateBloomer7773 小时前
FreeRTOS——信号量
笔记·stm32·学习·freertos
legend_jz3 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
Komorebi.py3 小时前
【Linux】-学习笔记04
linux·笔记·学习
weiabc4 小时前
学习electron
javascript·学习·electron
HackKong5 小时前
小白怎样入门网络安全?
网络·学习·安全·web安全·网络安全·黑客