跳转至

T08. Linked Lists

由于数组具有以下缺陷:

  • 在插入元素的时候需要移动大量数据
  • 可能开了 100000 的空间,但是没用到那么多
  • 如果满了,不方便扩容

所以引入链表这种数据结构。

单向的 Linked List 与 Link(singly)

链表,每一个节点都存储两个信息:数据、到下一个节点的链接。

在 CS210 这门课当中,认为 Linked List 是整个链表的头,而 Link(可以理解为 Node) 是每一个节点到下一个节点的连接。Linked List 存储到第一个 Link 的引用,而每一个 Link 存储到下一个节点的引用。

代码实现:

class LinkedList {
  private Link first;
  public LinkedList() { first = null; }
  public boolean isEmpty() { return first == null; }
}

public class Link {
  public int data;
  public Link next;
  public Link(int datain) { data = datain; next = null; }
}

对于 LinkedList 类,也就是整个链表结构类,还有以下操作:

// 在头部插入数据
public void insertHead(int x) {
  Link newLink = new Link(x);
  newLink.next = first;
  first = newLink;
}

// 删除头部数据并返回
public Link deleteHead() {
  Link data = first;
  first = first.next;
  return data;
}

// 遍历并输出链表
public void displayLink() { System.out.println("{" + data + "}"); }
public void display() {
  Link cur = first;
  while (cur != null) {
    cur.displayLink();
    cur = cur.next;
  }
}

// 删除一个节点
public Link delete(int key) {    // delete link with given key
  Link current = first;   // search for link
  Link previous = first;  // put these equal to first Link
  while (current.data != key)
    if (current.next == null) {
      return null;
    }  // didn't find it
    else {
      previous = current;  // go to next link
      current = current.next
    }
  }  // found it
  if (current == first) {          // if first link,
    first = first.next;            // change first
  } else {                         // otherwise,
    previous.next = current.next;  // bypass it
  }
  return current;
}

Double Ended Linked List

双端链表,也可以在尾部插入元素。

单端链表可以用来实现一个栈,双端链表可以用来实现一个队列。

有序链表 sorted linked list

就是插入元素的时候 $O(n)$ 找到合适的插入位置

可以用来实现排序,虽然仍然需要 $O(n^2)$ 的比较次数,但是 copy 次数是 $O(2n)$ 的,这方面比插入排序快一点。

doubly linked list

双向链表,每一个 Node(Link)额外存储一下 prev 信息。

iterators

用链表实现的栈