zoukankan      html  css  js  c++  java
  • 经典排序算法--归并排序

    基本思想:

      归并排序是将两个或两个以上的有序表组合成一个新的有序表。其基本思想是:先将N个数据看成N个长度为1的表,将相邻两个表合并,得到长度为2的N/2个有序表,进一步将相邻的表合并,得到长度为4的N/4个有序表,以此类推,知道所有数据合并成一个长度为N的有序表位置。没一次归并称为一趟。

      要解决归并问题,首先要解决两两归并问题(两个有序表合并成一个有序表),其java实现为:

     1     
     2     public static void mergeTwo(int[] data,int first,int mid,int last,int[] tmp){
     3         
     4         //把data[first]-data[mid]当做第一个有序序列 ,这里设为A
     5         //把data[mid+1]-data[last]当做第二个有序序列,这里设为B
     6         //将两个有序序列合并,形成的新序列为data[first]-data[last]
     7         int i = first, j = mid + 1;  
     8         int m = mid,   n = last;  
     9         int k = 0; 
    10         while(i<=m&&j<=n){
    11             //A序列和B序列依次从起始值开始比较
    12             //如果A序列值小,就将其移值tmp中
    13             //并且A下标i+1;tmp下标k+1
    14             if(data[i]<data[j]){
    15                 tmp[k++] =data[i++];
    16             }else{
    17                 //如果B序列值小,就将其移值tmp中
    18                 //并且B下标i+1;tmp下标k+1
    19                 tmp[k++] = data[j++];
    20             }
    21         }
    22         
    23         //如果A序列或者B序列已经全部移到tmp中
    24         //则剩余的另一个序列依次移到tmp中
    25         while(i<=m){
    26             tmp[k++] =data[i++];
    27         }
    28         while(j<=n){
    29             tmp[k++] = data[j++];
    30         }
    31         
    32         //遍历tmp,将tmp中元素移会data,此时data[first]-data[last]为有序序列
    33         for (i = 0; i < k; i++)  {
    34             data[first + i] = tmp[i]; 
    35         }
    36     }

    实现方法:

      归并排序有两种实现方法:

      1)自底向上

      2)自顶向下

      自底向上的基本思想是:第一趟归并排序时,将待排序的文件R[1.....n]看做是n个长度为1的有序文件,将这些子文件两两归并,若n为偶数,则得到n/2个长度为2的有序文件;若n为奇数,则最后一个子文件轮空(不参与归并,直接进入下一趟归并),估本趟归并完成后,前n/2-1个有序子文件长度为2,单最后一个子文件长度仍未1;第二趟归并则是将第一趟归并所得到的n/2个有序文件两两归并,如此反复,知道得到最后长度为n的有序文件位置。

      其程序实现:

     1 package sortDemo;
     2 
     3 public class MargeSort {
     4     
     5     public static void main(String[] args) {
     6         int[] sort ={3,2,1,4,6,5,8,9,10,7} ;
     7         System.out.println("排序前:");
     8         print(sort);
     9         int[] tmp = new int[sort.length];
    10         mergeSort(sort,0,sort.length-1,tmp);
    11         System.out.println("
    排序后:");
    12         print(sort);
    13     }
    14     
    15     public static void mergeSort(int[] data,int first,int last,int[] tmp){
    16         if(first<last){
    17             int mid = (last-first)/2+first;
    18             //使左侧有序
    19             mergeSort(data,first,mid,tmp);
    20             //使右侧有序
    21             mergeSort(data,mid+1,last,tmp);
    22             //合并两个有序的子序列
    23             mergeTwo(data, first, mid, last, tmp);
    24         }
    25     }
    26     
    27     public static void mergeTwo(int[] data,int first,int mid,int last,int[] tmp){
    28         
    29         //把data[first]-data[mid]当做第一个有序序列 ,这里设为A
    30         //把data[mid+1]-data[last]当做第二个有序序列,这里设为B
    31         //将两个有序序列合并,形成的新序列为data[first]-data[last]
    32         int i = first, j = mid + 1;  
    33         int m = mid,   n = last;  
    34         int k = 0; 
    35         while(i<=m&&j<=n){
    36             //A序列和B序列依次从起始值开始比较
    37             //如果A序列值小,就将其移值tmp中
    38             //并且A下标i+1;tmp下标k+1
    39             if(data[i]<data[j]){
    40                 tmp[k++] =data[i++];
    41             }else{
    42                 //如果B序列值小,就将其移值tmp中
    43                 //并且B下标i+1;tmp下标k+1
    44                 tmp[k++] = data[j++];
    45             }
    46         }
    47         
    48         //如果A序列或者B序列已经全部移到tmp中
    49         //则剩余的另一个序列依次移到tmp中
    50         while(i<=m){
    51             tmp[k++] =data[i++];
    52         }
    53         while(j<=n){
    54             tmp[k++] = data[j++];
    55         }
    56         
    57         //遍历tmp,将tmp中元素移会data,此时data[first]-data[last]为有序序列
    58         for (i = 0; i < k; i++)  {
    59             data[first + i] = tmp[i]; 
    60         }
    61     }
    62     
    63     public static void print(int[] a){
    64         for (int i = 0; i < a.length; i++) {
    65             System.out.print(a[i]+" ");
    66         }
    67         System.out.println();
    68     }
    69 }

    算法分析:

      (1)稳定性

      归并排序是一种稳定的排序。

      (2)存储结构要求

      可用顺序存储结构,也易于在链表上实现。

      (3) 时间复杂度

      对长度为n的文件,需要进行[log2n]趟二路归并,没趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是最坏情况下均是O(nlgn).

      

  • 相关阅读:
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二十一:SDRAM模块④ — 页读写 β
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二十:SDRAM模块③ — 页读写 α
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十九:SDRAM模块② — 多字读写
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十八:SDRAM模块① — 单字读写
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十七:IIC储存模块
    【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十六:IIC储存模块
    APP安全测试用例梳理
    【python的练习题】:1-100奇数求和(涉及匿名函数filter lambda 的使用)
    反编译 AndroidManifest.xml文件(APP安全测试)
    Android app数据存储的安全测试
  • 原文地址:https://www.cnblogs.com/xsyfl/p/6905974.html
Copyright © 2011-2022 走看看