当前位置: 首页 > article >正文

数据结构和算法|排序算法系列(五)|排序总结(时间复杂度和是否稳定)

文章目录

  • 选择排序
  • 冒泡排序
  • 插入排序
  • 快排
  • 归并排序
  • 堆排序

选择排序

一句话总结,开启一个循环,每轮从未排序区间选择****最小的元素,将其放到已排序区间的末尾。「未排序区间一般也放在后面,已排序区间放在前面」

选择排序

  • 时间复杂度:O(n^2)
  • 非稳定排序
void selectionSort(vector<int>& nums) {
	// 未排序区间逐渐缩小
	for (int i = 0; i < nums.size(); i++) {
		int k = i;
		// 找到未排序区间中最小的值与排序区间最后一个值交换
		for (int j = i + 1; j < nums.size(); j++) {
			if (nums[j] < nums[k]) k = j;
		}
		swap(nums[i], nums[k]);
	}	
}

冒泡排序

通过连续得比较与交换相邻元素实现排序。这个过程就像气泡从底部升到顶部一样

冒泡过程可以利用元素交换操作来模拟:从数组最左端开始向右遍历,依次比较相邻元素的大小,如果“左元素>右元素”就交换二者。遍历完成后,最大的元素会被移动到数组的最右边。

<交换完成后,最大的泡泡浮出水面>

在这里插入图片描述
与选择排序的未排序区间不一样:
冒泡排序的未排序区间是前面的元素。

void bubbleSort(vector<int> &nums) {
    // 外循环:未排序区间为 [0, i]
    for (int i = nums.size() - 1; i > 0; i--) {
        // 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
        for (int j = 0; j < i; j++) {
            if (nums[j] > nums[j + 1]) {
                // 交换 nums[j] 与 nums[j + 1]
                // 这里使用了 std::swap() 函数
                swap(nums[j], nums[j + 1]);
            }
        }
    }
}

时间复杂度O(n^2)
稳定排序:在“冒泡”中遇到相等元素不交换

插入排序

插入排序像手动整理手牌一样。

分两个区,排序区和未排序区。

在未排序区间选择一个基准元素,将该元素与其左侧已排序区间的元素逐一比较大小,并将该元素插入到正确的位置。

一句话就是把第一个元素定为已排序区,然后把未排序区的第一个元素作为待定元素插入到一排序区中。


算法流程:

  1. 初始状态下,第一个元素已经完成排序;
  2. 选取第二个元素作为 base ,将其插入到正确位置后,此时已排序区中有两个元素
  3. 以此类推,最后一轮中,选取最后一个元素作为 base,将其插入到正确位置后,所有元素均已排序。

在这里插入图片描述

voidd insertSort(vector<int> &nums) {
	// 外循环:已排序区[0, i - 1]
	for (int i = 1; i < nums.size(); i++) {
		int base = nums[i], j = i - 1;
		// 内循环来插入
		while (j >= 0 && nums[j] > base) {
			nums[j + 1] = nums[j];//指针向右移
			j--;
		}
		nums[j + 1] = base; // 将 base 赋值到正确位置
	}
}

时间复杂度O(n^2)
稳定排序

快排

时间复杂度和平均时间复杂度均为O(nlog^n)
非稳定排序

归并排序

有划分阶段和合并阶段
非常像我们的后序遍历。

时间复杂度O(nlogn)

与快排相比,他的缓存命中率低,并且不是原地排序,也就是说需要额外的空间。

稳定排序

堆排序

用建堆操作和元素出堆操作实现堆排序;

  1. 输入数组并建立小顶堆,此时最小元素位于堆顶。
  2. 不断执行出堆操作,依次记录出堆元素,即可得到从小到大的序列。

时间复杂度O(nlogn)

非稳定排序


http://www.kler.cn/news/314870.html

相关文章:

  • 前端-js例子:定时器
  • HarmonyOS开发实战( Beta5.0)使用GTest测试C++案例
  • QT开发: Qt 框架中字符串核心类QString详解
  • ARM/Linux嵌入式面经(三五):诺瓦星云提前批
  • dpdk课程学习之练习笔记八(dpvs的了解)
  • unity3d入门教程九
  • 【Java】全面理解Java8特性
  • SpinalHDL之结构(三)
  • JavaScript高级—— js 是单线程运行的
  • 无人机+自组网:中继通信增强技术详解
  • 论文解读《MmAP : Multi-Modal Alignment Prompt for Cross-Domain Multi-Task Learning》
  • C#开发基础之单例模式下的集合数据,解决并发访问读写冲突的问题
  • PostgreSQL常用表操作SQL脚本整理
  • java重点学习-JVM类加载器+垃圾回收
  • 从一到无穷大 #35 Velox Parquet Reader 能力边界
  • 计算机基础知识笔记
  • 基于协同过滤+python+django+vue的音乐推荐系统
  • 鸿蒙Harmony-Next 徒手撸一个日历控件
  • Qt中样式表常用的属性名称定义
  • 利用Python与Ansible实现高效网络配置管理
  • 【Harmony】轮播图特效,持续更新中。。。。
  • Ubuntu24.04 安装ssh开启22端口及允许root用户远程登录
  • 【Flink实战】flink消费http数据并将数组展开多行
  • linux-虚拟化与容器化-虚拟化
  • 无法删除选定的端口,不支持请求【笔记】
  • Java流程控制语句——跳转语句详解:break 与 continue 有什么区别?
  • Go 并发模式:管道的妙用
  • biopython解析mmcif文件得到组装体、链、序列、原子坐标、变换矩阵等信息
  • 统信服务器操作系统【1050e版】安装手册
  • 十个服务器中毒的常见特征及其检测方法