排序3——C语言

news/2024/9/23 6:27:35/

排序

  • 1. 归并排序
  • 2. 计数排序
  • 3. 各排序的稳定性及复杂度

1. 归并排序

归并排序是建立在归并操作上的一种有效的算法>排序算法,该算法是采用分治法的一个非常典型的应用。

思路:将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
下图为归并的全过程
在这里插入图片描述
将序列分割,若子区间无序,对子区间再分割,直至子区间有序(只有一个数时)再进行合并(相当于合并两个有序数组)。合并数据时,不能直接覆盖再原数组,会造成数据丢失,因此需要开辟一个辅助数组。

//归并排序
//复杂度O(N*logN)
void _MergeSort(int* array, int* tmp, int begin, int end)//左右闭区间
{//只有一个值,不用归并if (begin == end)return;//分成两组分别递归,归并int mid = (begin + end) / 2;_MergeSort(array, tmp, begin, mid);_MergeSort(array, tmp, mid + 1, end);int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;//归并过程while (begin1 <= end1 && begin2 <= end2){if (array[begin1] <= array[begin2]){tmp[i++] = array[begin1++];}else{tmp[i++] = array[begin2++];}}while (begin1 <= end1){tmp[i++] = array[begin1++];}while (begin2 <= end2){tmp[i++] = array[begin2++];}//拷贝回原数组memcpy(array + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}void MergeSort(int* array, int numsArr)
{//开辟辅助数组int* tmp = (int*)malloc(sizeof(int) * numsArr);if (tmp == NULL){return;}_MergeSort(array, tmp, 0, numsArr - 1);free(tmp);tmp = NULL;
}

归并排序的缺点,空间复杂度为O(N),即额外需要一块辅助空间。

2. 计数排序

计数排序的思路:

  1. 统计相同元素出现次数(遍历一遍数据即可)
  2. 根据统计的结果将序列回收到原来的序列中

举例如下图
在这里插入图片描述
这里会面临两个问题

  1. 数据过大,数据范围分散
  2. 数据有负数,下标没有负数
    问题一会导致一个问题,开的辅助空间很大,比如数据为{ 1 ,19 ,33,50,69},五个数需要开辟70个空间,太浪费。事实上,计数排序不适用于数据范围分散的情况,如果当数据范围很大很 分数时,就不要采用计数排序了。

问题二可以采用相对映射的方法来解决。让每一个数都减去最小值,那么如果有负数,减去最小值(也是负数,可能是本身)之后的值肯定大于等于0,就可以满足数组的下标了。还原回去时,数据再加上最小值即可。

//计数排序
//时间复杂度O(N+range),空间复杂度O(range)
//适合于数据范围小的情况
void CountSort(int* array, int numsArr)
{//最大最小值int max = array[0], min = array[0];for (int i = 1; i < numsArr; i++){if (array[i] < min)min = array[i];if (array[i] > max)max = array[i];}//开空间int range = max - min + 1;int* count = (int*)calloc(range, sizeof(int));if (count == NULL)return;//统计每个数出现的次数(相对映射)for (int i = 0; i < numsArr; i++){count[array[i] - min]++;}//修改数组int j = 0;for (int i = 0; i < range; i++){while (count[i]--){array[j++] = i + min;}}
}

3. 各排序的稳定性及复杂度

有关常见排序就介绍完毕了,总结一下复杂度和稳定性。一个排序的稳定性是指,两个相同的值在排序前后的相对位置没有改变,则该排序为稳定排序。否则不稳定。

冒泡排序
相邻数据不等才会进行交换,因此为稳定排序。时间复杂度:O(N^2)空间复杂度O(1)

直接插入排序
数据不相等才会进行插入,两个相等的数,在插入前后不会改变相对位置,因此为稳定排序
时间复杂度O(N^2)空间复杂度O(1)

归并排序
稳定排序,时间复杂度O(N*logN)空间复杂度O(N)

希尔排序
不稳定排序,且看下面的例子。时间复杂度O(N^1.3)空间复杂度O(1)
在这里插入图片描述
直接选择排序
不稳定,例子如下图,时间复杂度O(N^2)空间复杂度O(1)
在这里插入图片描述
堆排序
不稳定,例子如下图,时间复杂度O(N*logN)空间复杂度O(1)
在这里插入图片描述

快速排序
不稳定,例子如下图,时间复杂度O(N*logN)空间复杂度O(logN)
在这里插入图片描述
总结:三稳定四不稳定。关于常用排序就介绍完了。


http://www.ppmy.cn/news/1441457.html

相关文章

四川省建设工程技术人员职称申报评审基本条件

四川省建设工程技术人员职称申报评审基本条件链接四川省住房和城乡建设厅 四川省人力资源和社会保障厅关于印发《四川省建设工程技术人员职称申报评审基本条件》的通知_文件通知_四川省住房和城乡建设厅类别基本条件业绩成果备注助理工程师1.具备硕士学位或第二学士学位&#x…

MySQL第一次作业

解压完安装包 以管理员进入命令行 初始化并记住初始随机密码 创建服务名称 启动mysql 使用随机密码登录 修改密码 退出并重登服务器 MySQL创建数据库和表 创建数据库 创建表 1.进入数据库 创建表 向表中插入数据

冰箱主控 32位MCU,多通道、高精度的AD采样配合温度传感器,实现冰箱各温室的精确控温;低功耗设计

概览 小华高性价比32位MCU&#xff0c;多通道、高精度的AD采样配合温度传感器&#xff0c;实现冰箱各温室的精确控温&#xff1b;低功耗设计&#xff0c;绿色低碳、节能环保&#xff1b;模块化设计&#xff0c;充分利用丰富的通讯接口&#xff0c;使主控板、显示板和驱动板灵活…

求三个字符数组最大者(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <string.h>int main() {//初始化变量值&#xff1b;int i 0;char str[3][20];char string[20];//循环输入3个字符…

【ZZULIOJ】1084: 计算两点间的距离(多实例测试)(Java)

目录 题目描述 输入 输出 样例输入 Copy 样例输出 Copy code 题目描述 输入两点坐标&#xff08;X1,Y1&#xff09;,&#xff08;X2,Y2&#xff09;,计算并输出两点间的距离。 输入 输入数据有多组&#xff0c;每组占一行&#xff0c;由4个实数组成&#xff0c;分别表…

QT入门:计算圆面积的QT开始以及日历相关

QT入门&#xff1a;计算圆面积的QT开始以及日历相关 使用的工具为Qt creator 如图所示的为Qt的一个基本目录&#xff0c;首先打开mainwindow.ui进行设计&#xff0c;首先是讲解日历的&#xff0c;可以完全不用写代码&#xff0c;只在mainwindow.ui即可实现。 这是最后的一个成…

vue3路由跳转传递参数: params传参接收不到?

params方法传递参数优势&#xff1a; 1.不可见 2.不会造成地址栏不美观 传统写法&#xff1a; router地址必须是name方法跳转&#xff0c;接收&#xff1a;route.params import { useRouter } from "vue-router";const router useRouter(); // 提现记录 const wi…

【OceanBase诊断调优】——hpet(高精度时钟源)引起的CPU高问题排查

最近总结一些诊断OCeanBase的一些经验&#xff0c;出一个【OceanBase诊断调优】专题出来&#xff0c;也欢迎大家贡献自己的诊断OceanBase的方法。 1. 前言 昨天在问答区帮忙排查一个用户CPU高的问题&#xff0c;帖子链接&#xff1a;《刚刚新安装的OceanBase集群&#xff0c;…