单向链表(常规和带哨兵)

1.定义

在计算机科学中,链表是数据元素的线性集合,每个元素都指向下一个元素,元素存储上并不连续

2.分类

链表中还有一种特殊的节点称为哨兵结点,也叫哑元结点、首元结点,它不存储数据,通常用作头尾,用来化简边界判断,如下图所示

3.性能

(1)随机访问

根据index查找,时间复杂度O(n)

(2)插入或删除

起始位置:O(1)

结束位置:如果已至tail尾结点是O(1),不知道尾结点是O(n)

中间位置:根据index查找时间+O(1)

4.单向链表操作

(1)单向链表类的实现
 public class SinglyLinkedList{//整体
     private Node head;//头指针

     private class Node {//节点类
         int value;//值
         Node next;//下一个节点指针
         
         public Node(int value,Node next){
             this.value = value;
             this.next = next;
         }
     }
 }
(2)头部插入结点
     public void addFirst(int value){
//       //1.链表为空
//       head = new Node(value,null);
         //2.链表非空
         head = new Node(value,head);
     }
(3)链表遍历
     public void loop(){
         Node p = head;
         while (p != null){
             System.out.println(p.value);
             p = p.next;
         }
     }

(4)尾部插入结点
     private Node findLast(){//寻找最后一个结点
         if (head == null){//空链表
             return null;
         }
         Node p = head;
         while (p.next != null){
             p = p.next;
         }
         return p;
     }
     
     public void addList(int value){
         Node last = findLast();
         if (last == null){
             head = new Node(value,head);
             return;
         }
         last.next = new Node(value,null);
     }
(5)根据索引获取结点值
     public void test(){//寻找索引
         int i = 0;
         for (Node p = head;p != null;p = p.next,i++){
             System.out.println(p.value + "索引是:" + i);
         }
     }

     private Node findNode(int index){//查找结点
         int i = 0;
         for (Node p = head;p != null;p = p.next,i++){
             if (i == index){
                 return p;
             }
         }
         return null;  //没找到
     }

     //单独写,方便其他方法调用
     public int get(int index){
         Node node = findNode(index);
         if (node == null){
             throw new IllegalArgumentException(
                     String.format("index [%d] 不合法%n",index));
         }
         return node.value;
     }
(6)向索引位置插入
     public void insert(int index,int value){
         if (index == 0){
             addFirst(value);//向第一位插入
             return;
         }
         Node prev = findNode(index-1);//找到上一个节点
         if (prev == null){//找不到
             throw new IllegalArgumentException(
                     String.format("index [%d] 不合法%n",index));
         }
         prev.next = new Node(value,prev.next);
     }
(7)删除头部结点
     public void removeFirst(){
         if (head == null){
             throw new IllegalArgumentException(
                     String.format("index [0] 不合法%n"));
         }
         head = head.next;
     }
(8)根据索引删除结点
     public void remove(int index){
         if (index == 0){ //要删除的是头结点
             removeFirst();
             return;
         }

         Node prev = findNode(index-1);//上一个结点
         if (prev == null){  //链表最多只有索引3,要删除5号则找不到索引4
             throw new IllegalArgumentException(
                     String.format("index [%d] 不合法%n",index));
         }

         Node removed = prev.next; //被删除的结点
         if (removed == null){  //链表最多只有索引3,要删除4号
             throw new IllegalArgumentException(
                     String.format("index [%d] 不合法%n",index));
         }
         prev.next = removed.next;
     }

5.带哨兵的单向链表

(1)单向链表类的实现
 public class SinglyLinkedList{//整体
     private Node head = new Node(666,null); //哨兵,value可以随意制定

     private class Node {//节点类
         int value;//值
         Node next;//下一个节点指针
         
         public Node(int value,Node next){
             this.value = value;
             this.next = next;
         }
     }
 }
(2)链表遍历
     public void loop(){
         Node p = head.next;
         while (p != null){
             System.out.println(p.value);
             p = p.next;
         }
     }
(3)尾部插入结点
​
private Node findLast(){//寻找最后一个结点
      Node p = head; //若是空链表,则最后一个是哨兵
      while (p.next != null){
         p = p.next;
      }
         return p;
  }

public void addList(int value){
      Node last = findLast();//若为空,则直接插入哨兵后面
      last.next = new Node(value,null);
  }
 (4)查找结点对象
     private Node findNode(int index){//查找结点
         int i = -1;
         for (Node p = head;p != null;p = p.next,i++){
             if (i == index){
                 return p;
             }
         }
         return null;  //没找到
     }
 (5)向索引位置插入
     public void insert(int index,int value){//若index为0,在哨兵后插入
         Node prev = findNode(index-1);//找到上一个节点
         if (prev == null){//找不到
             throw new IllegalArgumentException(
                     String.format("index [%d] 不合法%n",index));
         }
         prev.next = new Node(value,prev.next);
     }
 (6)根据索引删除结点
     public void remove(int index){
         Node prev = findNode(index-1);//上一个结点
         if (prev == null){  //链表最多只有索引3,要删除5号则找不到索引4
             throw new IllegalArgumentException(
                     String.format("index [%d] 不合法%n",index));
         }

         Node removed = prev.next; //被删除的结点
         if (removed == null){  //链表最多只有索引3,要删除4号
             throw new IllegalArgumentException(
                     String.format("index [%d] 不合法%n",index));
         }
         prev.next = removed.next;
     }
  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值