数据结构:归并排序

归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

归并操作

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。

算法描述

归并操作的过程如下:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  4. 重复步骤3直到某一指针达到序列尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾  

 

归并排序具体工作原理如下(假设序列共有n个元素):

  1. 将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序
  2. 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素后每个序列包含两个元素
  3. 重复步骤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    }

 

测试结果:

 

可见,归并排序很快,但缺点是大数据时,很暂用系统内存....

 

 

 

 

 

 

 

 

 

 

 

posted @ 2012-10-30 22:11  KeenLeung  阅读(378)  评论(0编辑  收藏  举报