美文网首页
链表——链表的基本概念及基本实现

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

作者: FrodeWY | 来源:发表于2018-07-07 20:19 被阅读0次

一.简介:

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

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

二.链表结构示意图

链表结构.jpg
  • .链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起,每个结点包括两个部分:一个是存储数据元素 的数据域,另一个是存储下一个结点地址的 指针。如果要访问链表中一个元素,需要从第一个元素始,一直找到需要元素位置。但是增加和删除一个元素对于链表数据结构就非常简单了,只要修改元素中的指针就可以

  • .一般会有一个头指针head指向头结点,有时也会有尾指针tail,指向尾节点。

三.链表的代码实现

dummyHead链表实现.png
  • 这个链表的实现中,使用了虚拟节点dummyHead,使添加操作add()不在区分添加的是头结点还是其他节点,如果不使用dummyHead则需要判断添加的是不是头结点,因为头结点是没有上一个节点的。
/**
 * 添加了虚拟节点的链表,使得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);

  }
}

参考:

  • 慕课网

相关文章

  • iOS面试算法基础(2)-链表

    本节我们一起来探讨用 Swift 如何实现链表以及链表相关的技巧。 基本概念 对于链表的概念,实在是基本概念太多,...

  • 链表

    用Swift实现链表 基本概念 链表节点 有了节点,就可以实现链表了 有了上面的基本操作,我们来看如何解决复杂的问...

  • HashMap的线程不安全(jdk8也会造成死循环,原因暂未查明

    HashMap 基本概念 HashMap在jdk7及以前由数组加链表实现,在jdk8中加入了红黑树,在链表长度到...

  • 数据结构与算法之链表(三)单链表的常用操作

    引言 在上篇文章数据结构与算法之链表(二)单链表的基本实现中我们学习了单链表的基本概念,本篇我们在此基础之上研究单...

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

    一.简介: 1.链表是一种真正动态的数据结构 2.如果应用需要经常插入和删除元素使用链表将是很好的选择。 二.链表...

  • java数据结构(四)

    关于树的基本概念可以查看此篇文章树、堆、集合 1、一般树的实现: 树结构可以由递归实现,也可以由链表实现:链表实现...

  • 线性表

    线性表的基本概念与实现 顺序表和链表的比较 顺序表的结构体定义和基本操作 链表的结构体定义和基本操作 线性表的基本...

  • Redis数据结构学习-链表(二)

    链表 链表提供了高效的节点重排能力, 及顺序性节点访问方式, Redis构建了自己的链表实现 链表和链表节点的实现...

  • 线性表之单链表实现

    线性表之单链表实现 实现单链表的初始化、插入、删除等基本运算 实现单链表的输入、输出运算 实现单链表的逆置、归并、...

  • 数据结构与算法-如何手动实现一个java.util.Linked

    本篇主要是讨论另外一种最基本的数据结构-链表,所有物理结构是由链表组成的,可以称之为链式存储结构。 链表的基本概念...

网友评论

      本文标题:链表——链表的基本概念及基本实现

      本文链接:https://www.haomeiwen.com/subject/qjiguftx.html