java-单链表

定义一个单链表,先定义一个节点,实现判断链表是否为空、在链表中插入节点(头插和尾插)、删除节点等操作

//定义节点
class Node{
    int value; //结点存放的值
    Node next; //next域
    public Node(){
        this(0);  //this引用
    }
    Node(int value){
        this.value = value;
        this.next = null;
    }
}

//定义单链表
class LinkList{
    Node head;  //头结点
    LinkList next; //next域
    public LinkList(){
        head = new Node();
    }
    //判断链表是够否空
    public boolean empty(){ 
        return head.next == null;
    }
    //头插法
    public void insertHead(int value){
        Node n = new Node(value); //定义一个新节点
        n.next = head.next; //将n插到头结点后
        head.next = n;
    }
    //尾插法
    public void insertTail(int value){
        Node ptail = head; //将头结点赋予尾
        while(ptail.next != null){
            ptail = ptail.next;
        } //找到单链表的尾部
        ptail.next = new Node(value); //插入新节点
    }
    //删除值为value的节点
    public void delete(int value){
        Node pcur = head.next; 
        Node ppre = head;
        while(pcur != null){
            if(pcur.value == value){  
                ppre.next = pcur.next;
                break;
            }
            ppre = pcur;
            pcur = pcur.next;
        }
    }
    //自己实现toString的方法,利用StringBuilder//可以改变底层元素的值
    public String toString(){
        StringBuilder builder = new StringBuilder();
        Node n = head.next;
        while(n != null){
            builder.append(n.value+" ");//插入值为value的节点
            n = n.next;
        }
        return builder.toString();
    }
}

1.判断单链表是否有环:定义两个引用变量,慢变量slow,快变量fast,慢变量一次走1个节点,快变量一次走2个节点,当两个变量所指的值相等时退出循环

//判断当前单链表是否有环  true:有环  false:没有环
public boolean haveCircle(){
    Node slow = head;
    Node fast = head;
    while(fast != null && fast.next != null){
        slow = slow.next;
        fast = fast.next.next;
        if(slow == fast){
            return true;
        }
    }
    return false;
}

2.如果单链表有环,返回环的入口节点
先判断是否有环,若有环,将快引用fast移回到头结点,慢引用slow在它们的相交节点,同时向后移直至再次相交,相交节点就是入口节点
单链表返回环的入口
慢指针slow走到相遇点走了x+y,快指针走了x+y+(n-x-y)+y,而快指针走的距离是慢指针的两倍,即快指针走了2x+2y,所以2x+2y = x+y+(n-x-y)+y,即2x + y = n

public Node firstCircleNode(){
    //碰撞点到连接点的距离 = 头指针到连接点的距离
    if(this.haveCircle() == false){
        return null;
    }
    else{
        Node fast = this.head;
        Node slow = this.head;
        while(fast != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                break;
            }
        }
        fast= head;
        while(slow != fast){
            slow = slow.next;
            fast = fast.next;
        }
        return fast;
    }

}

3.寻找单链表的倒数第K个节点:
定义两个引用变量,第一个变量在正数第K个节点位置,第二个变量个在头部,然后两个变量一起遍历直至第一个变量走到尾部,然后返回第二个变量所指的节点
环的倒数第K个节点

public Node findReverseKNode(int k){
    Node p1= head;
    Node p2= head;
    if(p1 == null || k < 1){
        return null;
    }
    while(p1.next != null && k > 1){
        p1 = p1.next;  //正数第k个
        k--;
    }
    while(p1 != null){
        p1 = p1.next;  // k = length - (length - k)
        p2 = p2.next;
    }
    return p2;
}

4.判断链表相交(只传入一个参数,另一个环引用此函数)
先求出两个链表的长度,然后让长链表先跑两个链表长度之差,接着两个链表一起向后遍历直至有值相等

public boolean isLinkCross(LinkList list){
    if (!(this.haveCircle() || list.haveCircle())) { 
        int l1 = this.length();
        int l2 = list.length();
        int n;
        Node p = this.head;
        Node q = list.head;
        if(l1 > l2){ //如果p是长链表,让p先走长度之差
            n = l1 - l2;
            for(int i=0;i<n;++i){
                p = p.next;
            }
        }
        else{ //如果q是长链表,让q先走长度之差
            n = l2- l1;
            for(int i=0;i<n;++i){
                q = q.next;
            }
        }
        while(p!=q && p.next != null){
            p = p.next;
            q = q.next;
            if(p == q){
                retern true;
                break;
            }
    }
    else if (this.HaveCircle()&&list.HaveCircle()) {  
            if (firstCircleNode() ==firstCircleNode()){
                return true;
                // 两个有环单链表,它们环的入口结点相同时,它们相交  
            }  
            else{
                return false;  
            }    
        }  

    return false;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值