问题
在一个循环链表中节点的值递增排序,请设计一个算法在该循环链表中插入节点,并保证插入节点之后的循环链表仍然是排序的。
分析
首先分析在排序的循环链表中插入节点的规律。当在图4.15(a)的链表中插入值为4的节点时,新的节点位于值为3的节点和值为5的节点之间。这很容易理解,为了使插入新节点的循环链表仍然是排序的,新节点的前一个节点的值应该比新节点的值小,后一个节点的值应该比新节点的值大。
但是特殊情况需要特殊处理。如果新节点的值比链表中已有的最大值还要大,那么新的节点将被插入最大值和最小值之间。如果新节点的值比链表中已有的最大值还要大,那么新的节点将被插入最大值和最小值之间。
在上面的规则中,总是先试图从链表中找到符合条件的相邻的两个节点。如果开始的时候链表中的节点数小于2,那么应该有两种可能。第1种可能是开始的时候链表是空的,一个节点都没有。此时插入一个新的节点,该节点成为循环链表中的唯一节点,那么next指针指向节点自己,如图4.17(a)所示。第2种可能是开始的时候链表中只有一个节点,插入一个新的节点之后,两个节点的next指针互相指向对方,如图4.17(b)所示。
解
public class Test {
public static void main(String[] args) {
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(2);
ListNode listNode3 = new ListNode(3);
ListNode listNode4 = new ListNode(4);
ListNode listNode5 = new ListNode(5);
ListNode listNode6 = new ListNode(6);
listNode1.next = listNode2;
listNode2.next = listNode3;
listNode3.next = listNode5;
listNode5.next = listNode6;
listNode6.next = listNode1;
ListNode result = insert(listNode1, 4);
while (result != null) {
System.out.println(result.val);
result = result.next;
}
}
public static ListNode insert(ListNode head, int insertVal) {
ListNode node = new ListNode(insertVal);
if (head == null) {// 没有节点
head = node;
head.next = head;
}
else if (head.next == head) {// 只有一个节点
head.next = node;
node.next = head;
}
else {
insertCore(head, node);
}
return head;
}
private static void insertCore(ListNode head, ListNode node) {
ListNode cur = head;
ListNode next = head.next;
ListNode biggest = head;
while (!(cur.val <= node.val && next.val >= node.val) && next != head) {
cur = next;
next = next.next;
if (cur.val >= biggest.val)
biggest = cur;
}
if (cur.val <= node.val && next.val >= node.val) {
cur.next = node;
node.next = next;
}
else {
node.next = biggest.next;
biggest.next = node;
}
}
}