数据结构学习笔记(17)---归并排序与基排序

(1)归并排序

算法思想:
(1)对于一个人数组,首先把数组平均分为两部分,即[low,mid]和[mid+1,high],
(2)分别对左右两部分进行再进行归并排序。
(3)将左右两步部分合并
例如以下例子:开始将数据看成长度为1的有序表,两两归并为长度为2的表,依次类推直到长度为n的有序表

性能分析:平均时间复杂度O(nlogn),空间复杂度O(1),比较稳定

代码:

void Merge(int pNew[], int low,int  mid,int  high,int  b[])
{
    int k = 1,i = low, j = mid + 1;
    while (i<=mid && j<= high)
    {
        if (pNew[i] < pNew[j])
        {
            b[k] = pNew[i];
            k++;
            i++;
        }
        else
        {
            b[k] = pNew[j];
            k++;
            j++;
        }
    }
    while (i <= mid)
    {
        b[k] = pNew[i];
        i++;
        k++;
    }
    while (j <= high)
    {
        b[k] = pNew[j];
        j++;
        k++;
    }
}
void MSort(int a[], int low, int high, int b[])
{
    //申请一个辅助空间,用来存放数组a的mid两边的已经归并好的数
    int pNew[12];
    //判断low与high是否相等,如果相等就直接可以放到,不需要归并排序了
    if (low == high)
    {
        b[low] = a[low];
    }
    else
    {
        int mid = (low + high) / 2;
        //对mid左边的数进行归并排序
        MSort(a, low, mid, pNew);
        //对mid右边的数进行归并排序
        MSort(a, mid + 1, high, pNew);
        //合并pNew中左右数
        Merge(pNew, low, mid, high, b); 
    }
}
void MergeSort(int a[],int len)
{
    MSort(a, 1, len, a);//做归并排序
}
(2)基数排序在, 比较适用于元素数值位数相差不大时候最好

算法思性:
(1)首先要有是个桶,其实就是十个队列,元素值得各位对应着桶的编号。
(2)把桶中数据一一拿出来放回原数组,比较元素的十位数,按十位数的大小与桶的编号对应起来。
(3)这时候再把桶中拿出来放回原数组,比较元素的百位数,操作和上面相同,直到到达位数中最大结束,这时候就是有序的了。
例子:例子: B = 5、2、9、7、18、17、52 用基数排序法进行排序。
首先根据元素的个位数放入各个桶:

收集桶中元素为:2 , 52, 5, 7, 17, 18, 9,再按十位放入桶

收集桶中元素为:2,,5,7,9,17,18,52,所以最后得到排序。

性能分析: 时间:上例中每个数有 t = 2 位,因此执行 t = 2 次分配和收集就可以了。在一般情况下,每个结点有 d 位关键字,必须执行 t = d次分配和收集操作。分配的代价:O(n) ,收集的代价:O(rd(rd是基数),总的代价为:O( d ×(n + rd)).

代码:

#define MAXSIZE 20
#include <queue>
queue<int> sta[10];
void RadixSort(int a[], size_t length)
{
    int NumSum = 1;//表示数组中元素最大位数
    while (NumSum!=4)
    {
        for (size_t i = 0; i < length; i++)
        {
            int n = (a[i] % (int)pow(10, NumSum)) / (pow(10, NumSum-1));
            sta[n].push(a[i]);
        }
        int k = 0;
        for (int i = 0; i < 10; i++)
        {
            while (!sta[i].empty())
            {
                a[k] = sta[i].front();
                sta[i].pop();
                k++;
            }
        }
        NumSum++;
    }
}
(3)小结:
排序方法平均时间复杂度最坏时间复杂度空间复杂度稳定性
归并排序O(nlogn)O(nlogn)O(n)稳定
基数排序O(d(n+rd))O(d(n+rd))O(rd)稳定

R是关键字的取值范围,d是位数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值