归并排序法和基数排序法

归并排序法,这里介绍二路归并排序法,其他原理类似,只是更加复杂。

归并排序(Merge Sort)是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。

归并排序的具体做法:

  1. 把原序列不断地递归等分,直至每等份只有一个元素,此时每等份都是有序的。
  2. 相邻等份合并,不断合并,直至合并完全。

二路归并

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序最常用的是二路归并,即把两个小的有序的序列和并成一个大的有序序列:合二为一。

一个二路归并的流程图是这样的:

多路归并无非是多个有序的小序列合并成一个大的有序序列,道理和二路归并一样。

把两个有序序列合成一个大的有序序列的实现代码如下:

void MergeSort(int* a,int* b,int na,int nb,int* c)
{
    if(a == NULL || na <= 0 || b == NULL || nb <= 0)
        return;
    int i=0,j=0,k=0;
    //将a和b数组中的元素有序的放入到c数组中
    while(i<na && j<na)
    {
        if(a[i]<=b[j])
            c[k++] = a[i++];
        else
            c[k++] = b[j++];
    }

    //将剩下的元素全都放入到c数组中
    while(i<na)
        c[k++] = a[i++];
    while(i<nb)
        c[k++] = b[j++];

}

可以看出,二路归并的时间复杂度是O(n),n是原序列的数据规模。以上代码是归并排序的基础,弄懂了它,就很好写归并排序了,看下归并排序的流程图:

可以看出,上半部分不断地递归深入:不断地均分原序列,直到每一部分只含有一个元素。下半部分,开始递归返回,通过反复调用二路归并算法,把相邻的有序子序列合并成一个规模更大的序列。

归并排序的代码如下:

//把[first,mid]与[mid+1,last]范围内的数据合并
void mergeArray(int* a,int* b,int first,int mid,int last)
{
    int i = first;
    int j = mid + 1;
    int k = 0;
    while(i<=mid && j<=last)
    {
        //将[first,mid]与[mid+1,last]内的数据排序合并
        while(i<=mid && a[i]<=a[j])
            b[k++] = a[i++];
        while(j<=last && a[j]<a[i])
            b[k++] = a[j++];

        //将剩下的a的数组元素放入到b中
        while(i<=mid)
            b[k++] = a[i++];
        while(j<=last)
            b[k++] = a[j++];
    }
    //将合并后的数组返回到a数组上
    for(int i=0;i<k;i++)
        a[first+i] = b[i];

}

//归并排序
void mergesort(int* a,int* b,int first,int last)
{
    if(first < last)
    {
        int mid = first + (last-first)>>1; //求区间中点
        //不断的划分区间,然后进行递归操作
        mergesort(a,b,first,mid);
        mergesort(a,b,mid+1,last);
        mergeArray(a,b,first,mid,last);
    }
}

//传入需要归并排序的数组
void MergeSort(int* a,int n)
{
    if(a == NULL && n <= 1)
        return;
    int b[n];
    mergesort(a,b,0,n-1);
    delete[] b;
}

归并排序参考:http://blog.csdn.net/zhangxiangdavaid/article/details/34463409

基数排序法

今天看了太多排序,累了,晚点更新。。。

原文地址:https://www.cnblogs.com/jeavenwong/p/8214752.html

时间: 2024-11-05 16:04:28

归并排序法和基数排序法的相关文章

排序算法(四)——归并排序、基数排序

前面三篇文章分别介绍了插入排序.选择排序和交换排序,今天将最后两个排序讲完,分别是归并排序和基数排序. ****************************************************************************************************** 1.归并排序: 定义:所谓归并就是将两个或两个以上的有序文件合并成为一个新的有序文件.归并排序就是有n个记录的无序文件看成是由n个长度为1的有序子文件组成的文件,然后两两归并,得到n/2个长

Python八大算法的实现,插入排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序。

Python八大算法的实现,插入排序.希尔排序.冒泡排序.快速排序.直接选择排序.堆排序.归并排序.基数排序. 1.插入排序 描述 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2).是稳定的排序方法.插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素).在第一部分排序完成后,再将这

C#版 选择法、冒泡法、插入法和快速排序法分析与对比(一)

前言 之前老师就讲过了选择法和冒泡法,之后又提到了插入法和排序法,今天做了一个小DEMO,对比了一下四种方法的效率,当然看了很多大牛也博客,其实算法还设计了时间复杂度和空间复杂度,对于这两个概念,我只能从表面上进行理解,其中涉及到了很多数学的问题,所以就不展开写了. 选择排序 冒泡法 插入法 快速排序法 这部分知识比较新,而且内容比较多,所以打算单独另外总结一遍博客,来详细的总结一下这个方法~ DEMO(比较三个算法所用时间) 先说一下设计的思路,生成要求个数的不重复的随机数,将随机数循环赋给l

数据结构之排序算法Java实现(4)—— 基数排序法

基数排序算法是计数排序的延伸,计数排序会造成很大的空间浪费,但基数排序法是对位数进行排序,适合于位数之间相差较大的情况,废话不多说,直接上代码: 升序排序法: /** * 基数排序法 * 升序排列 * @param data */ public void sortByAsc(int[] data) { /** step1:确定排序的趟数*/ int max=data[0]; for(int i=1;i<data.length;i++){ if(data[i]>max){ max=data[i]

算法导论第2章 分治法与归并排序, 二分查找法

分治策略:将原问题划分成n个规模较小而结构与原问题相似的子问题,然后递归地解决这些子问题,最后再合并其结果,就可以得到原问题的解. 它需要三个步骤: 分解:将原问题分解成一系列的子问题. 解决:递归地解决各个子问题.若子问题足够小,则直接求解. 合并:将子问题的结果合并成原问题的解. 通过分治策略和分治步骤,可以简单地默出归并算法. 分解:将n个元素分成各自包含n/2个元素的子序列 解决:用归并排序法递归地对两个子序列进行排序. 合并:合并两个以排序的子序列,得到排序结果: void merge

关于Java中的选择排序法和冒泡排序法

一,这种方法是直接传入一个数组进行排序(选择排序法) public static void selectSort(int arr[]){ for (int i = 0; i < arr.length-1; i++) { for (int j = i+1; j < arr.length; j++) { if(arr[j]<arr[i]){ int temp=arr[i]; arr[i]=arr[j]; arr[j]=temp; } } } } 二,这种事传入一个数组和一个数组个数(选择排序

选择法和冒泡法排序接口

#define ret_ok 0 #define ret_err 1 #define ARRAY_SIZE 10 /*选择法排序*/ int Choice_Sort(int array[],int array_len) { int i = 0; int j = 0; int iMin = 0; int iTemp = 0; int iFlag = 0; for(i=0;i<array_len-1;i++) { iMin = i; for(j=i+1;j<array_len;j++) { if(

黑盒测试用例设计-功能图法和场景法(八)

7.功能图法 一个程序的功能包括静态和动态说明.动态说明描述输入数据的次序或转移的次序,和业务流程紧密对应.静态说明描述了输入输出条件之间的对应关系.对于面向市场的产品,其逻辑复杂.组合庞大,必须用动态说明来补充功能说明. 功能图设计方法:功能图方法使用功能图形象地表示程序的功能说明,并机械地生成功能图的测试用例.我们在不同文档中看到的"状态迁移图"."流程图"."菜单树",在一定程度上都是功能图的不同表现,不同测试人员可能对具体方法的使用稍有不

算法的时间复杂度比较,计算多项式的直接法和秦九韶法

1.直接法: 1 double Polynomial_1(int n, double a[], double x) 2 { 3 int i; 4 double sum = 0; 5 for (i = 0; i < n; i++) 6 sum += a[i] * pow(x, i); 7 return sum; 8 } 每次循环迭代,pow函数内部都会执行i次乘法,然后一次加法,所以整体的算法复杂度为O = 1/2 * n ^ 2 + 3/2n,尽管pow函数的实现方法是利用递归优化后的,但是算法