单向链表判断是否有环

原理:
假设链表节点依次从左向右排列,p为链表头,即第一个节点,q为链表第二个节点,且设置p每次向右走一步,q每次向右走两步,
1.若链表没有环,则在q等于null之前,p永远追不上q,即q到链表尾部时即可确定该链表没有环;
2.若链表有环,则q会回到p的左边,当q最接近p时,有下面两种情况:
(1)p和q再向右走一步,则会相遇
(2)p和q再向右走两步,则会相遇
即在p和q相遇时即可判断该链表有环

代码如下

public class Node
{
	private int value;

	private Node next;

	public Node()
	{
	}

	public Node(int value)
	{
		super();
		this.value = value;
	}

	public int getValue()
	{
		return value;
	}

	public void setValue(int value)
	{
		this.value = value;
	}

	public Node getNext()
	{
		return next;
	}

	public void setNext(Node next)
	{
		this.next = next;
	}

}
public class Link
{
	/**
	 * 判断一个单向链表是否有环
	 * 
	 * @param head
	 *            表头
	 * @return
	 */
	public static boolean isLoopLink(Node head)
	{
		// 如果是空链表,则没有环
		if (null == head)
		{
			return false;
		}

		// 第一个节点
		Node p = head;
		// 第二个节点
		Node q = head.getNext();

		// 只有一个节点自环
		if (p == q)
		{
			return true;
		}

		while (p != q && null != p && null != q)
		{
			p = p.getNext();
			if (null != q.getNext())
			{
				q = q.getNext().getNext();
			}
			else
			{
				q = null;
			}

			if (p == q)
			{
				return true;
			}
		}

		return false;
	}

}

单元测试

public class LinkTest
{
	/**
	 * 空链表
	 */
	@Test
	public void test1()
	{
		Node node1 = null;

		assertFalse(Link.isLoopLink(node1));
	}

	/**
	 * 只有一个节点
	 */
	@Test
	public void test2()
	{
		Node node1 = new Node(1);

		assertFalse(Link.isLoopLink(node1));
	}

	/**
	 * 单节点自环
	 */
	@Test
	public void test3()
	{
		Node node1 = new Node(1);
		node1.setNext(node1);

		assertTrue(Link.isLoopLink(node1));
	}

	/**
	 * 多节点无环
	 */
	@Test
	public void test4()
	{
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(4);

		node1.setNext(node2);
		node2.setNext(node3);
		node3.setNext(node4);

		assertFalse(Link.isLoopLink(node1));
	}

	/**
	 * 多节点首尾相连有环
	 */
	@Test
	public void test5()
	{
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(4);

		node1.setNext(node2);
		node2.setNext(node3);
		node3.setNext(node4);
		node4.setNext(node1);

		assertTrue(Link.isLoopLink(node1));
	}

	/**
	 * 多节点非首尾相连有环
	 */
	@Test
	public void test6()
	{
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(4);

		node1.setNext(node2);
		node2.setNext(node3);
		node3.setNext(node4);
		node4.setNext(node2);

		assertTrue(Link.isLoopLink(node1));
	}

}

测试结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值