链表——链表的基本概念及基本实现

2018-07-07  本文已影响0人  FrodeWY

一.简介:

1.链表是一种真正动态的数据结构

2.如果应用需要经常插入和删除元素使用链表将是很好的选择。

二.链表结构示意图

链表结构.jpg

三.链表的代码实现

dummyHead链表实现.png
/**
 * 添加了虚拟节点的链表,使得add()方法不需要对第一个节点特殊处理 
 * 链表时间复杂度分析: 增:O(n) 删:O(n) 改:O(n) 查:O(n)
 */
public class DummyLinkedList<E> {

  private int size;
  private Node dummyHead;

  public DummyLinkedList() {
    this.size = 0;
    this.dummyHead = new Node();
  }

  private class Node {

    public E e;
    public Node next;

    public Node(E e, Node next) {
      this.e = e;
      this.next = next;
    }

    public Node(E e) {
      this(e, null);
    }

    public Node() {
      this(null, null);
    }

    @Override
    public String toString() {
      return e.toString();
    }
  }

  // 获取链表中的元素个数
  public int getSize() {
    return size;
  }

  // 返回链表是否为空
  public boolean isEmpty() {
    return size == 0;
  }

  /**
   * 在链表头添加新的元素e 时间复杂度O(1)
   */
  public void addFirst(E e) {
    add(0, e);
  }

  /**
   * 在链表的index(0-based)位置添加新的元素e 在链表中不是一个常用的操作,练习用:) 时间复杂度O(n/2)=O(n)
   */
  public void add(int index, E e) {
    if (index < 0 || index > size) {
      throw new IndexOutOfBoundsException();
    }
    if (index > 0 && isEmpty()) {
      throw new IndexOutOfBoundsException();
    }

    Node prevNode = dummyHead;
   /* 因为加了一个虚拟头结点,而使用者是不知道存在虚拟头结点的,
     所以使用者使用时的index指向的其实是用户想要添加的节点的上一个节点*/
    int i = 0;
    while (i < index) {
      prevNode = prevNode.next;
      i++;
    }
    prevNode.next = new Node(e, prevNode.next);
    size++;
  }

  /**
   * 在链表末尾添加新的元素e 时间复杂度O(n)
   */
  public void addLast(E e) {
    add(size, e);
  }

  /**
   * 根据底标获取一个元素 时间复杂度O(n/2)=O(n)
   */
  public E get(int index) {
    if (index < 0 || index >= size) {
      throw new IndexOutOfBoundsException();
    }
    Node node = dummyHead.next;
    for (int i = 0; i < index; i++) {
      node = node.next;
    }
    return node.e;
  }

  /**
   * 获得链表的第一个元素 时间复杂度O(1)
   */
  public E getFirst() {
    return get(0);
  }

  /**
   * 获得链表的最后一个元素 时间复杂度O(n)
   */
  public E getLast() {
    return get(size - 1);
  }

  /**
   * 修改index底标元素的值 时间复杂度O(n)
   */
  public void set(int index, E e) {
    if (index < 0 || index >= size) {
      throw new IndexOutOfBoundsException();
    }
    Node node = dummyHead.next;
    for (int i = 0; i < index; i++) {
      node = node.next;
    }
    node.e = e;
  }

  /**
   * 查找链表中是否有元素e,时间复杂度O(n)
   */
  public boolean contains(E e) {
    Node node = dummyHead.next;
    while (node != null) {
      if (node.e.equals(e)) {
        return true;
      }
      node = node.next;
    }
    return false;
  }

  /**
   * 删除节点 时间复杂度O(n/2)=O(n)
   */
  public E remove(int index) {
    if (index < 0 || index >= size) {
      throw new IndexOutOfBoundsException();
    }
    Node prev = dummyHead;

    for (int i = 0; i < index; i++) {
      prev = prev.next;
    }
    Node cur = prev.next;
    prev.next = cur.next;
    cur.next = null;
    size--;
    return cur.e;
  }

  /**
   * 删除最后节点 时间复杂度O(n)
   */
  public E removeLast() {
    return remove(size - 1);
  }

  /**
   * 删除第一个节点 时间复杂度O(1)
   */
  public E removeFirst() {
    return remove(0);
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    Node cur;
    for (cur = dummyHead.next; cur != null; cur = cur.next) {
      builder.append(cur.e + "  ");
    }
    return builder.toString();
  }

  public static void main(String[] args) {

    DummyLinkedList<Integer> linkedList = new DummyLinkedList<>();
    for (int i = 0; i < 5; i++) {
      linkedList.addFirst(i);
      System.out.println(linkedList);
    }

    linkedList.add(2, 666);
    linkedList.remove(2);
    linkedList.removeFirst();
    linkedList.removeLast();
    System.out.println(linkedList);

  }
}

参考:

上一篇下一篇

猜你喜欢

热点阅读