单链表,我来了

一、单链表的特点

链表以结点作为存储单元,这些存储单元可以是不连续的。单链表每个结点由两部分组成:存储的数值+后序结点的指针,下面均是单链表的操作。

在这里插入图片描述
上面展示的是一个单链表的存储原理图,简单易懂,head为头节点,他不存放任何的数据,只是充当一个指向链表中真正存放数据的第一个节点的作用,而每个节点中都有一个next引用,指向下一个节点,就这样一节一节往下面记录,直到最后一个节点,其中的next指向null。(网络引用)

二、实战(废话不多说,直接上机开干)

class Node {
    
    
  ///数据域
  int data;

  下一个结点
  Node next;

  Node(int data){
    
    
    this.data = data;
  }
}
class LinkList {
    
    
  Node head;

 void addNode(Node data) {
    
    
    if (head == null) {
    
    
      head = data;
      return;
    }
    Node temp = head;
    while (temp.next != null) {
    
    
      temp = temp.next;
    }
    temp.next = data;
  }

  ///插入到指定位置
  void insertNodeByIndex(int index, Node newNode) {
    
    
    if (index < 0 || index > getLength()) {
    
    
      print("插入位置不合法");
    }
    if (head == null) {
    
    
      head = newNode;
      return;
    }
    int len = 0;
    Node temp = head;
    while (temp.next != null) {
    
    
      len++;
      if (len == index) {
    
    
        newNode.next = temp.next;
        temp.next = newNode;
        break;
      }
      temp = temp.next;
    }
  }

  Node removeAt(int index) {
    
    
    if (index < 0 || index > getLength()) {
    
    
      return null;
    }
    if (head == null) {
    
    
      return null;
    }
    if (index == 0) {
    
    
      //删除头结点
      head = head.next;
      return head;
    }
    Node temp = head;
    Node delNode;
    int len = 0;
    while (temp.next != null) {
    
    
      len++;
      if (len == index) {
    
    
        delNode = temp.next;
        temp.next = temp.next.next;
        break;
      }
      temp = temp.next;
    }
    return delNode;
  }

  bool remove(Node node) {
    
    
    if (node == null) {
    
    
      return false;
    }
    if (head == null) {
    
    
      return false;
    }
    if (node.data == head.data) {
    
    
      //删除头结点
      head = head.next;
      return true;
    }
    Node temp = head;
    bool isSuccess = false;
    while (temp.next != null) {
    
    
      if (temp.next.next == node.next) {
    
    
        temp.next = node.next;
        isSuccess = true;
        break;
      }
      temp = temp.next;
    }
    return isSuccess;
  }

  int getLength() {
    
    
    if (head == null) {
    
    
      return 0;
    }
    int len = 0;
    Node temp = head;
    while (temp.next != null) {
    
    
      temp = temp.next;
      len++;
    }
    return len;
  }

  ///查找元素
  Node findNodeByIndex(int index) {
    
    
    if (index < 0 || index > getLength()) {
    
    
      return null;
    }
    if (head == null) {
    
    
      return null;
    }
    Node temp = head;
    for (int i = 0; i < index; i++) {
    
    
      temp = temp.next;
    }
    return temp;
  }

  ///遍历
  void printLink() {
    
    
    Node curNode = head;
    while (curNode != null) {
    
    
      print(curNode.data);
      curNode = curNode.next;
    }
  }
}

测试类

  LinkList list = new LinkList();
  Node node1 = Node(1);
  Node node2 = Node(2);
  Node node3 = Node(3);
  list.addNode(node1);
  list.addNode(node2);
  list.addNode(node3);
  Node node4 = Node(4);
  list.insertNodeByIndex(1, node4);
  print("删除前:");
  list.printLink();
  list.remove(node4);
  print("删除的元素:${list.removeAt(1).data}");
  print("删除后:");
  list.printLink();
  print("查找元素:${list.findNodeByIndex(1).data}");

三、链表的总结

单链表、循环链表、双向链表的比较

链表结构 优点 缺点
单链表 1、在找出节点后,插入和删除速度相较于顺序表更快 2、不需要预分配空间,元素个数不受限制 查找数据元素的速度相较于顺序表更慢
循环链表 在单链表的基础上进一步改进,遍历的时候可以从任意结点开始,增加了遍历的灵活性 没有解决单链表查找元素速度较慢的问题
双向链表 在单链表的基础上进一步改进,查找元素可以反向查找前缀结点,一定程度上提升了查找数据元素的速度 需要记录前缀结点,增加了额外的内存空间开销
静态链表 在插入和删除操作时,不需要移动元素,只需要修改游标,改进 了顺序表插入和删除需要移动元素的缺点 1、没有解决顺序表表长难以确定的问题 2、失去了顺序表随机存储的特性

猜你喜欢

转载自blog.csdn.net/hjjdehao/article/details/119600930