单向链表中有单端单向链表和双端单向链表,其实另外还有双向链表,但是想到双向链表如果环,从后往前遍历的时候遇到连接点的时候没有办法分叉指向。
简单说说单向链表的成环问题,我的想法是先构建一个单向链表,然后指定一个连接的结点,判断这个指定的连接结点是否存在,如果存在,则尾部结点指向这个连接结点即可成环。
定义结点类
private class Node {
private Object data;
private Node next;
public Node(Object data) {
this.data = data;
}
}
单向链表头部添加:
public Object addHead(Object data) {
Node newNode = new Node(data);
if (size == 0) {
head = newNode;
} else {
newNode.next = head;// 在头部前面增加元素,当然是新元素的下一个结点才等于原先的头结点
head = newNode;
}
size++;
return data;
}
查找连接的结点
在方法外部定义一个全局变量linkedPointNode,
// 查找连接结点
public Node linkedPoint(String data) {
Node linkedNode = new Node(data);
Node current = head;
if (head == null) {
return null;
}
while (current.next != null) {
current = current.next;
if (current.data == linkedNode.data) {//结点的值相等不能说明地址相等
linkedPointNode = current;//结点相等才是复制地址
}
}
System.out.println("找到了连接的结点");
return linkedPointNode;
}
连接结点,遍历到尾部结点,然后尾部结点的next指向指定的连接点linkedPointNode
public boolean doLink() {
Node node = head;
if (head == null) {
return false;
}
while (node.next != null) {
node = node.next;
}
node.next = linkedPointNode;
return true;
}
合并两个有序链表(两个有序链表由小到大排序)
public class MergeList {
// 定义一个头节点
private Node head;
private int size;
private class Node {
private int data;
private Node next;
// Node类构造函数的初始化
public Node(int data) {
this.data = data;
}
}
// 从链表的头部添加结点
public Node addHead(int data) {
// 将要添加的数据保存为一个结点
Node newHead = new Node(data);
if (size == 0) {
head = newHead;
} else {
newHead.next = head;
head = newHead;
}
size++;
return newHead;
}
//合并操作
public static Node mergeList(Node list1, Node list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
Node resultNode;
if (list1.data < list2.data) {
resultNode = list1;
list1 = list1.next;
} else {
resultNode = list2;
list2 = list2.next;
}
//自身调用
resultNode.next = mergeList(list1, list2);
return resultNode;
}
public static void main(String[] args) {
MergeList mergeList1 = new MergeList();
MergeList mergeList2 = new MergeList();
mergeList1.addHead(9);
mergeList1.addHead(7);
mergeList1.addHead(5);
mergeList2.addHead(8);
mergeList2.addHead(6);
mergeList2.addHead(4);
Node result = mergeList(mergeList1.head, mergeList2.head);
while (result.next != null) {
System.out.println(result.data);
result = result.next;
}
}
}
判断两个单链表是否相交
如果两个链表相交于某一节点,那么在这个相交节点之后的所有节点都是两个链表所共有的。 也就是说,如果两个链表相交,那么最后一个节点肯定是共有的。 (与数学中的两条线交叉不同)
先遍历第一个链表,记住最后一个节点,然后遍历第二个链表, 到最后一个节点时和第一个链表的最后一个节点做比较,如果相同,则相交,
否则不相交。时间复杂度为O(len1+len2),因为只需要一个额外指针保存最后一个节点地址, 空间复杂度为O(1)
public static boolean isIntersect(Node head1, Node head2) {
if (head1 == null || head2 == null) {
return false;
}
Node tail1 = head1;
// 找到链表1的最后一个节点
while (tail1.next != null) {
tail1 = tail1.next;
}
Node tail2 = head2;
// 找到链表2的最后一个节点
while (tail2.next != null) {
tail2 = tail2.next;
}
return tail1 == tail2;
}