因为单链表不能随便访问,只能通过节点的逐步移动访问,因此在数组上应用较多的堆排序和快速排序在链表这块并不适用,而归并排序则能很好的实现,因为归并排序只需要知道中间位置即可,这对于链表来说并不困难。
简单说一下归并排序的思想:
首先将一段链表分成两段,两段长度相等
然后对两段对应的位置进行排序,使用一个临时节点控制链表方向。
使用递归可以非常清晰表达该思想,通过不断递归将有序的两段链表细化到两个节点,排序完成后返回到外层执行该层的有序排列,依次进行后即可实现排序。
下面贴上代码,其中有注释.
/*
* 无环链表实现归并排序
*/
package com.sh.LinkedListMerge;
import java.util.Random;
public class LinkedListMerge {
/**
* @param args
*/
//核心合并操作
public Node merge(Node firstHalf,Node secondHalf)
{
Node current = new Node(-1);//current节点代表临时链表的指针,可移动
Node dummyNode = current;//dummyNode节点指向临时链表的首节点,不可移动,实际上也不移动
while(firstHalf != null && secondHalf != null)
{
if(firstHalf.value <= secondHalf.value)
{
current.next = firstHalf;
firstHalf = firstHalf.next;
}
else
{
current.next = secondHalf;
secondHalf = secondHalf.next;
}
//将current始终作为临时链表最后一个节点
current = current.next;
}
//将剩下的节点加入到临时链表中
current.next = (firstHalf != null) ? firstHalf : secondHalf;
return dummyNode.next;
}
public Node mergeSort(Node head)
{
if(head == null || head.next == null)
return head;
Node middleNode = this.getMiddleNode(head);
Node secondHalfNode = middleNode.next;
middleNode.next=null;//将两段链表分开
return merge(mergeSort(head),mergeSort(secondHalfNode));
}
public Node getMiddleNode(Node head)
{
if(head == null)
return null;
Node slow = head;
Node fast = head;
while(fast.next != null && fast.next.next != null)
{
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
//建立链表
public Node buildList(int number)
{
if(number<=0)
return null;
Random r = new Random();
Node head = new Node(r.nextInt(100));
Node pointer = head;
for(int i =1;i
{
Node tem = new Node(r.nextInt(100));//生成一个随机节点
pointer.next = tem;
pointer = tem;
}
return head;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int number = 10;
LinkedListMerge llm = new LinkedListMerge();
Node head = llm.buildList(number);
StringBuilder s= new StringBuilder();
for(Node temNode = head ; temNode != null; temNode = temNode.next)
s.append(temNode.value + "->");
String st = s.substring(0,s.length()-2);
System.out.println("原链表为:"+st);
//进行排序并输出
Node sortedHead = llm.mergeSort(head);
StringBuilder sorteds= new StringBuilder();
while(sortedHead!=null){
sorteds.append(sortedHead.value+"->");
sortedHead = sortedHead.next;
}
String sortedst = sorteds.substring(0,sorteds.length()-2);
System.out.println("排序后为:"+sortedst);
}
}
Node节点定义
package com.sh.LinkedListMerge;
public class Node {
int value ;
Node next;
public Node(int value)
{
this.value=value;
next = null;
}
public Node() {
// TODO Auto-generated constructor stub
}
} 打印输出为 原链表为:70->46->47->46->1->93->39->38->68->63 排序后为:1->38->39->46->46->47->63->68->70->93