单向链表基本操作(增删改查)

链表的基本操作

添加节点

默认添加到链表最后

 public void add(HeroNode heroNode){
        //因为头节点不能动  我们需要一个辅助变量Temp
        HeroNode temp = head;
        //遍历链表找到最后
        while (true){
            //找到链表最后
            if(temp.next==null){
                break;
            }
            //没有找到最后的时候Temp后移
            temp = temp.next;
        }
        temp.next = heroNode;
    }

按链表中的某个信息按顺序添加

示例中按照的是HeroNode中的no顺序添加

 public void addByOrder(HeroNode heroNode){
        //头节点不能动需要定义辅助变量
        //单链表,因此找的Temp是位于添加位置的前一个节点否则插入不了
        HeroNode temp = head;
        boolean flag = false;//标识所需要添加的编号是否存在默认为false
        while (true){
            if(temp.next == null){//说明此时temp在链表的最后
                break;
            }
            if(temp.next.no > heroNode.no){//位置找到就在temp的后面插入
                break;
            }
            else if(temp.next.no == heroNode.no){//该节点的编号已经存在
                flag = true;//说明编号存在System.out.println("该节点的编号已经存在");
                break;
            }
            temp = temp.next;
        }
        if(flag == true){
            System.out.println("准备插入的编号已经存在" + heroNode.no);
        }
        else {
            //可以插入
            heroNode.next = temp.next;
            temp.next = heroNode;
        }

    }

删除节点

示例中的根据节点的no来查找删除

public void deleteHeroNode(int no){
        //判断是否为空
        if(head.next == null){
            System.out.println("链表为空·····");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while (true){
            if(temp.next == null){
                //找到了链表的最后一个节点
                break;
            }

            if(temp.next.no == no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag){//找到需要删除的节点
            temp.next = temp.next.next;
        }
        else {
            System.out.println("需要删除的节点不存在");
        }
    }

    //显示链表遍历
    public void list(){
        //判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //头节点不能动  需要一个辅助变量来遍历
        HeroNode temp = head.next;
        while (true){
            if(temp == null){
                break;
            }
            //输出节点信息
            System.out.println(temp);
            //将next后移
            temp = temp.next;
        }
    }

修改链表中的信息

示例中根据节点的no来修改节点的信息

public void update(HeroNode newHeroNode){
        //判断是否为空
        if(head.next == null){
            System.out.println("链表为空·····");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while (true){
            if(temp == null){
                //找到了链表的最后一个节点
                break;
            }
            if (temp.no == newHeroNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //链表中没有
        if (flag){
            temp.name = newHeroNode.name;
            temp.nickname =newHeroNode.nickname;
        }
        else {
            System.out.println("没有找到编号为"+ newHeroNode.no + "的节点");
        }
    }

查看链表的详细信息

遍历链表打印即可

public void list(){
        //判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //头节点不能动  需要一个辅助变量来遍历
        HeroNode temp = head.next;
        while (true){
            if(temp == null){
                break;
            }
            //输出节点信息
            System.out.println(temp);
            //将next后移
            temp = temp.next;
        }
    }

具体的示例

package com.yc.day01.linkList;
/*
    @ClassName HeroNode
    @author cc
    @Date 2020-07-29 13:22
    @Version 1.0
    1.创建一个head头节点作用就是表示链表的头
    2.后面我们每添加一个节点直接就添加到链表的最后
    遍历
    1.
    顺序添加节点
    1.首先要找到新节点添加的位置 是通过辅助变量(指针) 通过遍历来确定
    2.新的节点的next域指向temp的next域
    3.将temp.next=新节点

    双向链表
    1.遍历和单向链表一样 不同:可以向前也可以先后查找
    2.添加(默认添加到双向链表的最后)
        1).先找到双向链表的最后节点
        2).temp.next = new heroNode
        3).newHeroNode.pro = temp
    3.修改  和单线链表思路一致
    4.删除
        1).双向链表 可以实现自我删除某个节点
        2).直接找到要删除的节点如:temp
        3).temp.pro.next = temp.next
        4).temp.next.pro = temp.pro
*/

import java.util.Stack;

public class SingleLinkedListDome {
    public static void main(String[] args) {
        //测试
        //创建节点
        HeroNode heroNode1 = new HeroNode(1, "宋江", "及时雨");
        HeroNode heroNode2 = new HeroNode(2,"卢俊义","玉麒麟");
        HeroNode heroNode3 = new HeroNode(3,"吴用","智多星");
        HeroNode heroNode4 = new HeroNode(4,"林冲","豹子头");
        //HeroNode newHeroNode = new HeroNode(4,"林冲","32145636524");

        //创建给链表
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        /*singleLinkedList.add(heroNode1);
        singleLinkedList.add(heroNode4);
        singleLinkedList.add(heroNode2);
        singleLinkedList.add(heroNode3);*/
        singleLinkedList.addByOrder(heroNode1);
        singleLinkedList.addByOrder(heroNode4);
        singleLinkedList.addByOrder(heroNode2);
        singleLinkedList.addByOrder(heroNode3);
        //singleLinkedList.addByOrder(heroNode3);
        //测试逆序打印单链表
        /*System.out.println("原来链表的情况-------------");
        singleLinkedList.list();
        System.out.println("逆序打印单链表-------------");
        reversePrint(singleLinkedList.getHead());*/

        singleLinkedList.deleteHeroNode(2);
        System.out.println("删除后链表的情况-------------");
        singleLinkedList.list();
        /*//测试单链表反转
        System.out.println("原来链表的情况");
        singleLinkedList.list();

        System.out.println("反转链表-------------------------");
        reverseList(singleLinkedList.getHead());
        singleLinkedList.list();*/

        /*System.out.println("-----------------------------");
        singleLinkedList.update(newHeroNode);
        singleLinkedList.list();

        System.out.println("----------------------");
        System.out.println("当前的的节点个数为"+getLength(singleLinkedList.getHead()));
        HeroNode res = findLastIndexNode(singleLinkedList.getHead(),2);
        System.out.println("倒数第"+res+"个节点");*/
    }

    //查找单链表的倒数第K个节点
    /*
    * 1.编写一个方法接收head节点 同时接收一个index
    * 2.index是表示倒数index节点
    * 3.把链表从头到尾遍历 得到链表的总长度 getLength
    * 4.得到Size后 从链表的第一个开始遍历(Size - Index)个就可以得到
    * 5.如果找到了就返回该节点  否则返回Null
    * */
    public static HeroNode findLastIndexNode(HeroNode head,int index){
        //判断链表是否为空
        if(head.next == null){
            return  null;
        }
        //遍历得到链表的长度
        int size =getLength(head);
        //第二次遍历  size-index 位置 就是我们需要的倒数第K个节点
        //先做一个数据校验
        if(index <= 0 || index>size){
            return  null;
        }
        //定义一个辅助变量使用for循坏定位到倒数第K个节点
        HeroNode cur = head.next;//指向第一个有效节点
        for(int i=0;i < size-index; i++){
            cur = cur.next;
        }
        return cur;

    }


    /*
    * 1.定义一个节点reverseHead = new HeroNode();
    * 2.从头遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表的最前端
    * 3.原来链表的Head.next = reverseHead.next
    * 4.
    * */
    //单链表反转
    public static void reverseList(HeroNode head){
        //如果当前的链表为空或者只有一个节点的无需反转直接放回
        if(head.next == null || head.next.next == null){
            return;
        }
        //定义一个辅助变量帮助我们遍历原来的链表
        HeroNode cur = head.next;
        HeroNode next =null;//指向当前节点cur的下一个节点
        HeroNode reverseHead = new HeroNode(0,"","");
        //遍历原来的链表每遍历一个节点就将其取出放在新链表reverseHead的最前端
        while (cur != null){
            next = cur.next;//保存当前节点的下一个节点 后面需要使用
            cur.next = reverseHead.next;//将cur的下一个节点指向新的链表的头部
            reverseHead.next = cur;//将cur连接到reverseHead链表上
            cur =cur.next;
        }
        //将head.next指向reverseHead.next 实现链表反转
        head.next = reverseHead.next;

    }
    //有效节点的个数
    public static int getLength(HeroNode head){
        //判断链表是否是空链表
        if(head.next == null){
            return 0;
        }
        int Length = 0;
        //不统计头节点
        HeroNode cur = head.next;
        while (cur != null){
            Length ++ ;
            cur = cur.next;
        }
        return Length;
    }
    /*
    * 逆序打印单链表
    * 方式一:将单链表反转之后打印单链表
    *       问题:会破坏原来单链表的结构
    * 方式二:利用栈这个数据结构将各个节点压入栈中
    *       然后利用栈先进后出的特点实现逆序打印
    * Stack 栈
    * */
    //使用方式二来实现
    public static  void reversePrint(HeroNode head){
        if(head.next == null){
            return; //空链表
        }
        //创建一个栈
        Stack<HeroNode> stack = new Stack<>();
        HeroNode cur =head.next;
        while (cur != null){
            stack.push(cur);
            cur = cur.next;
        }
        //将栈中的节点打印
        while (stack.size()>0){
            System.out.println(stack.pop());
        }
    }
}
//定义HeroNode ,每个HeroNode就是一个节点
class HeroNode{

    public int no;
    public String name;
    public String nickname;
    public HeroNode next;//指向下一个节点

    public HeroNode(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    //显示方便从写ToString
    @Override
    public String toString() {
        return "HeroNode{" +
                "no='" + no + '\'' +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }

}

class SingleLinkedList{
    //定义一个头节点 头节点不动
    private HeroNode head = new HeroNode
            (0,"","");
    //返回头节点
    public HeroNode getHead() {
        return head;
    }

    //添加节点方法
    //1.不考虑编号顺序
    //2.将最后的节点的next指向新节点
    public void add(HeroNode heroNode){
        //因为头节点不能动  我们需要一个辅助变量Temp
        HeroNode temp = head;
        //遍历链表找到最后
        while (true){
            //找到链表最后
            if(temp.next==null){
                break;
            }
            //没有找到最后的时候Temp后移
            temp = temp.next;
        }
        temp.next = heroNode;
    }

    //顺序添加节点的方式
    //根据对象里面的字段来进行排序插入(有重复的时候提示添加失败)
    public void addByOrder(HeroNode heroNode){
        //头节点不能动需要定义辅助变量
        //单链表,因此找的Temp是位于添加位置的前一个节点否则插入不了
        HeroNode temp = head;
        boolean flag = false;//标识所需要添加的编号是否存在默认为false
        while (true){
            if(temp.next == null){//说明此时temp在链表的最后
                break;
            }
            if(temp.next.no > heroNode.no){//位置找到就在temp的后面插入
                break;
            }
            else if(temp.next.no == heroNode.no){//该节点的编号已经存在
                flag = true;//说明编号存在System.out.println("该节点的编号已经存在");
                break;
            }
            temp = temp.next;
        }
        if(flag == true){
            System.out.println("准备插入的编号已经存在" + heroNode.no);
        }
        else {
            //可以插入
            heroNode.next = temp.next;
            temp.next = heroNode;
        }

    }
    //修改节点,根据编号来修改
    public void update(HeroNode newHeroNode){
        //判断是否为空
        if(head.next == null){
            System.out.println("链表为空·····");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while (true){
            if(temp == null){
                //找到了链表的最后一个节点
                break;
            }
            if (temp.no == newHeroNode.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }

        //链表中没有
        if (flag){
            temp.name = newHeroNode.name;
            temp.nickname =newHeroNode.nickname;
        }
        else {
            System.out.println("没有找到编号为"+ newHeroNode.no + "的节点");
        }
    }
    //删除节点
    /*
    1.先找到需要删除的这个节点的前一个节点temp
    2.temp.next = temp.next.next
    3.被删除的节点将不会有其他应用会被垃圾回收机制回收
    * */
    public void deleteHeroNode(int no){
        //判断是否为空
        if(head.next == null){
            System.out.println("链表为空·····");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while (true){
            if(temp.next == null){
                //找到了链表的最后一个节点
                break;
            }

            if(temp.next.no == no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag){//找到需要删除的节点
            temp.next = temp.next.next;
        }
        else {
            System.out.println("需要删除的节点不存在");
        }
    }

    //显示链表遍历
    public void list(){
        //判断链表是否为空
        if (head.next == null){
            System.out.println("链表为空");
            return;
        }
        //头节点不能动  需要一个辅助变量来遍历
        HeroNode temp = head.next;
        while (true){
            if(temp == null){
                break;
            }
            //输出节点信息
            System.out.println(temp);
            //将next后移
            temp = temp.next;
        }
    }
}



单向链表是由若干个节点组成的,每个节点都包含一个数据域和一个指向下一个节点的指针域。在单向链表中,只能从头节点开始遍历链表,每个节点只能访问其后继节点。下面是用单向链表实现增删改查的代码实现: ```python # 定义单向链表节点类 class ListNode: def __init__(self, val): self.val = val self.next = None # 定义单向链表类 class LinkedList: def __init__(self): self.head = None # 添加节点 def add_node(self, val): new_node = ListNode(val) if not self.head: self.head = new_node else: curr = self.head while curr.next: curr = curr.next curr.next = new_node # 删除节点 def delete_node(self, val): if not self.head: return if self.head.val == val: self.head = self.head.next else: curr = self.head while curr.next: if curr.next.val == val: curr.next = curr.next.next return curr = curr.next # 修改节点 def update_node(self, old_val, new_val): curr = self.head while curr: if curr.val == old_val: curr.val = new_val return curr = curr.next # 查找节点 def search_node(self, val): curr = self.head while curr: if curr.val == val: return True curr = curr.next return False ``` 在上面的代码中,我们定义了一个单向链表节点类 ListNode ,包含一个数据域 val 和一个指向下一个节点的指针域 next 。然后定义了单向链表类 LinkedList ,包含一个头节点 head 。在 LinkedList 中,我们实现了 add_node() 方法用于添加节点,delete_node() 方法用于删除节点,update_node() 方法用于修改节点,search_node() 方法用于查找节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值