从零实现单链表(增删查改)

本篇博客只是简单实现单链表(不带头节点),此类链表头节点会改变,面试遇到的会比较多。此外,只是简单的实现单链表,和原码有很大差距,目的是为了通过简单的实现单链表,对链表的各种操作更加熟悉。以便以后刷链表的题更加的得心应手。

目录

全部代码

MySIngleList

增删查改详解

遍历打印单链表

链表节点个数

头插法:

尾插法:

在指定位置插入节点

查看链表是否包含某个元素

 删除第一次出现关键字为key的节点

 删除所有值为key的节点

清空链表


全部代码

MySIngleList

public class MySingleList {
    //写一个内部类ListNode,表示单链表的节点
    static class ListNode{
        public int vale;//节点里面的值域
        public ListNode next;//节点里面放下一个节点的地址域
        //写一个构造方法
        public ListNode(int vale) {
            this.vale = vale;
        }
    }
    public ListNode head;//头节点

    //这里用比较low的方法先创建一个链表,以便学习。
    // 下面会写add方法,到时候可以拿add方法创建一个链表
    public void creatList(){
        ListNode list1 = new ListNode(20);
        ListNode list2 = new ListNode(22);
        ListNode list3 = new ListNode(10);
        ListNode list4 = new ListNode(01);
        list1.next = list2;
        list2.next = list3;
        list3.next = list4;
        this.head = list1;
    }
    //遍历打印单链表
    public void display(){
        ListNode cur = this.head;
        while(cur != null){
            System.out.print(cur.vale+" ");
            cur = cur.next;
        }
        System.out.println();
    }
    //链表节点个数
   public int size(){
        int count = 0;
       ListNode cur = this.head;
       while(cur != null){
           count++;
           cur = cur.next;
       }
       return count;
   }
    //头插法
   public void addFirst(int data){
        ListNode node = new ListNode(data);
        node.next = this.head;
        head = node;
    }
// 尾插法
   public void addLast(int data){
        ListNode node = new ListNode(data);
        if(head == null){
            head = node;
        }else{
            ListNode cur = this.head;
            while (cur.next != null){
                cur = cur.next;
            }
            cur.next = node;
        }
   }
   //任意位置插入,第一个数据节点为0号下标
  public void addIndex(int index,int data){
        if(index<0 || index > this.size()){
            throw new PosWrongFulException("index位置不合法");
        }
        if(index == 0){
            addFirst(data);
            return;
        }
        if(index == this.size()){
            addLast(data);
            return;
        }
        ListNode cur = findIndexSubOne(index);
        ListNode node = new ListNode(data);
        node.next = cur.next;
        cur.next = node;
  }
  private ListNode findIndexSubOne(int index){
        ListNode cur = this.head;
        while (index-1 != 0){
            cur = cur.next;
            index--;
        }
        return cur;
  }
    //查找是否包含关键字key是否在单链表当中
   public boolean conains(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.vale == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
   }
// 删除第一次出现关键字为key的节点
   public void remove(int key){
        if(head.vale == key){
            head = head.next;
            return;
        }
        ListNode cur = findPrevOfKey(key);
        if(cur == null){
            System.out.println("没有你要删除的值");
            return;
        }
        cur.next = cur.next.next;
   }
   private ListNode findPrevOfKey(int key){
        ListNode cur = head;
        while(cur.next != null){
            if(cur.next.vale == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
   }
// 删除所有值为key的节点
   public void removeAllKey(int key){
        ListNode pre = head;
        ListNode cur = head.next;
        while (cur != null){
            if(cur.vale == key){
                pre.next = cur.next;
                cur = cur.next;
            }else {
                pre = cur;
                cur = cur.next;
            }
        }
        if(head.vale == key){
            head = head.next;
        }
   }
   public void clear(){
        head = null;
   }
}

增删查改详解

遍历打印单链表

思路:创建一个cur代替head遍历这个链表,把里面的每个元素打印出来

代码

public void display(){
        ListNode cur = this.head;
        while(cur != null){
            System.out.print(cur.vale+" ");
            cur = cur.next;
        }
    }

这里while的终止条件是cur != null,而不是cur.next != null,是因为我们要打印每个节点里面的值。如果是cur.next!=null,最后一个节点不会被打印,且如果是空链表会空指针异常。

运行结果:

 (这里的creatList可以看上面写在一起的代码,就是用穷举的方法简单创建了一个单链表,很low,放下面辣)

public void creatList(){
        ListNode list1 = new ListNode(20);
        ListNode list2 = new ListNode(22);
        ListNode list3 = new ListNode(10);
        ListNode list4 = new ListNode(01);
        list1.next = list2;
        list2.next = list3;
        list3.next = list4;
        this.head = list1;
    }

链表节点个数

思路:和上面一样,创建一个count用来计数,遍历一下这个链表。

代码:

   //链表节点个数
   public int size(){
        int count = 0;
       ListNode cur = this.head;
       while(cur != null){
           count++;
           cur = cur.next;
       }
       return count;
   }

运行结果:

头插法:

思路

代码:

//头插法
   public void addFirst(int data){
        ListNode node = new ListNode(data);
        node.next = this.head;
        head = node;
    }

运行结果:

尾插法:

思路:

代码:

public void addLast(int data){
        ListNode node = new ListNode(data);
        if(head == null){
            head = node;
        }else{
            ListNode cur = this.head;
            while (cur.next != null){
                cur = cur.next;
            }
            cur.next = node;
        }
   }

 运行结果:

在指定位置插入节点

思路:

代码

public void addIndex(int index,int data){
        if(index<0 || index > this.size()){
            throw new PosWrongFulException("index位置不合法");
        }
        if(index == 0){
            addFirst(data);
            return;
        }
        if(index == this.size()){
            addLast(data);
            return;
        }
        ListNode cur = findIndexSubOne(index);
        ListNode node = new ListNode(data);
        node.next = cur.next;
        cur.next = node;
  }
  private ListNode findIndexSubOne(int index){
        ListNode cur = this.head;
        while (index-1 != 0){
            cur = cur.next;
            index--;
        }
        return cur;
  }

 PosWrongFulException

public class PosWrongFulException extends RuntimeException{
    public PosWrongFulException() {
    }

    public PosWrongFulException(String message) {
        super(message);
    }
}

运行结果:

查看链表是否包含某个元素

思路:遍历链表

代码:

public boolean conains(int key){
        ListNode cur = head;
        while(cur != null){
            if(cur.vale == key){
                return true;
            }
            cur = cur.next;
        }
        return false;
   }

运行结果:

 删除第一次出现关键字为key的节点

思路:

 假设我们现在要删除值为22这个节点,那么需要找到值为22的前一个节点,把它的next的域改为22这个节点next域指向的节点。我们可以写一个函数来找到前一个节点pre
pre.next = pre.next.next还要考虑如果删除的是头节点,则只需要把头节点指向头节点next域指向的节点:head = head.next;

代码

// 删除第一次出现关键字为key的节点
   public void remove(int key){
        if(head.vale == key){
            head = head.next;
            return;
        }
        ListNode cur = findPrevOfKey(key);
        if(cur == null){
            System.out.println("没有你要删除的值");
            return;
        }
        cur.next = cur.next.next;
   }
   private ListNode findPrevOfKey(int key){
        ListNode cur = head;
        while(cur.next != null){
            if(cur.next.vale == key){
                return cur;
            }
            cur = cur.next;
        }
        return null;
   }

运行结果:

 删除所有值为key的节点

思路:

 假设我现在要删除所有值为20的节点,我们需要2个ListNode变量,因为如果只定义一个 cur,那么如果是连续俩个都是20的节点在一起,就会漏删。原因是当我们把第一个20节点删掉后,cur必须向后走一步,如果此时cur指向的节点的值刚好还是20就删除不了了。

我们可以先判断cur的值是否等于20,如果等于:pre的next域指向cur的next域。cur继续往后走,如果不等于,pre指向cur,cur往后走。

为什么要等cur的值不等于20时再让pre指向cur,cur再往后走。是因为如果cur的值是20,cur需要删除。如果此时另pre = cur,那么pre就不是cur的前驱了。

最后我还需要判断头节点是否等于20,如果需要删除再把头节点删除。head = head.next

代码:

// 删除所有值为key的节点
   public void removeAllKey(int key){
        ListNode pre = head;
        ListNode cur = head.next;
        while (cur != null){
            if(cur.vale == key){
                pre.next = cur.next;
                cur = cur.next;
            }else {
                pre = cur;
                cur = cur.next;
            }
        }
        if(head.vale == key){
            head = head.next;
        }
   }

运行结果:

清空链表

思路:当节点没有对象引用时就会被回收。此时只需要另头结点为空就好。

代码:

public void clear(){
        head = null;
   }

运行结果

猜你喜欢

转载自blog.csdn.net/qq_62712350/article/details/127137725
今日推荐