单链表的基本操作一
1. 单链表的反转
2.判断两个链表是否相交
public class LinkList {
/**
* 单链表的反转
*/
public static Node reverseList(Node head) {
if (head == null) {
return null;
}
if (head.getNext() == null) {
return null;
}
Node pNode = head.getNext();
Node qNode = null;
head.setNext(qNode);
qNode = head;
while(pNode != null) {
Node tmp = pNode.getNext();
pNode.setNext(qNode);
qNode = pNode;
pNode = tmp;
}
head = qNode;
return head;
}
/**
* 遍历链表
*/
public static void printList(Node head) {
while(head!=null) {
System.out.print(head.getData());
head = head.getNext();
}
System.out.println();
}
/**
* 判断单链表是否有环
* 快慢指针,快指针可以追上慢指针,有环
*/
public static Node hasCircle(Node head) {
if (head == null) {
return null;
}
Node fast, slow; //快慢指针
slow = head.getNext();
fast = head.getNext().getNext();
while(fast != slow) {
if (fast.getNext() == null || fast.getNext().getNext() ==null) {
return null;//无环
}
fast = fast.getNext().getNext();
slow = slow.getNext();
}
fast = head;
while(slow != fast) {// 快指针从头开始扫描,慢指针继续遍历,第一次相遇的节点即为环的入口;
fast = fast.getNext();
slow = slow.getNext();
}
return fast;
}
/**
* 判断两个链表是否相交:
* 1. 链表都无环:
* * * * * 1.1 先判断链表的尾指针是否相同,若不同,未相交;
* * * * * 1.2 若相同,则相交,让两个链表从 距离尾节点相同距离的位置开始遍历
* * * * *
* 2. 链表都有环 :
* * * * * 2.1 如果环的入口点相同,则判断方法同无环的判断方法,从距离换入口点相同距离的位置开始扫描两个链表;
* * * * * 2.2入口点不同:
*/
public static Node getFirstMeetNode(Node head1,Node head2) {
Node n1 = hasCircle(head1);
Node n2 = hasCircle(head2);
if (n1 == null && n2 == null) {
System.out.println(0);
//两个链表都无环;
return noCircleMeetNode(head1,head2);
}
if (n1 != null && n2 != null) {
System.out.println(1);
//两个链表都有环
return hasCircleMeetNode(head1,n1,head2,n2);
}
return null;
}
/**
* 无环时,找相交点
*/
public static Node noCircleMeetNode(Node head1,Node head2) {
if (head1 == null | head2 == null) { // 其中有一个为空链表,不相交
return null;
}
Node p1 = head1,p2 = head2;
int n = 0;
while(p1.getNext()!=null) {
n++;
p1 = p1.getNext();
}
while(p2.getNext()!=null) {
n--;
p2 = p2.getNext();
}
if (p1 != p2) {
return null; // 尾节点不相同,不相交
}
System.out.println("尾节点相同:"+p1.getData());
if (n >0) {
p1 = head1;
while(n >0) {
n --;
p1 = p1.getNext();
}
p2 = head2 ;
while(p1 != p2) {
p1 = p1.getNext();
p2 = p2.getNext();
}
return p1;
}else{
p2 = head2;
while (n<0) {
n++;
p2 = p2.getNext();
}
p1 = head1;
while( p1 != p2) {
p1 = p1.getNext();
p2 = p2.getNext();
}
return p1;
}
}
/**
* 有环,找相交点
*/
public static Node hasCircleMeetNode(Node head1,Node n1,Node head2,Node n2) {
Node p1 = null, p2 = null;
if (n1 == n2) {
System.out.println("入环点相同:"+ n1.getData());
//入环点相同
p1 = head1;
p2 = head2;
int n = 0;
while(p1 != n1) {
n++;
p1 = p1.getNext();
}
while(p2 != n2) {
n--;
p2 = p2.getNext();
}
if (n >0) {
p1 = head1;
while(n >0) {
n --;
p1 = p1.getNext();
}
p2 = head2 ;
while(p1 != p2) {
p1 = p1.getNext();
p2 = p2.getNext();
}
return p1;
}else{
p2 = head2;
while (n<0) {
n++;
p2 = p2.getNext();
}
p1 = head1;
while( p1 != p2) {
p1 = p1.getNext();
p2 = p2.getNext();
}
return p1;
}
}else {
System.out.println("入环点不同:"+ n1.getData()+" "+n2.getData());
p1 = n1.getNext();
while(p1 != n1) {
if (p1 == n2) {
return n1;
}
p1 = p1.getNext();
}
}
return null;
}
// 测试
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.setNext(node2);node2.setNext(node3);node3.setNext(node4);node4.setNext(node5);
Node head = node1;
// System.out.println("原始单链表");
// printList(head);
// System.out.println();
// System.out.println("反转后的单链表");
// Node newHead = reverseList(head);
// printList(newHead);
// System.out.println("判断单链表是否有环:");
Node node6 = new Node(6); Node node7 = new Node(7); Node node8 = new Node(8);
node5.setNext(node6); node6.setNext(node7); node7.setNext(node8); //node8.setNext(node5);
Node node0 = new Node(0);
Node node9 = new Node(9);
node0.setNext(node9); node9.setNext(node4);
// 0 9 7 8 5 6 7
System.out.println("list1是否有环:"+(hasCircle(head) == null ? null:hasCircle(head).getData()));
System.out.println("list2是否有环:"+(hasCircle(node0) == null ? null:hasCircle(node0).getData()));
//list1 1 > 2 > 3 > 4 > 5 > 6 > 7 > 8 >5
//list2 null
// Node node = getFirstMeetNode(head,null);
// System.out.println("链表的交点 :"+(node == null ? null : node.getData())); // null
// node = getFirstMeetNode(null,null);
// System.out.println("链表的交点 :"+(node == null ? null : node.getData())); // null
//list2 0 > 9 > 7 > 8 > 5 > 6 > 7
Node node = getFirstMeetNode(head,node0);
System.out.println("链表的交点 :"+(node == null ? null : node.getData()));
}
}
class Node{
// 单链表的节点类
private int data;//数据
private Node next;//指向下一个数据的指针
public Node(int data) {
super();
this.data = data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}