数据结构:归并排序
归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
归并操作
归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。
算法描述
归并操作的过程如下:
- 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
- 设定两个指针,最初位置分别为两个已经排序序列的起始位置
- 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
- 重复步骤3直到某一指针达到序列尾
- 将另一序列剩下的所有元素直接复制到合并序列尾
归并排序具体工作原理如下(假设序列共有n个元素):
- 将序列每相邻两个数字进行归并操作,形成个序列,排序
- 将上述序列再次归并,形成个序列,每个序列包含四个元素后每个序列包含两个元素
- 重复步骤2,直到所有元素排序完毕
————来自维基百科
java代码:
View Code
1 //通过递归实现归并排序 2 public class DArray 3 { 4 private long[] theArray ; //数组,记录数据 5 private int nElems ; //记录数组中元素的个数 6 7 //--------------------------------------------------- 8 //构造方法 9 public DArray(int max) 10 { 11 theArray = new long[max] ; 12 nElems = 0 ; 13 } 14 //--------------------------------------------------- 15 //插入数据 16 public void insert(long value) 17 { 18 theArray[nElems++] = value ; 19 } 20 //--------------------------------------------------- 21 //显示数组 22 public void display() 23 { 24 for(int i=0 ; i<nElems ; i++) 25 System.out.print(theArray[i]+" ") ; 26 System.out.println() ; 27 } 28 //--------------------------------------------------- 29 //调用归并 30 public void mergeSort() 31 { 32 long[] workSpace = new long[nElems] ;//用于存储排序好的数据,最后把该数组中的数据返回给theArray数组 33 recMergeSort(workSpace,0,nElems-1) ;//调用归并排序 34 } 35 //--------------------------------------------------- 36 //归并排序 37 private void recMergeSort(long[] workSpace,int lowerBound,int upperBound) 38 { 39 //基元 40 if(lowerBound == upperBound) 41 return ; 42 else 43 { 44 int mid = (lowerBound+upperBound)/2 ; 45 recMergeSort(workSpace,lowerBound,mid) ;//归并排序前一半 46 recMergeSort(workSpace,mid+1,upperBound) ;//归并排序后一半 47 merge(workSpace,lowerBound,mid+1,upperBound) ;//归并前一半和后一半 48 } 49 } 50 //--------------------------------------------------- 51 //归并数组 52 private void merge(long[] workSpace,int lowPtr,int highPtr,int upperBound) 53 { 54 int j = 0 ;//用于记录workSpace数组中元素的个数 55 int lowerBound = lowPtr ;//此处利用下标把数组分为两组,就是要合并这两组 ; lowerBound 记录从theArray传来的数据的起始下标 56 int mid = highPtr - 1 ; 57 int n = upperBound - lowerBound + 1 ;//统计数组中元素的个数,用于把排序好的数组返回给theArray数组 58 59 while(lowPtr<=mid && highPtr<=upperBound) 60 if(theArray[lowPtr] < theArray[highPtr]) 61 workSpace[j++] = theArray[lowPtr++] ; 62 else 63 workSpace[j++] = theArray[highPtr++] ; 64 65 //把还没有归并的数据插入 66 while(lowPtr<=mid) 67 workSpace[j++] = theArray[lowPtr++] ; 68 while(highPtr<=upperBound) 69 workSpace[j++] = theArray[highPtr++] ; 70 71 //最后把workSpce中排序好的数据返回给theArray数组 72 for(int i = 0 ; i<n ; i++) 73 theArray[lowerBound++] = workSpace[i] ; 74 } 75 }
View Code
1 //测试大数据时,归并排序的执行时间 2 import java.util.Date ; 3 public class DArrayApp2 4 { 5 public static void main(String[] agrs) 6 { 7 int maxSize = 10000 ; 8 DArray arr ; 9 int value ; 10 long time ; 11 System.out.println("【归并排序】"); 12 System.out.println("大小——>时间(ms)") ; 13 while(maxSize <= 1000000000) 14 { 15 System.out.print(maxSize+"——>") ; 16 arr = new DArray(maxSize) ; 17 //插入随机数据 18 for(int i = 0 ; i<maxSize ; i++) 19 { 20 value = (int)(Math.random()*1000) ;//产生随机数 21 arr.insert(value) ; 22 } 23 Date before = new Date() ;//记录排序前的时间 24 arr.mergeSort() ; 25 Date after = new Date() ;//记录排序后的时间 26 time = after.getTime() - before.getTime() ; 27 System.out.println(time) ; 28 maxSize += 10000 ; 29 } 30 } 31 }
主要程序:
View Code
1 //调用归并 2 public void mergeSort() 3 { 4 long[] workSpace = new long[nElems] ;//用于存储排序好的数据,最后把该数组中的数据返回给theArray数组 5 recMergeSort(workSpace,0,nElems-1) ;//调用归并排序 6 } 7 //--------------------------------------------------- 8 //归并排序 9 private void recMergeSort(long[] workSpace,int lowerBound,int upperBound) 10 { 11 //基元 12 if(lowerBound == upperBound) 13 return ; 14 else 15 //推卸责任 16 { 17 int mid = (lowerBound+upperBound)/2 ; 18 recMergeSort(workSpace,lowerBound,mid) ;//归并排序前一半 19 recMergeSort(workSpace,mid+1,upperBound) ;//归并排序后一半 20 merge(workSpace,lowerBound,mid+1,upperBound) ;//归并前一半和后一半 21 } 22 } 23 //--------------------------------------------------- 24 //归并数组 25 private void merge(long[] workSpace,int lowPtr,int highPtr,int upperBound) 26 { 27 int j = 0 ;//用于记录workSpace数组中元素的个数 28 int lowerBound = lowPtr ;//此处利用下标把数组分为两组,就是要合并这两组 ; lowerBound 记录从theArray传来的数据的起始下标 29 int mid = highPtr - 1 ; 30 int n = upperBound - lowerBound + 1 ;//统计数组中元素的个数,用于把排序好的数组返回给theArray数组 31 32 while(lowPtr<=mid && highPtr<=upperBound) 33 if(theArray[lowPtr] < theArray[highPtr]) 34 workSpace[j++] = theArray[lowPtr++] ; 35 else 36 workSpace[j++] = theArray[highPtr++] ; 37 38 //把还没有归并的数据插入 39 while(lowPtr<=mid) 40 workSpace[j++] = theArray[lowPtr++] ; 41 while(highPtr<=upperBound) 42 workSpace[j++] = theArray[highPtr++] ; 43 44 //最后把workSpce中排序好的数据返回给theArray数组 45 for(int i = 0 ; i<n ; i++) 46 theArray[lowerBound++] = workSpace[i] ; 47 }
测试结果:
可见,归并排序很快,但缺点是大数据时,很暂用系统内存....