列表

详细介绍见 Josh Hug 为 Berkeley CS61B 编写的教材

最新版本

一个数据结构可视化网站

基础实现

我们可以创建最基础的链表如下:

public class IntList {
    public int first;
    public IntList rest;

    public IntList(int f, IntList r) {
        first = f;
        rest = r;
    }

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

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

如果我们想加入数字 5、10、15,可以采取以下方式:

或者:

直观的显示为:

SLList

首先创建列表的单个元素:

再创建一个类用于与用户交互,简化用户的操作:

这样处理后的类更易于使用:

直观的表示为:

  • 进一步,我们可以采用嵌套类整合代码。如果嵌套类不需要使用外层类的任何实例方法和变量,可以将其声明为 static,这意味着静态类中的方法不能访问封闭类的任何成员,在下面代码即表现为 IntNode 中的任何方法都无法访问 first、addFirst 或者 getFirst,这样设置关键词可以节省少量内存。

  • 另一个改进是跟踪当前表的 size,这种保存重要数据以加快检索速度的方法有时称为缓存。

  • 考虑创建或插入空链表时可能导致的特殊情况(使用 sentinel node)。

DLList

DLList 将是基于 SLList 的改进。改进方向:

  • 双向链表,可以降低 addLast 运行耗时,同时解决哨兵节点在链表为空时出现的问题。

  • 使用泛型,可以储存任何类型的数据结构

AList

AList 也是一个可以存储任意长数据的列表,与前面不同的是,它使用数组而非链表,其优势主要在于 get(int i) 即获取特定索引的值的函数的响应时间。

该方法的主要难点在于数组的大小调整,做法是创建一个新的数组并复制原数组的内容,但需要考虑到程序用时与内存占用。

具体操作是:

  • RFACTOR 为拓展因子,在需要对数组进行拓展时使用乘法拓展;

  • THRESHOLD 为触发数组缩小的使用率阈值,即数组中非空部分占比小于此值,对数组进行缩小以减少空间占用;

Last updated