单链表是否存在环及相关操作

给定一个单链表,

1 判断该连表是否存在环

2 如何知道环的长度

3 如何找到环的连接点

4 连表的长度


 定义一个节点:


public class Node {

	public String value ;
	public Node next ;
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public Node getNext() {
		return next;
	}
	public void setNext(Node next) {
		this.next = next;
	}
	
}


public class IsCricle {

	
	public static void main(String[] args) {
		Node node = new Node() ;
		node.setValue("node");
		Node node01 = new Node() ;
		node01.setValue("node01");
		Node node02 = new Node() ;
		node02.setValue("node02");
		Node node03 = new Node() ;
		node03.setValue("node03");
		Node node04 = new Node() ;
		node04.setValue("node04");
		Node node05 = new Node() ;
		node05.setValue("node05");
		Node node06 = new Node() ;
		node06.setValue("node06");
		Node node07 = new Node() ;
		node07.setValue("node07");
		Node node08 = new Node() ;
		node08.setValue("node08");
		
		node.setNext(node01);
		node01.setNext(node02);
		node02.setNext(node03);
		node03.setNext(node04);
		node04.setNext(node05);
		node05.setNext(node06);
		node06.setNext(node07);
		node07.setNext(node08);
		node08.setNext(node02);
		
		IsCricle isCricle = new IsCricle() ;
//		boolean flag = isCricle.isCricle(node) ;
//		System.out.println("result = " + flag ) ;
		
		/**
		 * slow->1->2->3->4->5->6->7->8->2->3->4->5->6 
		 * fast->2->4->6->8->3->5->7->3->5->7->2->4->6
		 */
		
		
//		int size = isCricle.cricleSize(node);
//		System.out.println("size = " + size ) ;
		
		
//		isCricle.findLoopNode(node) ;
		int size = isCricle.size(node);
		System.out.println(size);
	}
	
	/**
	 * 判断单链表中是否存在闭环
	 * 主题思想:设定两个指针slow,fast.从头开始分别走一步和两步,如果存在环则两者相遇,如果不存在环fast遇到null退出
	 * @param node
	 * @return
	 */
	public boolean isCricle(Node node){
		Node fast = node ;
		Node slow = node ;
		int i = 0 ; 
		while( fast != null && fast.next != null ){
			slow = slow.next ;
			fast = fast.next.next ;
			if( slow == fast ){
				System.out.println("i=" + i++);
				return true ;
			}
			++i ;
		}
		return false ;
	}
	
	/**
	 * 环的长度
	 * 主题思想:在判断是否为闭环时找到碰撞点,然后slow,fast从该点开始继续执行,再次碰撞所走过的操作就是环的长度s
	 * @param node
	 * @return
	 */
	public int cricleSize( Node node ){
		Node fast = node ;
		Node slow = node ;
		while( fast != null && fast.next != null ){
			slow = slow.next ;
			fast = fast.next.next ;
			if( slow == fast ){
				break ;
			}
		}
		if( fast == null || fast.next == null ){
			return 0 ;
		}
		int i = 1 ;
		slow = slow.next ;
		fast = fast.next.next ;
		while(slow != fast){
			slow = slow.next ;
			fast = fast.next.next ;
			i++ ;
		}
		return i ;
	}
	
	/**
	 * 环的连接点
	 * 基本思想:碰撞点p到连接点的距离等于头指针到连接点的距离,因此分别从碰撞点和头指针开始遍历,相遇的点即为连接点
	 * @param node
	 * @return
	 */
	public Node findLoopNode( Node node ){
		Node fast = node ;
		Node slow = node ;
		while( fast != null && fast.next != null ){
			slow = slow.next ;
			fast = fast.next.next ;
			if( slow == fast ){
				break ;
			}
		}
		if( fast == null || fast.next == null ){
			return null ;
		}
		slow = node ;
		while(slow != fast){
			slow = slow.next ;
			fast = fast.next ;
		}
//		System.out.println(slow.value);
		return slow ;
	}
	
	/**
	 * 计算连表的长度:
	 * 1 计算环的长度
	 * 2 计算头结点到连接点的长度
	 * 3 1+2
	 * @param node
	 * @return
	 */
	public int size( Node node ){
		int cricleSize = cricleSize(node);
		Node loopNode = findLoopNode( node ) ;
		while( node != loopNode ){
			node = node.next ;
			cricleSize++ ;
		}
		return cricleSize ;
	}
	
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值