单链表的归并排序
来源:互联网 发布:网络会计授课教师招聘 编辑:程序博客网 时间:2024/05/10 19:28
归并排序是分治算法思想的一个具体体现。利用分治算法进行排序时,可以从两个方面进行考虑:
- merge方法:将两个已经有序的小集合合并为一个有序的大集合;
- sort方法:利用递归的方法,将总集合逐次二分为只有单个元素的集合,然后用merge方法将集合逐次两两合并,最后达到将总集合排序的目的。
对于链表而言,由于不能像数组一样随机访问,故而使用一般方法会因为迭代寻找节点而消耗大量的时间。归并排序可以说是链表排序的最佳方法,一方面利用分治算法不用大量的寻找节点从而节省了时间,另一方面不用开辟额外的空间保存节点。
Java代码如下所示:
import java.util.Iterator;// 可以调用递归排序的链表public class MergeLinkList<T extends Comparable<T>> implements Iterable<T>{ // 定义节点 private class Node { T item; Node next; } private Node first;// 头节点 private int currentLength; public MergeLinkList() { first = null; currentLength = 0; } public boolean isEmpty() { return first == null; } public int size() { return currentLength; } public void addFirst(T item) { Node newNode = new Node(); newNode.item = item; newNode.next = first; first = newNode; currentLength++; } public T removeFirst() { if (isEmpty()) { throw new NullPointerException(); } else { T item = first.item; first = first.next; currentLength--; return item; } } @SuppressWarnings("unchecked") public static <T> boolean less(Comparable<T> v,Comparable<T> w) { return v.compareTo((T)w)<0; } // 将两个有序链表合为一个有序链表并返回 private Node merge(Node a,Node b) { if (a==null&&b==null) { return null; } Node head=new Node();// 创建一个临时头节点 Node t=head;// 链表插入节点 while (a!=null&&b!=null) { if (less(a.item, b.item)) { // a的头节点插入 t.next=a; t=a; a=a.next; }else { // b的头节点插入 t.next=b; t=b; b=b.next; } } // 剩余的节点全部插入 if (a!=null) {t.next=a;} if (b!=null) {t.next=b;} t=head.next;// 跳过头节点 head=null;// 删除头节点 return t; } // 递归的将链表先二分,后归并 public Node sort(Node head) { if (head==null||head.next==null) { return head; } Node pfast=head.next;// 快指针,到达链表尾部时慢指针刚好指向链表中部 Node pslow=head;// 慢指针,配合快指针记录链表的中部 while (pfast.next!=null&&pfast.next.next!=null) { pslow=pslow.next; pfast=pfast.next.next; }// 结束时pslow指向中间,pfast指向末尾 pfast=sort(pslow.next);// 后半部分排序 pslow.next=null;// 从中间断开为两个链表 pslow=sort(head);// 前半部分排序 return merge(pslow, pfast);// 将前后有序链表合并 } public void sort() { Node newFirst=sort(first); first=newFirst; } @Override public Iterator<T> iterator() { return new Iterator<T>() { private Node current=first; @Override public boolean hasNext() { return current!=null; } @Override public T next() { T item=current.item; current=current.next; return item; } }; } public static void main(String[] args) { MergeLinkList<String> list=new MergeLinkList<>(); String[] s="uitvxbmqkcywhaszofnpldrgje".split(""); for (int i = 0; i < s.length; i++) { list.addFirst(s[i]); } for (String string : list) { System.out.print(string+" "); } System.out.println(); list.sort(); for (String string : list) { System.out.print(string+" "); } }}
代码中利用快慢指针进行二分的方法非常巧妙,快指针的移动是慢指针的两倍,所以快指针到达链表尾部时慢指针刚好指向链表中部。此时快指针的使命完成,我们可以让它指向排序好的后半链表。将链表从中部断开,此时慢指针也完成了使命,我们让它指向排序好的前半链表。最后调用merge方法将两者合并。
0 0
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 单链表的归并排序
- 自然归并排序和单链表实现的归并排序
- 单链表的排序(归并排序)
- 单链表的快速排序和归并排序
- 用归并排序实现单链表的排序
- 单链表的归并排序和插入排序
- 归并排序以及归并排序的优化
- 单链表的排序 快速排序 归并排序 quicksort mergesort
- 单链表的归并、快速排序 C++
- iOS开发中遇到的几种crash
- 显示和设置ProgressBar的进度
- 003-scanf函数使用和表达式-C语言笔记
- Universal Image Loader库使用方法
- 自定义spinner下拉框样式,并实现三级联动
- 单链表的归并排序
- 004-流程控制-C语言笔记
- 某大学期末C语言考试题(附加答案和讲解)
- 4.Android support design Snackbar
- 四种途径将HTML5 web应用变成android应用
- C实现memset函数
- 005-循环结构(上)-C语言笔记
- C语言中得到一个float值在内存中的16进制表示
- 黑马程序员-java