java实现链表的增删改查

本文详细介绍了如何使用Java实现单链表的常见操作,包括在链表头部和中间位置插入元素、查找指定位置的元素、检查元素是否存在、修改链表中的值、按索引和值删除元素。提供了完整的代码实现,包括节点类Node和单链表类SingleLinkedList,以及相关方法的逻辑解析。
摘要由CSDN通过智能技术生成

1.链表的增加

1.1 链表头部增加addFirst(int val)

  • 先创建节点 Node node = new node(val);
  • 判断头部是否为空,若为空,head=node;头部不为空,让新建的节点指向头部,node.next=head;头指针再指向新建节点head=node;
    注意:如果不清除指向的先后顺序,可以画图帮助判断。如若各种指向顺序都不行,建立临时变量
    public void addFirst(int val){
        // 先创建需要挂载的车厢节点
        Node node =new Node(val);
        // 判断火车头部是否为空
        if (head==null){
            head=node;
        }
        // 火车有节点,要将当前新车厢挂载到火车头节点上
        else{
            // 新车厢指向head头节点
            node.next=head;
            // 新的头节点再指向之前的头节点
            head=node;
        }
        size++;
    }

1.2 链表中间位置插入addIndex(int index,int val)

  • 首先判断索引的合法性(index<0 || index>size)非法
  • 若index=0为头部插入
  • index在中间位置(核心是找到插入位置的前驱节点)
    例如将7插入到index为1的位置,先让7指向插入位置,再让它的前驱节点指向它。
    前驱节点怎样找?
    用for循环遍历找到prev位置在这里插入图片描述
    public void addIndex(int index,int val){
        // 判断合法性
        if (index<0 || index>size){
            System.out.println("error");
            return;
        }
        if (index==0){
            addFirst(val);
            return;
        }
        // 插入元素,先创建
        Node node =new Node(val);
        // 找插入位置的前驱节点,先让前驱节点为头节点,在遍历向后走index-1步
        Node prev=head;
        for (int i = 0; i < index-1; i++) {
            prev=prev.next;
        }
        node.next=prev.next;
        prev.next=node;
        size++;
    }

2.链表的查找

  • get(int index)返回index位置的元素值
  • contains(int value) 查询值为value的元素在单链表中是否存在,存在返回true,否则返回false;

2.1 get(int index)

先判断index合法性(index<0 || index>=size)非法,此处index不能=size,因为size位置无元素

public int get(int index){
        // 合法性校验  rangecheck(index)为index合法性检测的方法
        if (rangecheck(index)){
            Node node=head;
            // 规定了node节点走了多少步
            for (int i = 0; i < index; i++) {
                node=node.next;
            }
            return node.val;
        }else{
            System.out.println("error");
            return -1;
        }
    }

2.2 contains(int value)

 public boolean contains(int val){
      Node temp=head;
      while(temp!=null){
          if (temp.val==val){
              return true;
          }
          temp=temp.next;
      }
      return false;
    }

3.链表的修改set(int index,int newval)

    // 修改链表index位置的元素值,返回修改前的值
    public int set(int index,int newval){
        if (rangecheck(index)){
            Node node=head;
            for (int i = 0; i < index; i++) {
                node=node.next;
            }
            int oldval=node.val;
            node.val=newval;
            return oldval;
        }else{
            System.out.println("error");
            return -1;
        }
    }

4.链表的删除

4.1 利用索引删除链表元素

例如删除3这个节点,先让3的前驱节点指向3的下一个节点,再让3指向5的线断掉
在这里插入图片描述

    public void removeindex(int index){
        if (rangecheck(index)){
            // 删除头节点
            if (index==0){
                Node temp=head;
                head=head.next;
                temp.next=null;
                size--;
            }else{
                // index是中间位置
                // 找到待删除节点的前驱节点
                Node prev =head;
                for (int i = 0; i < index-1; i++) {
                    prev=prev.next;
                }
                // 待删除节点
                Node cur=prev.next;
                prev.next=cur.next;
                cur.next=null;
                size--;
            }
        }
    }
    // 删除头部
    public void removeFirst(){
        removeindex(0);
    }
    //  // 删除尾部
    public void removeLast(){
        removeindex(size-1);
    }

4.2 利用元素值删除链表元素

removeValue(int value)
removeValueAll(int value)

 public void removeValueOnce(int val){
        // 遍历链表找到值为val的节点
        // 找到后删除
        if (head!=null&&head.val==val){
            // 头节点为待删除的节点
            Node temp=head;
            head=head.next;
            temp.next=null;
            size--;
        }else{
            // 头节点不是待删除的节点,此时需要找到待删除节点的前驱节点
           Node prev=head;
           // 判断前驱节点的下一个节点值是否是val
            while(prev.next!=null){
                if(prev.next.val==val){
                    Node cur=prev.next;
                    // cur是待删除的节点
                    prev.next=cur.next;
                    cur.next=null;
                    size--;
                    return;
                }
                prev=prev.next;
            }
        }
    }
 public void removeValueAll(int val){
   // 头节点就是待删除的节点
        while (head!=null&&head.val==val){
            head=head.next;
            size--;
        }
        if(head==null){
            // 链表中全是待删除的元素
            return;
        }else{
            // head不是待删除的节点
            Node prev=head;
            while(prev.next!=null){
                if (prev.next.val==val){
                    Node cur=prev.next;
                    prev.next=cur.next;
                    cur.next=null;
                    size--;
                }else{
                    prev=prev.next;
                }
            }
        }
    }

5 完整代码

package seqlist;
// 火车类,里面包含多个车厢和第一个车厢的地址
public class SingleLinkedList {
    // 车厢的节点个数
    private int size;
    // 火车头节点
    private Node head;
    // 火车头部添加元素
    public void addFirst(int val){
        // 先创建需要挂载的车厢节点
        Node node =new Node(val);
        // 判断火车头部是否为空
        if (head==null){
            head=node;
        }
        // 火车有节点,要将当前新车厢挂载到火车头节点上
        else{
            // 新车厢指向head头节点
            node.next=head;
            // 新的头节点再指向之前的头节点
            head=node;
        }
        size++;
    }
    public void addIndex(int index,int val){
        // 判断合法性
        if (index<0 || index>size){
            System.out.println("error");
            return;
        }
        if (index==0){
            addFirst(val);
            return;
        }
        // 插入元素,先创建
        Node node =new Node(val);
        // 找插入位置的前驱节点,先让前驱节点为头节点,在遍历向后走index-1步
        Node prev=head;
        for (int i = 0; i < index-1; i++) {
            prev=prev.next;
        }
        node.next=prev.next;
        prev.next=node;
        size++;
    }
    public void addLast(int val){
        addIndex(size,val);
    }
    public int get(int index){
        // 合法性校验
        if (rangecheck(index)){
            Node node=head;
            // 规定了node节点走了多少步
            for (int i = 0; i < index; i++) {
                node=node.next;
            }
            return node.val;
        }else{
            System.out.println("error");
            return -1;
        }
    }

    public boolean contains(int val){
      Node temp=head;
      while(temp!=null){
          if (temp.val==val){
              return true;
          }
          temp=temp.next;
      }
      return false;
    }
    // 修改链表index位置的元素值,返回修改前的值
    public int set(int index,int newval){
        if (rangecheck(index)){
            Node node=head;
            for (int i = 0; i < index; i++) {
                node=node.next;
            }
            int oldval=node.val;
            node.val=newval;
            return oldval;
        }else{
            System.out.println("error");
            return -1;
        }
    }
// 利用索引删除链表元素
    public void removeindex(int index){
        if (rangecheck(index)){
            // 删除头节点
            if (index==0){
                Node temp=head;
                head=head.next;
                temp.next=null;
                size--;
            }else{
                // index是中间位置
                // 找到待删除节点的前驱节点
                Node prev =head;
                for (int i = 0; i < index-1; i++) {
                    prev=prev.next;
                }
                // 待删除节点
                Node cur=prev.next;
                prev.next=cur.next;
                cur.next=null;
                size--;
            }
        }
    }
    // 删除头部
    public void removeFirst(){
        removeindex(0);
    }
    //  // 删除尾部
    public void removeLast(){
        removeindex(size-1);
    }
    //
    public void removeValueOnce(int val){
        // 遍历链表找到值为val的节点
        // 找到后删除
        if (head!=null&&head.val==val){
            // 头节点为待删除的节点
            Node temp=head;
            head=head.next;
            temp.next=null;
            size--;
        }else{
            // 头节点不是待删除的节点,此时需要找到待删除节点的前驱节点
           Node prev=head;
           // 判断前驱节点的下一个节点值是否是val
            while(prev.next!=null){
                if(prev.next.val==val){
                    Node cur=prev.next;
                    // cur是待删除的节点
                    prev.next=cur.next;
                    cur.next=null;
                    size--;
                    return;
                }
                prev=prev.next;
            }
        }
    }
    public void removeValueAll(int val){
   // 头节点就是待删除的节点
        while (head!=null&&head.val==val){
            head=head.next;
            size--;
        }
        if(head==null){
            // 链表中全是待删除的元素
            return;
        }else{
            // head不是待删除的节点
            Node prev=head;
            while(prev.next!=null){
                if (prev.next.val==val){
                    Node cur=prev.next;
                    prev.next=cur.next;
                    cur.next=null;
                    size--;
                }else{
                    prev=prev.next;
                }
            }
        }
    }
    // 索引合法性检测,改,查,删除
    private boolean rangecheck(int index){
        // 判断合法性
        if (index<0 || index>=size){
            return false;
        }
        else{
            return true;
        }
    }

    public String toString(){
        String ret="";
        // 遍历火车类,从头走到尾
        // node暂时存放当前头节点,相当于临时变量
        Node node=head;
        while(node!=null){
            ret += node.val;
            ret += "->";
            // node走向下一个节点
            node =node.next;
        }
        ret += "NULL";
        return ret;

    }
}
// 车厢类
class Node{
    // 存储每个车厢存放的数据
    int val;
    //下个车厢的节点
    Node next;

    public Node(int val) {
        this.val=val;
    }
}

package seqlist;

public class Test {
    public static void main(String[] args) {
        // 使用火车类,创建火车类对象
        SingleLinkedList singleLinkedList=new SingleLinkedList();
        singleLinkedList.addFirst(1);
        singleLinkedList.addFirst(3);
        singleLinkedList.addFirst(5);
        //5->3->1->NULL
        System.out.println(singleLinkedList);
        singleLinkedList.addIndex(1,10);
        //5->10->3->1->NULL
        System.out.println(singleLinkedList);
        //3
        System.out.println(singleLinkedList.get(2));
        // false
        System.out.println(singleLinkedList.contains(2));
        // true
        System.out.println(singleLinkedList.contains(10));
        //10
        System.out.println(singleLinkedList.set(1,7));
        //5->7->3->1->NULL
        System.out.println(singleLinkedList);
        singleLinkedList.removeindex(1);
        //5->3->1->NULL
        System.out.println(singleLinkedList);
        singleLinkedList.removeFirst();
        //3->1->NULL
        System.out.println(singleLinkedList);
        singleLinkedList.removeLast();
        //3->NULL
        System.out.println(singleLinkedList);
        singleLinkedList.addFirst(3);
        singleLinkedList.addFirst(5);
        //5->3->3->NULL
        System.out.println(singleLinkedList);
        singleLinkedList.removeValueOnce(3);
        //5->3->NULL
        System.out.println(singleLinkedList);
        singleLinkedList.addFirst(3);
        singleLinkedList.addFirst(3);
        singleLinkedList.addFirst(3);
        singleLinkedList.removeValueAll(3);
        //5->NULL
        System.out.println(singleLinkedList);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值