java对链表(环、交叉链表的应用)

本文详细介绍了一个Java实现的链表类,包括链表的基本操作如头插法创建、判断是否有环、寻找环的入口节点及计算环内节点数量、查找两链表相交节点和返回倒数第K个节点的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在链表中,有环链表,交叉链表,返回倒数第k个节点可谓非常经典,所以对java的实现做总结如下:
1、首先定义一个链表节点的类Node;

class Node{
    int value;
    Node next;
    public Node(){
        this(0);//注意调用时必须处在构造方法的第一行
    }
    public Node(int val){
        this.value=val;
        this.next=null;
    }
}

2、在类LinkList中实现链表的头插创建 ,判环,求倒数第K个节点,以及判断两链表是否相交

class LinkList{
    Node head;
    public LinkList(){
        this.head=new Node();//调用Node的第一个构造方法
    }
    public void insertHead(int val){ //头插法
        Node n=new Node(val);
        n.next=this.head.next;
        head.next=n;
    }
    public boolean haveCircle(){//判断有环的思路为两个节点,fast走两步,slow走一步,若fast和slow最终相等,则证明有环,否则不会相等
        if(head==null)return false;
        Node fast=head;
        Node slow=head;
        while(fast.next!=null && fast.next.next!=null){
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow){
                break;
            }
        }
        if(fast==slow)return true;
        else return false;
    }
    public Node firstCircleNode(){   //碰撞点到入口点的距离等于head到入口点的距离
        if(!this.haveCircle())return null;
        Node fast=head.next.next;
        Node slow=head.next;
        while(fast!=slow){
            fast=fast.next.next;
            slow=slow.next;
        }
        Node p=head;
        while(p!=slow){
            p=p.next;
            slow=slow.next;
        }
        return p;
    }
    public int getCircleNodeNum(){//第一次相交与第二次相交slow所走过的节点个数;
        if(!this.haveCircle())return 0;//如果没有环则返回0;
        Node fast=head.next.next;
        Node slow=head.next;
        Node f1=null;Node f2=null;
        int count=0;
        while(f1==null || f2==null){
            if(fast==slow && f1!=null){
                f2=fast;
            }
            if(fast==slow && f1==null){
                f1=fast;
            }
            if(f1!=null && f2==null){
                count ++;
            }
            fast=fast.next.next;
            slow=slow.next;
        }
        return count;
    }
    private int listNode(LinkList list){//私有方法用来返回链表的节点数
        int n=-1;
        Node p=list.head;
        while(p!=null){
            p=p.next;
            n+=1;
        }
        return n;
    }
    private Node LinkCross(LinkList list){//分别求出两个链表的个数,让个数多的先走k(多的个数)步
        Node p=this.head;//两链表相交,则从交点处汇聚为一条链
        Node q=list.head;
        if(p==null || q==null)return null;
        int np=listNode(this);
        int nq=listNode(list);
        int n=np-nq;
        while(n>0){
            p=p.next;
            n--;
        }
        while(n<0){
            q=q.next;
            n++;
        }
        while(p!=null || q!=null){
            if(p==q)break;
            p=p.next;q=q.next;
        }
        if(p==q)return p;
        else return null;
    }
    public boolean isLinkCross(LinkList list){//判断是否相交
       Node p=LinkCross(list);  
       if(p==null)return false;
       else return true;
    }
    public Node LinkNode(LinkList list){
        return LinkCross(list);
    }
    public Node findReverseKNode(int k){//返回倒数第K个节点时间复杂度为O(n)
        int n=listNode(this);
        if(n<k)return null;
        Node f=head;
        Node s=head;
        while(k>0){
            f=f.next;
            k--;
        }
        while(f!=null){
            f=f.next;
            s=s.next;
        }
        return s;
   }
    public String toString(){
        StringBuilder builder=new StringBuilder();
        if(haveCircle())return "链表有环";
        Node n=head;
        while(n.next!=null){
            builder.append(n.next.value+" ");
            n=n.next;
        }
        return builder.toString();
    }
    public LinkList createList(){ //随机生成单链表
        LinkList L=new LinkList();
        for(int i=0;i<10;i++){
            L.insertHead((int)(Math.random()*10));
        }
        return L;
    }
    public LinkList createCircleList(){  //随机生成带环链表
        LinkList L=createList();
        Random r=new Random();
        int k=r.nextInt(10);
        //System.out.printf("环的入口节点为第%d个\n",k);
        Node p=L.head;
        Node q=L.head;
        while(p.next!=null){
            if(k==0)q=p.next;//随机环的入口节点
            k--;
            p=p.next;
        }
        p.next=q;//链接形成环;
        return L;
    }
    public void createLink(LinkList List){
        Node p=head;
        while(p.next!=null){
            p=p.next;
        }
        p.next=List.head.next;
    }
}

3、在主函数中对各种方法进行调用检测

public class TLinkList {
    public static void main(String [] args) {
        LinkList L=new LinkList();
      LinkList L1=L.createList();
      LinkList L2=L.createCircleList();
      System.out.println("判断L1链表是否有环:"+L1.haveCircle());
      System.out.println("判断L2链表是否有环:"+L2.haveCircle());
      System.out.println("有环链表的入口点的value值为:"+(L2.firstCircleNode()).value);
      System.out.println("计算环的节点个数:"+L2.getCircleNodeNum());
      System.out.println("L1链表的倒数第3个节点为:"+L1.findReverseKNode(3).value);
      System.out.println("L1链表的节点元素为:"+L1.toString());
      //创建两条相交链表L3、L4;
      LinkList L3=L.createList();
      LinkList L4=L.createList();
      L3.createLink(L1);//将L1链接在L3的末尾
      L4.createLink(L1);//将L1链接在L4的末尾
      System.out.println("判断L3和L4是否相交:"+L3.isLinkCross(L4));
      System.out.println("两链表链接的节点元素的值为:"+L3.LinkNode(L4).value);
      System.out.println("L3链表的节点元素为:"+L3.toString());
      System.out.println("L4链表的节点元素为:"+L4.toString());

    }
}

运行结果:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值