2. 拓扑排序
/** 拓扑排序** 返回值:* -1 -- 失败(由于内存不足等原因导致)* 0 -- 成功排序,并输入结果* 1 -- 失败(该有向图是有环的)*/public int topologicalSort() { int index = 0; int num = mVexs.size(); int[] ins;// 入度数组 char[] tops;// 拓扑排序结果数组,记录每个节点的排序后的序号 。Queue<Integer> queue;// 辅组队列 ins = new int[num]; tops = new char[num]; queue = new LinkedList<Integer>(); // 统计每个顶点的入度数 for(int i = 0; i < num; i++) { ENode node = mVexs.get(i).firstEdge; while (node != null) { ins[node.ivex]++; node = node.nextEdge; } } // 将所有入度为0的顶点入队列 for(int i = 0; i < num; i ++) if(ins[i] == 0) queue.offer(i);// 入队列 while (!queue.isEmpty()) {// 队列非空 int j = queue.poll().intValue();// 出队列 。j是顶点的序号 tops[index++] = mVexs.get(j).data;// 将该顶点添加到tops中,tops是排序结果 ENode node = mVexs.get(j).firstEdge; // 获取以该顶点为起点的出边队列 // 将与"node"关联的节点的入度减1; // 若减1之后,该节点的入度为0;则将该节点添加到队列中 。while(node != null) { // 将节点(序号为node.ivex)的入度减1 。ins[node.ivex]--; // 若节点的入度为0,则将其"入队列" if( ins[node.ivex] == 0) queue.offer(node.ivex);// 入队列 node = node.nextEdge; } } if(index != num) { System.out.printf("Graph has a cyclen"); return 1; } // 打印拓扑排序结果 System.out.printf("== TopSort: "); for(int i = 0; i < num; i ++) System.out.printf("%c ", tops[i]); System.out.printf("n"); return 0;}
说明:
queue的作用就是用来存储没有依赖顶点的顶点 。它与前面所说的Q相对应 。
tops的作用就是用来存储排序结果 。它与前面所说的T相对应 。
归并排序
基本思想
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之) 。
分而治之

文章插图
可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现) 。分阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n 。
合并相邻有序子序列
再来看看治阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤 。

文章插图
代码实现
package sortdemo;import JAVA.util.Arrays;/*** Created by chengxiao on 2016/12/8.*/public class MergeSort { public static void main(String []args){ int []arr = {9,8,7,6,5,4,3,2,1}; sort(arr); System.out.println(Arrays.toString(arr)); } public static void sort(int []arr){ int []temp = new int[arr.length]; //在排序前,先建好一个长度等于原数组长度的临时数组,//避免递归中频繁开辟空间 sort(arr,0,arr.length-1,temp); } private static void sort(int[] arr,int left,int right,int []temp){ if(left<right){ int mid = (left+right)/2; sort(arr,left,mid,temp); //左边归并排序,使得左子序列有序 sort(arr,mid+1,right,temp); //右边归并排序,使得右子序列有序 merge(arr,left,mid,right,temp); //将两个有序子数组合并操作 } } private static void merge(int[] arr,int left,int mid,int right,int[] temp){ int i = left;//左序列指针 int j = mid+1;//右序列指针 int t = 0;//临时数组指针 while (i<=mid && j<=right){ if(arr[i]<=arr[j]){ temp[t++] = arr[i++]; }else { temp[t++] = arr[j++]; } } while(i<=mid){//将左边剩余元素填充进temp中 temp[t++] = arr[i++]; } while(j<=right){//将右序列剩余元素填充进temp中 temp[t++] = arr[j++]; } t = 0; //将temp中的元素全部拷贝到原数组中 while(left <= right){ arr[left++] = temp[t++]; } }}
最后
归并排序是稳定排序,它也是一种十分高效的排序,能利用完全二叉树特性的排序一般性能都不会太差 。java中Arrays.sort()采用了一种名为TimSort的排序算法,就是归并排序的优化版本 。从上文的图中可看出,每次合并操作的平均时间复杂度为O(n),而完全二叉树的深度为|log2n| 。总的平均时间复杂度为O(nlogn) 。而且,归并排序的最好,最坏,平均时间复杂度均为O(nlogn) 。
【冒泡,快速,希尔,拓扑,归并 排序算法整合】
推荐阅读
- Centos7环境下快速安装Pyspider WEB爬虫框架和phantomjs浏览器
- 小程序如何阻止事件冒泡?
- 如何快速了解一个陌生人?
- 淘宝直播快速上链接 淘宝直播间秒杀链接怎么上
- 软考考什么 pmp报考资格
- 淘宝店怎么快速提升等级 淘宝号等级怎么升级快速升级
- 快速了解正向代理与反向代理
- PS一分钟快速抠公章
- 怎么才能快速的增强肌肉弹性?
- 3条快速秘诀让你跑步愉快
