数据结构List实例(四):使用归并排序对单链表进行排序

    对链表进行排序,要求的时间复杂度为O(n log n)。nlogn的排序有快速排序、归并排序、堆排序。双向链表用快排比较适合,堆排序也可以用于链表,单向链表适合用归并排序。题目要求的是常数的空间复杂度,因为这里用了递归,如果算上栈空间的话,也要 o(logn)的复杂度。

    方案:关于链表的划分,这里使用了快慢指针,从中间节点进行切开成单独的链表。在merge之后又会合并成一个链表。

   实现代码如下:

     /**   
* @Title: MergeSortList.java 
* @Package List 
* @Description: TODO 
* @author peidong  
* @date 2017-4-22 上午9:24:15 
* @version V1.0   
*/
package List;


import java.awt.List;


import List.ListReverse.Node;


/** 
 * @ClassName: MergeSortList 
 * @Description: 使用归并排序对单链表进行排序
 * @date 2017-4-22 上午9:24:15 
 *  
 */

public class MergeSortList {


/**

* @ClassName: ListNode 
* @Description: 构建链表结点内部类
* @date 2017-4-22 上午9:33:14 
* 注意:原来我写的内部类是动态的,也就是开头以public class开头。而主程序是public static 
* class main。在Java中,类中的静态方法不能直接调用动态方法。只有将某个内部类修饰为静态类,然
* 后才能够在静态类中调用该类的成员变量与成员方法
*
*/
public static class ListNode {
public int data;
public ListNode next;


public ListNode(int data) {
this.data = data;
this.next = null;
}
}

/**

* @Title: sortList 
* @Description: 利用递归来对链表进行划分至最小单元
* @param @param head
* @param @return    
* @return ListNode    
* @throws
*/
public static ListNode sortList(ListNode head){
if(head == null || head.next == null){
return head;
}

ListNode slow = head; //慢指针
ListNode fast = head; //快指针

//利用快慢指针找到中间结点
while(fast.next != null && fast.next.next != null){
slow = slow.next;   //慢指针每次后移一步
fast = fast.next.next;  //快指针每次后移两步
}

ListNode list2 = slow.next;
slow.next = null;  //链表的前半部分形成新的链表
head = sortList(head); //对链表的前半部分进行递归
list2 = sortList(list2);  //对链表的后半部分递归

return merge(head, list2); //归并
}

public static ListNode merge(ListNode list1, ListNode list2) {
// 边界条件判断
if(list1 == null){
return list2; 
}
if(list2 == null){
return list1;
}

ListNode newHead = new ListNode(0);//头结点
ListNode last = newHead;

//比较归并,只需更换指针,控件复杂度为O(1)
while(list1 != null && list2 != null){
if(list1.data < list2.data){
last.next = list1;  //赋值
list1 = list1.next; //步进
}else{
last.next = list2;
list2 = list2.next;
}
last = last.next;
}

//剩余部分直接连接
if(list1 != null ){
last.next = list1;
}
if(list2 != null){
last.next = list2;
}

return newHead.next;
}
/** 
* @Title: main 
* @Description: 测试归并排序
* @param @param args    
* @return void    
* @throws 
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
        
//添加数据
ListNode t1 =new ListNode(13);
ListNode t2 =new ListNode(11);
ListNode t3 =new ListNode(15);
ListNode t4 =new ListNode(17);
ListNode t5 =new ListNode(16);
ListNode t6 =new ListNode(20);
ListNode t7 =new ListNode(9);
ListNode t8 =new ListNode(6);

//构建链表
t1.next = t2;
t2.next = t3;
t3.next = t4;
t4.next = t5;
t5.next = t6;
t6.next = t7;
t7.next = t8;

// //输出原始链表
// while(t1 != null){
// System.out.println(t1.data + " ");
// t1 = t1.next;
// }
//使用归并排序对链表进行排序
t1 = MergeSortList.sortList(t1);

//输出排序后的链表
while(t1 != null){
System.out.println(t1.data + " ");
t1 = t1.next;
}

}


}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值