自顶向下合并排序

/**
 * -*- coding : GBK -*-
 * @Author : huangshengjiang
 * @Email : 1005542693@qq.com
 * @Date : 2016-10-28 13:59
 * @Last Modified Date : 2016-11-10 18:46
 * @FileName : 自顶向下合并排序.cpp
 */

/*自顶向下合并排序
    基本概念 : 从上往下递归调用的排序,与自底向上合并排序相反
    应用场景 : 分解思想,将大问题分解成小问题,主要是分析程序代码.
    局限性 : 与自底向上排序比较,两者时间复杂度一样,另外前者比后者需要额外的空间,但是自顶向下有利于分析理解.
    具体需求 : 将无序的数组A排序成从小到大的数组
        输入 : 一组无序的数组A
        输出 : 有序的数组

    分析 : 自顶向下实际上是将数组划分成多个小数组,并对每个小数组按相同方法递归调用.
           这里使用的是二分法(每次讲数组划分为2个部分),其递归基础是小组个数为1.
        时间复杂度 : O(nlogn)
        空间复杂度 : O(1)
 */
#include <iostream>
#include <vector>
using namespace std;
//辅助函数
template<class T>
int Size(T &array)
{
    return sizeof(array)/sizeof(array[0]);
}
vector<int> buffer;
void merge(int *a,int left,int mid,int right)//合并数组a的两个部分,
                                    //left表示最左边位置,mid表示左边最后位置,right表示最右边位置,下标都在[0...n-1]范围内
                                    //由于每次需要额外的空间暂时存放数据,因此建议在外面直接申请一个数组
{
    int i,j;
    int t;

    i = left ; 
    j = mid + 1 ;
    t = 0 ; 

    while(i <= mid && j <= right) {//i,j都在合理范围内,没有过界,当某个达到边界,则跳出循环
        if (a[i] <= a[j])
        {
            buffer[t++] = a[i++];
        }
        else{
            buffer[t++] = a[j++];
        }
    }

    //右边已经遍历完
    while(i <= mid) {
        buffer[t++] = a[i++] ;
    }

    //左边已经遍历完
    while(j <= right) {
        buffer[t++] = a[j++] ;
    }

    //赋值
    i = left ;
    for (int k = 0; k < t; ++k)
    {
        a[i++] = buffer[k];
    }
}

//函数
void mergesort(int *a,int left,int right)
{
    if( left == right) return ; 
    int mid = (left + right) / 2 ; //由于/的特性,两个临近值相加/2,是左边的值.因此merge的参数mid是指左边的最后位置
    mergesort(a,left,mid) ;
    mergesort(a,mid+1,right) ;
    merge(a,left,mid,right) ;//后序遍历,先左再右最后根
}

void sort(int *a,int n)
{
    mergesort(a,0,n-1);
}

//测试
int main(int argc, char const *argv[])
{
    int a[] = {3,5,8,5,45,4,6,8,9};
    int n = Size(a);
    buffer.resize(n);
    
    sort(a,n);

    for (int i = 0; i < n; ++i)
    {
        cout << a[i] <<" ";
    }
    cout<<endl;

    system("pause");
    return 0;
}

转载于:https://www.cnblogs.com/jiangge3/articles/6052041.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值