408数据结构学习笔记——归并排序、基数排序

目录

1.归并排序

1.1.算法思想

1.2.代码

1.3.时间复杂度和稳定性

2.基数排序

2.1.算法思想

2.2.手算实现过程

2.3.时间复杂度和稳定性

2.4.基数排序的应用


1.归并排序

1.1.算法思想

归并:把两个或者多个有序的序列表合并成一个(m路归并,每选出一个元素需要关键字为m - 1个)

将相邻的两个有序表归并为一个有序表 

1.将顺序表中每两个相邻元素分为一组,进行排序:分组(49、38)(65、97)(66、13)(27)

2.将重复1操作直到序列有序:分组(38、49、65、97)(13、76、27)

3.整个数组为一组,进行排序后,整组有序

1.2.代码

//全局变量,申明一个大小为n + 1的数组(可以容纳下所有的数组元素)
elemtype *temp = (elemtype*)malloc(sizeof(elemtype) * (n + 1));
void Merge(int arr[], int low, int mid, int high){
    //将arr数组元素复制到temp中
    for (int k = low; k <= high; k++) temp[k] = arr[k];
    int i, j, k;
    //遍历数组
    for (i = low, j = low, k = mid + 1; j <= mid && k <= high; i++) {
        //将j和k指向的元素中更小的那个插入表中,并且其对应的指针往后移动
        if (temp[j] <= temp[k]) arr[i] = temp[j++];    //两个子表若元素相同,则优先选择左子表
        else arr[i] = temp[k++];
    }
    //将剩余元素插入到表中
    while (j <= mid) arr[i++] = temp[j++];
    while (j <= mid) arr[i++] = temp[k++];
}

void MergeSort(int arr[], int low, int high){
    if (low < high) {
        int mid = low + high / 2;
        //对左子表进行排序
        MergeSort(arr, low , mid);
        //对右子表进行排序
        MergeSort(arr, mid + 1, high);
        //对当前整个表进行排序
        Merge(arr, low, high);
    }//if
}

1.3.时间复杂度和稳定性

1.时间复杂度:O(nlog2n)

A.归并的过程类似二叉树,树高即为归并总次数→O(log2n)向上取整

B.每次归并的时间复杂度为O(n),指针需要从头到尾遍历一次数组

2.空间复杂度:O(n),辅助数组B需要复制数组元素

3.稳定性:稳定。左右两个数组中若同时出现相同元素,则优先将左边的元素加入数组中

2.基数排序

2.1.算法思想

不基于比较的算法

基于关键字的各个位数的大小进行排序

1.初始化r个队列,按照关键字的权值递增的顺序(个十百),进行关键字总位数分配和收集

2.分配:遍历各个元素,根据当前轮次的关键字和当前元素的关键字位插入相应的链表中

3.收集:将各个队列中的元素依次出队,并首尾相接形成新的序列 

2.2.手算实现过程

1.初始状态,申明十个队列分别表示当前位数上的数字为0 - 9

2.以个位进行匹配,按当前数字的个位入队到相应的队列中

3.为得到递减序列,按9 - 0 的顺序将各个队列中的元素依次出队,并首尾相接形成新的序列(实现按个位递减)

4.基于3中结果,以十位进行匹配,按当前数字的十位挂到入队相应队列中。因为已经对个位排序,因此,每个队列中的元素按照个位递减的顺序排列

5.为得到递减序列,按9 - 0 的顺序将各个队列中的元素依次出队,并首尾相接形成新的序列(实现按十位递减、十位相同按个位递减)

6. 基于5中结果,以十位进行匹配,按当前数字的十位入队相应队列中。因为已经对十位排序,因此,每个队列中的元素按照十位递减的顺序排列

6.为得到递减序列,按9 - 0 的顺序将各个队列中的元素依次出队,并首尾相接形成新的序列(实现按百位递减、百位相同按十位递减、十位相同按个位递减)

 

2.3.时间复杂度和稳定性

1.空间复杂度:需要r个队列,每个队列需要的仅是头尾指针。O(r)

2.时间复杂度:O(d(n + r))

A.需要进行d趟(关键字个数)O(d)

B.每趟进行一次分配遍历 n 个元素O(n),一趟收集遍历r个队列O(r)。O(n + r)(可以为每个队列结构体中设置一个队尾元素指针,遍历队列的过程中将队尾指针的next域指向下一个队列的队首元素,不需要遍历队列中全部元素)

3.稳定性:稳定

2.4.基数排序的应用

例:生日(日→月→年)

1.数据元素可以被拆分为d个关键字(d不宜过大)(反例:身份证)

2.每个关键字的取值范围不大(反例:中文名字,虽然只有几个字,但是每个字有几千种可能)

3.数据元素的个数 n 很大(例子:给全中国人的身份证排序)

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值