两条单链表,插入同一个节点,为什么出现错误?

  两条单链表分别插入同一个节点,分别打印两链表中的元素,发现和预期不一样。我的代码如下:

 1        HeroNode h1=new HeroNode(1,"宋江","及时雨");
 2         HeroNode h2=new HeroNode(2,"卢俊义","玉麒麟");
 3         HeroNode h3=new HeroNode(3,"吴用","智多星");
 4         HeroNode h4=new HeroNode(4,"林冲","豹子头");
 5 
 6         //创建链表
 7         SingleLinkedList sll1=new SingleLinkedList();
 8         SingleLinkedList sll2=new SingleLinkedList();
 9 
10       //按编号顺序插入h1和h4
11         sll1.addByOrder(h1);
12         sll1.addByOrder(h4);
13       
14         sll2.addByOrder(h1);

  结果如下:

两条单链表,插入同一个节点,为什么出现错误?

   我改一下代码,sll2不添加h1了,添加h2,h3:

 1         HeroNode h1=new HeroNode(1,"宋江","及时雨");
 2         HeroNode h2=new HeroNode(2,"卢俊义","玉麒麟");
 3         HeroNode h3=new HeroNode(3,"吴用","智多星");
 4         HeroNode h4=new HeroNode(4,"林冲","豹子头");
 5 
 6         //创建链表
 7         SingleLinkedList sll1=new SingleLinkedList();
 8         SingleLinkedList sll2=new SingleLinkedList();
 9 
10         sll1.addByOrder(h1);
11         sll1.addByOrder(h4);
12 
13         //sll2.addByOrder(h1);
14         sll2.addByOrder(h2);
15         sll2.addByOrder(h3);

  结果又变正常了!

两条单链表,插入同一个节点,为什么出现错误?

  HeroNode代码如下:

两条单链表,插入同一个节点,为什么出现错误?
 1 class HeroNode {
 2     public int no;
 3     public String name;
 4     public String nickName;
 5     public HeroNode next;
 6 
 7     public HeroNode(int no,String name,String nickName){
 8         this.no=no;
 9         this.name=name;
10         this.nickName=nickName;
11     }
12 
13     @Override
14     public String toString() {
15         return "HeroNode{" +
16                 "no=" + no +
17                 ", name='" + name + '\'' +
18                 ", nickName='" + nickName + '\'' +
19                 '}';
20     }
21 }
View Code

  

  SingleLinkedList代码如下:

两条单链表,插入同一个节点,为什么出现错误?
class SingleLinkedList {
    public HeroNode head=new HeroNode(0,null,null);

    //添加结点
    public void addElement(HeroNode hero){
        //使用辅助变量来遍历链表
        HeroNode temp=head;
        while(temp.next!=null){
            temp=temp.next;
        }
        temp.next=hero;
    }

    //按英雄顺序添加结点,如果已经有了,则添加失败
    public void addByOrder(HeroNode hero){
        //因为头节点不能动,所以我们通过辅助变量来帮助找到添加的位置
        HeroNode temp=head;
        boolean flag=false;
        while(true){
            if(temp.next==null){  //遍历完整个链表,插入节点应该是最后一个节点
                break;
            }
            if(temp.next.no>hero.no){  //找到添加位置,在temp后,temp.next前
                break;
            }else if(temp.next.no== hero.no){  //已有此节点
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if(flag){
            System.out.printf("已有编号为%d的节点,无法添加!\n",hero.no);
        }else {
            hero.next=temp.next;
            temp.next=hero;
        }
    }

    //修改结点,如果没找到,则修改失败
    public void update(HeroNode hero){
        HeroNode temp=head;
        boolean flag=true;  //true代表需要修改
        while(true){
            if(temp.next==null){
                flag=false;
                break;
            }
            if(temp.next.no==hero.no){  //temp.next为修改的位置
                break;
            }
            temp=temp.next;
        }
        if(flag){
            temp.next.name=hero.name;
            temp.next.nickName=hero.nickName;
        }else {
            System.out.printf("没有找到编号为%d的节点,无法修改!\n",hero.no);
        }
    }

    //删除节点,如果没找到,则删除失败
    public void delete(int no){
        HeroNode temp=head;
        boolean flag=true;  //true代表可以删除
        while(true){
            if (temp.next==null){  //没有找到要删除的节点
                flag=false;
                break;
            }
            if(temp.next.no==no){  //删除的节点为temp.next
                break;
            }
            temp=temp.next;
        }
        if(flag){
            temp.next=temp.next.next;
        }else {
            System.out.printf("没有找到编号为%d的节点,无法删除!\n",no);
        }
    }

    //输出链表
    public void list(){
        if(head.next==null){
            System.out.println("链表为空!");
        }
        HeroNode temp=head.next;
        while(temp!=null){
            System.out.println(temp);
            temp=temp.next;
        }
    }

    //获取单链表有效节点个数
    public int length(){
        int count=0;
        HeroNode temp=head;
        while(temp.next!=null){
            temp=temp.next;
            count++;
        }
        return count;
    }

    //查找倒数第k个节点:先遍历一次,求出链表长度,再遍历(length()-k+1)次得到该节点
    public HeroNode findTheLastK(int k){
        HeroNode temp=head;
        if(length()==0){
            throw new RuntimeException("链表为空,查找异常!");
        }
        if(k>length()){
            throw new RuntimeException("查找倒数第"+k+"个节点异常:查找节点编号超出链表长度!");
        }
        for(int i=0;i<(length()-k+1);i++){
            temp=temp.next;
        }
        return temp;
    }

    //反转单链表:遍历原链表,把每一个节点都头插到新链表上,再把head.next指向新链表的第一个元素节点
    public void reverse(){
        //如果为空或只有一个,不需要反转
        if(head.next==null || head.next.next==null){
            return;
        }
        HeroNode temp=head.next;
        HeroNode reverseHead=new HeroNode(0,null,null);
        HeroNode node=null;
        while(temp!=null){
            //用node暂存temp.next
            node=temp.next;

            //把temp头插到reverseHead
            temp.next=reverseHead.next;
            reverseHead.next=temp;

            //移动指针
            temp=node;
        }
        head.next=reverseHead.next;
    }

    //逆序打印:(不建议先反转再打印,会改变原来的链表)遍历链表,把每个节点压入栈中,出栈打印,链表结构不改变
    public void reversePrint(){
        if(head.next==null){
            System.out.println("链表为空,无法逆序打印!");
            return;
        }
        HeroNode temp=head.next;
        HeroNode node=null;
        Stack<HeroNode> stack=new Stack<>();
        while(temp!=null){
            //保存temp.next,以免链表丢失
            node=temp.next;

            //压入栈中
            stack.push(temp);

            temp=temp.next;
        }
        while(!stack.isEmpty()){
            System.out.println(stack.pop());
        }
    }

    //有序合并两个单链表
    public void combineList(SingleLinkedList linkedList){
        HeroNode anotherHead=linkedList.head;
        if(anotherHead.next==null){
            return;
        }
        HeroNode temp=anotherHead.next;
        HeroNode node=null;
        while(temp!=null){
            //保存temp2.next,以免丢失链表
            node=temp.next;
            //按顺序插入
            addByOrder(temp);
            temp=node;
        }
    }
}
View Code

 

  为什么会出现这个结果呢?

 

  在sll1中插入h1、h4之后,此时sll1链表:head-->h1-->h4-->null。h1的next指向h4!

 

  在sll2添加h1的时候,实际上并不止是添加h1,而是添加h1-->h4-->null这条链!

 

  SingleLinkedList里的addByOrder()执行后,sll2:head-->h1-->null,而sll1的head指向h1,sll1也会变成:head-->h1-->null!

 

  如果单链表里面的元素,不是引用类型,而是基本数据类型呢?是否会出现这种情况呢?答案是不会!

  

 

上一篇:认知网络知识点及例题总结


下一篇:2021-01-03