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

来源:互联网 发布:java人机猜拳代码 编辑:程序博客网 时间:2024/06/05 18:04

在链表中,有环链表,交叉链表,返回倒数第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());    }}

运行结果:

这里写图片描述

原创粉丝点击