二路归并排序

hello 你好放松放松发顺丰的说法都是付水电费水电费的说法适当放松的方式水电费水电费水电费时代发生的付水电费水电费水电费地方发送到水电费水电费算法水电费水电费算法速度付水电费速度付水电费水电费算法水电费水电费水电费沙发上地方是水电费水电费水电费水电费算法算法水电费杀毒分水电费杀毒付水电费算法水电费算法水电费算法算法水电费是方式发送到 是非颠倒

题目描述

使用归并排序对n个元素进行排序。

题目分析

归并排序算法是用分治策略实现对n个元素进行排序的算法。其基本思想是:

将待排序元素分成大小大致相同的2个子集合,分别对2个子集合进行排序,最终将排好序的子集合合并成为所要求的排好序的集合。

image

算法实现

#include <stdio.h>
#define N 7

void merge(int a[],int left,int mid,int right);

void mergeSort(int a[],int left,int right)
{
    if (left < right)
    {
        int mid = (left+right)/2;    // 从中间划分两个子序列
        mergeSort(a,left,mid);        // 对左侧子序列进行递归排序
        mergeSort(a,mid+1,right);    // 对右侧子序列进行递归排序
        merge(a,left,mid,right);    // 归并
    }
}

// 一趟归并排序算法
int b[N];
void merge(int a[],int left,int mid,int right)
{
    // 表a的两段a[left..mid]和a[mid+1..right]各自有序,将它们合并成一个有序表
    for (int m=left;m<=right;m++)
        b[m] = a[m];                    // 将a中所有元素复制到b中
    for (int i=left,j=mid+1,k=i;i<=mid&&j<=right;k++)
    {
        if(b[i]<=b[j])                    // 比较b的左右两段中的元素
            a[k]=b[i++];                // 将较小值复制到a中
        else
            a[k]=b[j++];
    }
    while (i<=mid)      a[k++]=b[i++];    // 若第一个表为检测完,复制
    while (j<=right)  a[k++]=b[j++];    // 若第二个表为检测完,复制
    // 最后两个while循环只有一个会执行
}

int main()
{
    int a[] = {49,38,65,97,76,13,27};
    mergeSort(a,0,N-1);
    for (int i=0;i<N;i++)
        printf("%d ",a[i]);
    printf("\n");
    return 0;
}

image

复杂度分析

归并排序的时间主要分为“分-治-合”的时间。划分子序列是在常数时间内完成,最后的归并操作又可以在线性时间内完成。因此,对长度为n的元素序列进行归并排序的时间代价为

image

归并排序时间复杂度为O(nlogn),空间复杂度为O(n),并且它是一种稳定的排序方法。

PS:如果在待排序列中有两个记录Ri和Rj,它们的关键字ki=kj,且在排序之前,记录Ri排在Rj前面,如果在排序之后,记录Ri仍在Rj的前面,则称所用的排序方法时稳定的。是否具有稳定性仅是对算法的性质的描述,而并不能代表算法的优劣。

posted @ 2015-05-16 11:18  枯桃  阅读(1136)  评论(0编辑  收藏  举报