【数据结构与算法】单向链表与双向链表的增删改查(包括有序插入到链表)

单向链表

1、链表是以节点的方式来存储,是链式存储
2、每个节点包含data域,next域:指向下一个节点
3、链表的每个节点不一定是连续存储
4、链表分带头节点的链表和没有头节点链表,根据需求确定
在这里插入图片描述

1、遍历

通过一个辅助遍历,帮助遍历整个链表

2、添加(创建)

(1)先创建一个head头节点,作用就是表示单链表的头
(2)后面每添加一个节点,就直接加入到链表的最后

添加有俩种形式,一种是直接添加到链表的尾部,一种是根据顺序添加到链表(比如链表中已经有了1,3,那么添加一个2时就放到1和3之间)

3、修改

(1)先找到该节点,通过遍历
(2)temp.name=newHeroNode.name

4、删除

(1)找到需要删除的这个节点的前一个节点temp
(2)temp.net=temp.next.next
(3)被删除的节点,将不会有其他引用指向,会被垃圾回收机制回收

5、实现代码

class SingleLinkedList{
    private HeroNode head=new HeroNode(0,"","");

    public HeroNode getHead() {
        return head;
    }

    //直接添加到尾部
    public void addHero(HeroNode heroNode){
        HeroNode temp=head;
        while (true){
            //找到链表的最后
            if(temp.next==null){
                break;
            }
            //链表没有到最后,则temp后移
            temp=temp.next;
        }
        temp.next=heroNode;
    }

    //根据顺序添加
    public void addHeroByOrder(HeroNode heroNode){
        HeroNode temp=head;
        boolean flag=false;
        while (true){
            if(temp.next==null){
                break;
            }
            if(temp.next.no>heroNode.no){
                break;
            }else if(temp.next.no==heroNode.no){
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if(flag){
            System.out.printf("准备插入的英雄编号%d已经存在,不能加入\n",heroNode.no);
        }else {
            heroNode.next=temp.next;
            temp.next=heroNode;
        }
    }

    //修改
    public void updateHero(HeroNode newHeroNode){
        HeroNode temp=head.next;
        if(temp==null){
            System.out.println("链表为空");
            return;
        }
        //表示是否找到该节点
        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.printf("没有找到编号%d的节点",newHeroNode.no);
        }
    }
    //删除
    public void delHero(int no){
        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.printf("要删除的%d节点不存在\n",no);
        }
    }

    public void showHero(){
        if(head.next==null){
            System.out.println("链表为空");
            return;
        }
        HeroNode temp=head.next;
        while (true){
            if(temp==null){
                break;
            }
            System.out.println(temp);
            temp=temp.next;
        }
    }
}
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;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname +
//                ", next=" + next +
                '}';
    }
}

双向链表

1、遍历

遍历和单链表一样,通过一个辅助遍历,帮助遍历整个链表,只是可以向前,也可以向后

2、添加

(1)先找到双向链表的最后这个节点
(2)temp.next=newHeroNode
(3)newHeroNode.pre=temp

添加有俩种形式,一种是直接添加到链表的尾部,一种是根据顺序添加到链表(比如链表中已经有了1,3,那么添加一个2时就放到1和3之间)

3、修改

与单向链表一样
(1)先找到该节点,通过遍历
(2)temp.name=newHeroNode.name

4、删除

(1)可以实现自我删除某个节点
(2)直接找到要删除的这个节点,比如temp
(3)temp.pre.next=temp.next
(4)temp.next.pre=temp.pre

5、代码实现

class DoubleLinkedList{
    private HeroNode2 head=new HeroNode2(0,"","");
    public HeroNode2 getHead(){return head;}
    //添加
    public void addHero(HeroNode2 heroNode){
        HeroNode2 temp=head;
        while (true){
            if (temp.next==null){
                break;
            }
            temp=temp.next;
        }
        temp.next=heroNode;
        heroNode.pre=temp;
    }

    //根据排名添加
    public void addHeroByOrder(HeroNode2 heroNode){
        HeroNode2 temp=head;
        boolean flag=false;
        while (true){
            if(temp.next==null){
                break;
            }
            if(temp.next.no>heroNode.no){
                break;
            }else if(temp.next.no==heroNode.no){
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if(flag){
            System.out.printf("准备插入的英雄编号%d已经存在,不能加入\n",heroNode.no);
        }else {
            if(temp.next!=null){
                heroNode.next=temp.next;
                temp.next.pre=heroNode;
            }
            temp.next=heroNode;
            heroNode.pre=temp;

        }
    }

    //修改
    public void updateHero(HeroNode2 newHeroNode){
        HeroNode2 temp=head.next;
        if(temp==null){
            System.out.println("链表为空");
        }
        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.printf("没有找到编号%d节点",newHeroNode.no);
        }

    }
    //删除
    public void delHero(int no){
        if(head.next==null){
            System.out.println("链表为空");
            return;
        }
        HeroNode2 temp=head.next;
        boolean flag=false;
        while (true){
            if(temp==null){
                break;
            }
            if(temp.no==no){
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if (flag){
            temp.pre.next=temp.next;
            if(temp.next!=null){
                temp.next.pre=temp.pre;
            }
        }else{
            System.out.printf("要删除的%d节点不存在\n",no);
        }
    }

    //显示
    public void showHero(){
        if(head.next==null){
            System.out.println("链表为空");
            return;
        }
        HeroNode2 temp=head.next;
        while (true){
            if (temp==null){
                break;
            }
            System.out.println(temp);
            temp=temp.next;
        }
    }

}
class HeroNode2{
    public int no;
    public String name;
    public String nickname;
    public HeroNode2 next;
    public HeroNode2 pre;
    public HeroNode2(int no,String name,String nickname){
        this.no=no;
        this.name=name;
        this.nickname=nickname;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname +
//                ", next=" + next +
                '}';
    }
}

单向链表与双向链表的比较

1.单向链表,查找的方向只能是一个方向,
而双向链表可以向前或者向后查找
2.单向链表不能自我删除,需要靠辅助节点,
而双向链表可以自我删除

原创文章 255 获赞 116 访问量 19万+

猜你喜欢

转载自blog.csdn.net/cxh6863/article/details/104799231