请用归并排序帮我写一段排序链表的代码,语言用JAVA
时间: 2024-10-01 16:09:26 浏览: 39
在Java中,由于链表的特点(数据结构),我们可以直接对链表节点进行操作,不需要像数组那样预分配额外的空间。这里是一个基于迭代方式的归并排序链表的简化版本,我们先将链表拆分成两个独立的有序链表,然后再合并它们:
```java
import java.util.Stack;
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class MergeSortLinkedList {
public ListNode mergeSortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
// 使用栈来辅助归并过程
Stack<ListNode> stack = new Stack<>();
ListNode slow = head, fast = head.next;
// 将链表拆成若干个连续段
while (fast != null && fast.next != null) {
stack.push(slow);
slow = slow.next;
fast = fast.next.next;
}
stack.push(slow); // 最后一个段
ListNode sortedTail = null;
while (!stack.isEmpty()) {
ListNode firstHalf = stack.pop(); // 取出一个段
ListNode secondHalf = stack.empty() ? null : stack.peek(); // 获取下一个段(如果存在)
ListNode current = firstHalf, temp = firstHalf;
while (secondHalf != null) {
// 比较并合并两个链表
if (current.val <= secondHalf.val) {
temp.next = current;
current = current.next;
} else {
temp.next = secondHalf;
secondHalf = secondHalf.next;
}
temp = temp.next;
}
temp.next = secondHalf; // 如果第二半链表未遍历完,直接接上
if (sortedTail != null) {
sortedTail.next = firstHalf; // 连接到已经排序好的链表尾部
} else {
head = firstHalf; // 如果这是第一个段,就替换为头节点
}
sortedTail = current; // 更新排序后的链表尾部
}
return head;
}
public static void main(String[] args) {
ListNode head = new ListNode(4);
head.next = new ListNode(2);
head.next.next = new ListNode(1);
head.next.next.next = new ListNode(3);
MergeSortLinkedList sorter = new MergeSortLinkedList();
ListNode sortedHead = sorter.mergeSortList(head);
printList(sortedHead);
}
private static void printList(ListNode node) {
while (node != null) {
System.out.print(node.val + " ");
node = node.next;
}
System.out.println();
}
}
```
在这个代码中,`mergeSortList`函数通过不断取堆栈顶部的链表段,将其与下一段合并,直到所有链表都被排序。请注意,这个解决方案保留了链表原有的空间效率,因为它只用到了常数级别的额外空间。
阅读全文