归并排序(MERGE_SORT)

归并排序(MERGE_SORT)

1)分治思想 :归并排序用到了一种称为分治法的设计方法,分治法的思想就是将原问题的分解成为几个规模小的但是类似于原问题的子问题,递归的求解子问题,之后再合并子问题的解,来组成原问题的解。

2)原理 :根据分治方法的思想,归并排序算法的基本操作分为三大步:分解,解决问题,合并结果。以一个需要排序的数组为例,分解也就是不停地递归分解问题,直到问题的规模降为1,然后开始合并。

3)C语言实现

void merge(int from, int mid, int to, int* a)
{
    //新建了一个辅助的数组,用来暂时寄存merge时的数组
    int left_top, right_top, index, count, *t;
    index = 0;
    //左半边的等待merge数组的顶端
    left_top = from;
    //右半边的等待merge数组的顶端
    right_top = mid + 1;
    //整个merge后的数组长度
    count = to - from;
    t = (int*)malloc( (count + 1) * 2);
    //不断的从左右两个需要merge的子数组中取出顶端较小的数字
    //直到其中一个数组取尽
    while ((left_top <= mid) && (right_top <= to))
    {
        if (a[left_top] < a[right_top])
        {
            t[index++] = a[left_top++];
        }
        else
        {
            t[index++] = a[right_top++];
        }
    }
    //下面两个while循环
    //作用是将还没有取尽的数组元素放入merge时的暂存数组中
    while (left_top <= mid)
    {
        t[index++] = a[left_top++];
    }
    while (right_top <= to)
    {
    t[index++] = a[right_top++];
    }
    //将merge暂存数组的结果给原数组
    for (int i = 0; i <= count; i++)
    {
        a[from++] = t[i];
    }
}

void merge_sort(int from, int to, int* a)
{
    if (from < to)
    {
        //分解问题
        int mid = (from + to) / 2;
        merge_sort(from, mid, a);
        merge_sort(mid + 1, to, a);
        //开始合并
        merge(from, mid, to, a);
    }
}

void main()
{
    int count, *p;
    printf("please input the count :");
    scanf_s("%d", &count);
    p = (int *)malloc(count * 2);
    printf("\nplease input the number to be sorted : \n");
    for (int i = 0; i < count; i++)
    {
        scanf_s("%d", p+i);
    }

    merge_sort(0, count-1, p);

    for (int i = 0; i < count; i++)
    {
        printf("%d ", p[i]);
    }
    system("pause");
}

3)分析:上面实现的MERGE_SORT算法在输入的数字数量为奇数和偶数的时候都可以正常的工作,但是这里我们为了方便分析效率,将问题的规模假设为2的幂,在每次分解问题的时候都可以分成n/2。我们按照三个步骤来分析效率:

  • 分解:分解步骤只需要找到数组的中间位置,因此时间是常数O(1)。
  • 解决:分解之后,需要递归的求解两个规模为n/2的子问题,花费时间为2T(n/2)。
  • 合并:将两个长度为n/2是的数组合并成一个长度为n的数组,相当于将n个元素都遍历了一遍,时间复杂度为O(n)。

因此我们可以写出T(n)和T(n/2)的关系表达式,T(n) = 2T(n/2) + cn(c为常数);后面会分析可以从这个式子导出T(n) = O(nlgn)。

时间: 2024-08-27 12:27:56

归并排序(MERGE_SORT)的相关文章

疯子的算法总结(六) 复杂排序算法 ① 归并排序 merge_sort()

归并排序采取了分治的思想,每次分别排左半边和右半边,不断递归调用自己,直到只有一个元素递归结束,开始回溯,调用merge函数,合并两个有序序列,再合并的时候每次给末尾追上一个最大int这样就不怕最后一位的数字不会被排序. #include <bits/stdc++.h> using namespace std; void merge(int a[],int n,int left ,int mid,int right); void merge_sort(int a[],int n,int lef

【Algorithm】自顶向下的归并排序

一. 算法描述 自顶向下的归并排序:采用分治法进行自顶向下的程序设计方式,分治法的核心思想就是分解.求解.合并. 先将长度为N的无序序列分割平均分割为两段 然后分别对前半段进行归并排序.后半段进行归并排序 最后再将排序好的前半段和后半段归并 过程(2)中进行递归求解,最终下图详细的分解了自顶向下的合并算法的实现过程: 二. 算法实现 /*============================================================================= #

插入排序和归并排序的实现代码(C++)

插入排序和归并排序是算法导论先讲到的两中排序方法. 插入排序的思路是对于一个已经排好序的数组,现在新插入一个元素并且保持其有序.那么该如何插入呢,从数组最后一个元素开始进行比较,直到遇到比小于等于自己的元素,然后插入到该元素的后面(所以插入是稳定的).循环不变式:子数组一直保持有序(使用循环不变式来证明算法正确性的方法类似于高中经常用的数学归纳法). 归并排序的思想就是很有名的分治思想(divide and conquer).从较小的多个有序数组得到较大的有序数组即合并,归并排序采用二路归并.多

九种经典排序算法详解(冒泡排序,插入排序,选择排序,快速排序,归并排序,堆排序,计数排序,桶排序,基数排序)

综述 最近复习了各种排序算法,记录了一下学习总结和心得,希望对大家能有所帮助.本文介绍了冒泡排序.插入排序.选择排序.快速排序.归并排序.堆排序.计数排序.桶排序.基数排序9种经典的排序算法.针对每种排序算法分析了算法的主要思路,每个算法都附上了伪代码和C++实现. 算法分类 原地排序(in-place):没有使用辅助数据结构来存储中间结果的排序**算法. 非原地排序(not-in-place / out-of-place):使用了辅助数据结构来存储中间结果的排序算法 稳定排序:数列值(key)

八种排序算法

最近一段时间自己在研究各种排序算法,于是自己写了一个八种排序算法的集合: /************************************************************************* > Copyright (c)2014 stay hungry,stay foolish !!! > File Name: sort.cpp > Author: kanty > Mail: [email protected] > Created Time:

所有的排序、查找算法

import javax.mail.Part; /** * 顺序查找.排序 * * @author 曾修建 * @version 创建时间:2014-7-30 下午04:15:10 */ public class SequentialSearch { public static void main(String[] args) { Integer[] a = {1,2,3,4,5,7,6,88}; //二分查找非递归 System.out.println( "二分查找非递归实现 位置 : &qu

常用排序算法比较与分析

一.常用排序算法简述 下面主要从排序算法的基本概念.原理出发,分别从算法的时间复杂度.空间复杂度.算法的稳定性和速度等方面进行分析比较.依据待排序的问题大小(记录数量 n)的不同,排序过程中需要的存储器空间也不同,由此将排序算法分为两大类:[内排序].[外排序]. 内排序:指排序时数据元素全部存放在计算机的随机存储器RAM中. 外排序:待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中还需要对外存进行访问的排序过程. 先了解一下常见排序算法的分类关系(见图1-1) 图1-1 常见排

给一已经排序数组A和x,求A中是否包含两个元素之和为x

亲爱的大神老爷们,这是小渣第一次写blog,欢迎大家来喷(批评指正),算法渣因为面试中连这道题都不会写就自己琢磨了一下,也参考了网上大家的做法 解法一: 思路:从首尾向目的靠拢,因为已经排序,[假设存在A[i]+A[j]=x]  (i<j:这样的i,j对可能不止一对,只要确保如果存在这样的i,j对,设计的算法一定能找到其中一对算法就算有效,该算法找到的是[最小i和最大j]那一对,那么在查找过程中始终有:[A[head]<=A[i]&&A[j]<=A[tail]]): 在靠

大话快排 和 归排的渊源

一:起因 (1)包括冒泡算法.快排算法.插入排序算法等:还有基于外部排序的归并排序(以二路归并排序为例 ) 但是基本上在一个数量级上: (2) mergesort (归并排序) 可以应用在外部排序,这与基于内存的quicksort(快速排序)略有不同,他们的算法复杂度都可以达到O(nlogn) (3)mergesort 是稳定的排序算法,需要额外的空间开销O(n):quicksort 是非稳定的排序算法,额外的空间开销O(1):两者的核心思想都来源与分支的策略(divide and conque