单链表的实现,判断是否有环和环的入口,找到链表的中间节点和倒数第k个节点

2019-04-17 14:45:48 浏览数 (1)

单链表的核心是头节点,定义一个next指针指向下一个节点的位置

代码语言:javascript复制
package cn.chinotan.linkedList;

public class LinkList {

	private Node head;

	public Node getHead() {
		return head;
	}

	public void setHead(Node head) {
		this.head = head;
	}

	// 插入
	public void insert(int msg) {
		Node node = new Node(msg);
		if (head == null) {
			head = node;
		} else {
			Node cNode = head;
			while (cNode.next != null) {
				cNode = cNode.next;
			}
			cNode.next = node;
		}
	}

	// 遍历当前链表
	public void printLink() {
		Node cNode = head;
		while (cNode != null) {
			System.out.println(cNode.msg);
			cNode = cNode.next;
		}
	}

	// 删除某个节点(根据索引号)
	public void delete(int index) {
		if (index < 0 || index > (len() - 1)) {
			return;
		}
		if (index == 0) {
			head = head.next;
			return;
		}
		Node pNode = head;
		Node cNode = pNode.next;
		int i = 1;
		while (cNode != null) {
			if (i == index) {
				pNode.next = cNode.next;
			}
			pNode = cNode;
			cNode = cNode.next;
			i  ;
		}
	}

	// 删除某个节点(根据节点删除)
	public void delete(Node dNode) {
		if (dNode == null) {
			return;
		}

		dNode.msg = dNode.next.msg;
		dNode.next = dNode.next.next;
	}

	// 统计链表长度
	public int len() {
		Node cNode = head;
		int count = 0;
		while (cNode != null) {
			count  ;
			cNode = cNode.next;
		}
		return count;
	}

	// 翻转链表输出(采用递归)
	public void reverseLink(Node node) {
		if (node != null) {
			reverseLink(node.next);
			System.out.println(node.msg);
		}
	}

	// 查找最中间的节点(采用快慢指针,快指针一下走两步,慢指针一下走一步,当快指针走完时,慢指针正好走到中间点,此时慢指针的位置就是要求的位置)
	public void midLink() {
		Node slow = head;
		Node fast = head;
		while (fast != null && fast.next != null && fast.next.next != null) {
			slow = slow.next;
			fast = fast.next.next;
		}

		System.out.println("中间节点为:"   slow.msg);
	}

	// 查找倒数第k节点(采用快慢指针,快指针一下走一步,慢指针一下走一步,快指针先走k步,之后慢指针和快指针一起走,当快指针到终点时,满指针的位置即所求点)
	public void findElem(int i) {
		int k = i;
		if (k < 1 || k > len()) {
			return;
		}
		Node slow = head;
		Node fast = head;

		for (; k != 0; k--) {
			fast = fast.next;
		}

		while (fast != null) {
			fast = fast.next;
			slow = slow.next;
		}
		System.out.println("倒数第"   i   "个节点为"   slow.msg);
	}

	// 判断链表是否有环(采用快慢指针,快指针一下走两步,慢指针一下走一步,当没有遍历完时,快指针和慢指针遇到后就说明链表有环)
	public Boolean isLoop() {
		Node slow = head;
		Node fast = head;
		while (fast != null && fast.next != null) {
			fast = fast.next.next;
			slow = slow.next;
			if (fast == slow) {
				System.out.println("该列表有环");
				return true;
			}
		}
		System.out.println("该列表没有环");
		return false;
	}

	// 找到链表的环的入口(采用快慢指针,记住头节点到环的入口所走过的路和快慢指针相遇点到环的入口所走过的路是一样的)
	public void findLoopPort() {
		Node slow = head;
		Node fast = head;

		while (fast != null && fast.next != null) {
			fast = fast.next.next;
			slow = slow.next;

			if (fast == slow) {
				break;
			}
		}

		if (fast == null) {
			return;
		}

		slow = head;
		while (fast != slow) {
			slow = slow.next;
			fast = fast.next;
		}

		System.out.println("环的入口为:"   slow.msg);
	}

	public static void main(String[] args) {
		int[] is = { 0, 2, 5, 7, 88, 2, 1, 66, 99 };
		LinkList linkList = new LinkList();
		for (int i : is) {
			linkList.insert(i);
		}
		System.out.println("原长度"   linkList.len());
		linkList.printLink();
		linkList.delete(3);
		System.out.println("删除后的长度"   linkList.len());
		System.out.println("删除后的值:");
		linkList.printLink();
		linkList.delete(linkList.head.next);
		System.out.println("删除后的长度"   linkList.len());
		System.out.println("删除后的值:");
		linkList.printLink();
		System.out.println("翻转链表:");
		linkList.reverseLink(linkList.head);
		linkList.midLink();
		linkList.findElem(4);

		// 环链表生成
		Node cNode = linkList.head;
		while (cNode.next != null) {
			cNode = cNode.next;
		}
		cNode.next = linkList.head.next;
		linkList.isLoop();
		linkList.findLoopPort();
	}

	class Node {

		int msg;

		Node next;

		public Node(int msg) {
			this.msg = msg;
		}
	}

}

(adsbygoogle = window.adsbygoogle || []).push({});

0 人点赞