数据结构 - 排序 | C (插入、希尔、选择、堆、冒泡)

news2024/12/23 12:59:05

目录

  • 0.排序
  • 思维导图(总)
  • 一、插入排序
    • 1.直接插入排序
        • 思路分析
        • 代码实现
        • 时间复杂度
    • 2.希尔排序
        • 思路分析
        • 代码实现
        • 时间复杂度
  • 二、选择排序
    • 1.选择排序
        • 思路分析
        • 代码实现
        • 时间复杂度
    • 2.堆排序
        • 思路分析
        • 代码实现
        • 时间复杂度
  • 三、交换排序
    • 冒泡排序
        • 思路分析
        • 代码实现
        • 时间复杂度

0.排序

// Sort.h
#pragma once

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include "Stack.h"

// 插入排序
void InsertSort(int* a, int n);

// 希尔排序
void ShellSort(int* a, int n);

// 选择排序
void SelectSort(int* a, int n);


// 堆排序
void AdjustDwon(int* a, int n, int root);
void HeapSort(int* a, int n);

// 冒泡排序
void BubbleSort(int* a, int n);

思维导图(总)

在这里插入图片描述

一、插入排序

1.直接插入排序

思路分析

  • 升序排序

  • 一个数插入一个升序列,找到不比自己大的数,插入在这个数的后面
    在这里插入图片描述

  • 具体是如何插入的:

    • 如下图,如果 a[end]>tmp 就往后挪动数据→a[end+1]=a[end]当找到 不比tmp大的数 之后,将tmp插入到这个数的后面→a[end+1]=tmp
      在这里插入图片描述
  • 因此,对于一个无序列,就是依次插入数据
    在这里插入图片描述

代码实现

// 插入排序
void InsertSort(int* a, int n)
{
	assert(a);
	for (int i = 1; i < n; i++)
	{
		int tmp = a[i];
		int end = i - 1;
		while (end >= 0)
		{
			if (a[end] <= tmp)
			{
				break;
			}
			a[end + 1] = a[end--];
		}
		a[end + 1] = tmp;
	}
}

时间复杂度

  • 最坏的情况:排升序,但原数列为降序
    array[0]挪动数据并插入的次数为:0;
    array[1]挪动数据并插入的次数为:1;
    array[2]挪动数据并插入的次数为:2;
    array[3]挪动数据并插入的次数为:3;
    …………
    array[n]挪动数据并插入的次数为:n;
    Σ = 0+1+2+3+……+n = (1+n)*n/2

时间复杂度O(N)=N²

  • 最好的情况:时间复杂度O(N)=N

插入排序的适应性很强,对于有序、局部有序的情况,都能效率提升

2.希尔排序

思路分析

为了优化直接插入,我们选择进行预排序,让较大的位于前列的数先排到较后面的位置,以此减少挪动数据的次数
在这里插入图片描述
预排序:分组,每组进行插入排序

下图以gap==3为例
在这里插入图片描述
在这里插入图片描述
gap的变化:

while(gap)
{
	int gap = n / 2;
	gap /= 2;
}
//当gap==1时就是直接插入排序
//or
while(gap)
{
	int gap = n / 3;
	gap = (gap/3 + 1);
}

代码实现

// 希尔排序
void ShellSort(int* a, int n)
{
	assert(a);

	int gap = n / 2;
	while (gap)
	{
		for (int i = 1; i < n; i++)
		{
			int tmp = a[i];
			int end = i - gap;
			while (end >= 0)
			{
				if (a[end] <= tmp)
				{
					break;
				}
				a[end + gap] = a[end];
				end -= gap;
			}
			a[end + gap] = tmp;
		}
		gap /= 2;
	}
}

时间复杂度

希尔排序的时间复杂度算起来很复杂,预排序之后无法确定数列的顺序情况。
这里直接给结果:O(N)=N^1.3

二、选择排序

1.选择排序

思路分析

遍历数组(以排升序为例)
找到最一小的数与数组第一个位置的数交换;
找到第二小的数与数组第二个位置的数交换;
……(依次类推)
在这里插入图片描述

优化:两头缩进
从数组的头和尾开始,在中间(区间为👉[begin,end])同时找最大和最小的数,找到分别与“两头的数”交换,依次类推,“两头缩进”
在这里插入图片描述
找到后 Swap ↓

Swap(&a[begin], &a[mini]);
Swap(&a[end], &a[maxi]);
++begin;
--end;
  • 注意!:Swap之后:begin → min ; mini → original-a[begin]
    • 如果 original-a[begin] → max 则会影响 a[maxi] =? max
      if (begin == maxi)即如果原本 begin 指向的数是 max,则 Swap 之后这个数已经被交换到了 mini 所指向的位置
    • end 指向的数是否改变不影响,因为,我们只是要把 max 放在最后面的位置(同时保持数据不丢失)
    • 就是说 ,begin 代表头部的位置,end 代表尾部的位置;mini 是最小值的下标,maxi 是最大值的下标
      在这里插入图片描述

代码实现

//优化后:
void Swap(int* x, int* y)
{
	assert(x && y);
	int tmp = *x;
	*x = *y;
	*y = tmp;
}

// 选择排序
void SelectSort(int* a, int n)
{
	assert(a);
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int mini = begin, maxi = end;

		//[begin+1,end-1]
		for (int j = begin; j <= end; j++)
		{
			if (a[j] < a[mini])
				mini = j;
			if (a[j] > a[maxi])
				maxi = j;
		}
		//swap之前 min==a[mini]  max==a[maxi]
		Swap(&a[begin], &a[mini]);
		//swap之后:begin → min ; mini → original-a[begin]
		//if(original-a[begin] → max)则会影响 a[maxi] =? max
		if (begin == maxi)//如果原本begin指向的数是max,则swap之后这个数已经被交换到了mini所指向的位置
			maxi = mini;
		Swap(&a[end], &a[maxi]);
		++begin;
		--end;
	}
}

时间复杂度

未优化的算法:
从头找到尾
找到最一小的数与数组第一个位置的数交换,查找的次数为:n - 1;
找到第二小的数与数组第二个位置的数交换,查找的次数为:n - 2;
…………
最后一次查找次数为:1( n -(n-1))
Σ = 1+2+3+……+(n-1)= n*(n-1)/2

时间复杂度为O(N²)

2.堆排序

详细分析过程见→二叉树-堆| [堆的实现【建堆算法图解+分析】]

思路分析

排升序:建大堆。把数组按大堆的方式排列,此时堆顶就是最大的数,让堆顶与数组最后一个数交换,最大的数就被放在了数组的尾部。对于前面的部分,调整使其依旧为大堆,此时堆顶的数就是第二大的数……重复这个操作👉向下调整建堆,不断取堆顶的数
排降序:建小堆。思路同上。

代码实现

// 堆排序
void AdjustDwon(int* a, int n, int root)
{
	assert(a);
	int parent = root;
	int child = parent * 2 + 1;

	while (child < n)
	{
		if ((child + 1) < n && a[child + 1] > a[child])
			++child;
		if (a[parent] < a[child])
			Swap(&a[parent], &a[child]);
		else
			break;

		parent = child;
		child = parent * 2 + 1;
	}
}
void HeapSort(int* a, int n)
{
	assert(a);

	//建大堆
	for (int parent = (n - 1 - 1) / 2; parent >= 0; parent--)
	{
		AdjustDwon(a, n, parent);
	}

	//取堆顶的数据并向下调整
	int end = n - 1;
	while (end)
	{
		Swap(&a[0], &a[end]);
		AdjustDwon(a, end, 0);
		end--;
	}
}

时间复杂度

向下调整建堆的时间复杂度:O(N)

取堆顶数据然后向下调整时间复杂度:O(logN) → 重复 N次 → O(N*logN)

时间复杂度 为 O(N*logN)

三、交换排序

冒泡排序

思路分析

前后比较交换

以下列这个数组为例,展示一趟冒泡排序:
在这里插入图片描述
在这里插入图片描述

代码实现

// 冒泡排序
void BubbleSort(int* a, int n)
{
	assert(a);
	for (int j = 0; j < n; j++)
	{
		for (int i = 0; i < n - j - 1; i++)
		{
			if (a[i] > a[i + 1])
				Swap(&a[i], &a[i + 1]);
		}
	}
}

时间复杂度

第一趟冒泡排序:n-1次
第二趟冒泡排序:n-2次
……
第n趟冒泡排序:n-n次
Σ = 1 + 2 + 3 + …… + n-1 = n(n-1)/2

时间复杂度为O(N)=N²

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/425695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何基于vue实现倒计时效果

如何基于vue实现倒计时效果基于vue2 element实现画面效果代码基于vue2 element 实现画面效果 代码 <template><div><div class"Box"><div style"position: relative;"><el-progress type"circle" :width"30…

pytorch注意力机制

pytorch注意力机制 最近看了一篇大佬的注意力机制的文章然后自己花了一上午的时间把按照大佬的图把大佬提到的注意力机制都复现了一遍&#xff0c;大佬有一些写的复杂的网络我按照自己的理解写了几个简单的版本接下来就放出我写的代码。顺便从大佬手里盗走一些图片&#xff0c…

Vue3使用触摸滑动插件(Swiper)

Vue2使用触摸滑动插件&#xff08;Swiper&#xff09; 参考文档&#xff1a; Swiper官方 Swiper Vue Swiper Demos 本文使用的是最新版本&#xff1a;Swiper9.2.2 安装插件&#xff1a;yarn add swiper 本文基于Swiper插件进行封装&#xff0c;主要实现两种形式的轮播图展示…

电脑自带远程桌面和远程控制软件哪个好?

随着科技的不断发展和普及&#xff0c;越来越多的公司和个人开始关注远程控制软件的使用。我们常常需要在不同的地方工作&#xff0c;但工作需要的文件和软件却只能在一个地方使用&#xff0c;这时候远程控制电脑软件就变得尤为重要咯。但是&#xff0c;许多人分不清楚&#xf…

Windows远程连接工具有哪些

Windows远程连接工具&#xff0c;一般称为远程桌面软件&#xff0c;更准确的叫远程访问软件或远程控制软件&#xff0c;可以让你从一台电脑远程控制另一台电脑。远程桌面软件允许您控制连接的计算机&#xff0c;就好像它就在您面前一样。 远程桌面工具可用于技术支持、远程工作…

单TYPE-C口 可支持快充又可传输USB2.0数据方案

虽然现在有不少厂商也采用了Type-C接口&#xff0c;但是只作为一个充电接口&#xff0c;对于跨时代的type-c接口来说&#xff0c;多少有点大材小用&#xff0c; 那么有没有办法&#xff0c;让一个type-c接口既可以充电&#xff0c;又可以接OTG&#xff1f;比如不充电的时候可以…

Python一行命令搭建HTTP服务器并外网访问 - 内网穿透

文章目录1.前言2.本地http服务器搭建2.1.Python的安装和设置2.2.Python服务器设置和测试3.cpolar的安装和注册3.1 Cpolar云端设置3.2 Cpolar本地设置4.公网访问测试5.结语转载自远程内网穿透的文章&#xff1a;【Python】快速简单搭建HTTP服务器并公网访问「cpolar内网穿透」 1…

第二章:HTML CSS 网页开发基础(二)

CSS概述 CSS全称&#xff1a;Cascading Style Sheet&#xff0c;可以对文字进行重叠&#xff0c;定位。主要实现页面美化。 一、CSS规则 CSS样式表中包括了3部分&#xff1a;选择符、属性、属性值 选择符{属性:属性值;} 选择符&#xff1a;也可以称为选择器&#xff0c;所有…

Java实现输入行数打印取缔字符,打印金字塔三角形的两个代码程序

目录 前言 一、实现输入行数&#xff0c;打印取缔字符 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图 二、打印金字塔三角形 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图​​​​​​​ 前言 1.因多重原因&#xff0c;本博文有…

【BlazePose】《BlazePose: On-device Real-time Body Pose tracking》

arXiv-2020 文章目录1 Background and Motivation2 Advantages / Contributions3 Method4 Experiments5 Conclusion&#xff08;own&#xff09;1 Background and Motivation 人体关键点存在的难点&#xff1a;a wide variety of poses, numerous degrees of freedom, and occ…

JavaWeb—Maven

目录 1.什么是Maven 2.Maven的作用 3.Maven概述 3.1Maven介绍 3.2 Maven模型 3.3 Maven仓库 1.什么是Maven Maven是Apache旗下的一个开源项目&#xff0c;是一款用于管理和构建java项目的工具。 官网&#xff1a;Maven – Welcome to Apache Mavenhttps://maven.apache.o…

vscode 终端集成bash

windows 版本的 vs code 终端默认是没有集成bash的&#xff0c;虽然也能在vscode 终端可以提交git&#xff0c;但是没有高亮&#xff0c;没有提示&#xff0c;很不方便&#xff0c;这时候就需要我们将bash集成到vs code的终端&#xff0c;就可以愉快的使用git的分支高亮&#x…

阿里云蔡英华:云智一体,让产业全面迈向智能

4月11日&#xff0c;在2023阿里云峰会上&#xff0c;阿里云智能首席商业官蔡英华表示&#xff0c;算力的飞速发展使数字化成为确定&#xff0c;使智能化成为可能。阿里云将以云计算为基石&#xff0c;以AI为引擎&#xff0c;参与到从数字化迈向智能化的划时代变革中。 基于服务…

资深PM赞不绝口的【9种项目管理图】

好用的项目管理工具可以帮助项目经理掌握项目进度&#xff0c;更好的拆分任务&#xff0c;节约时间。 今天给大家安排上&#xff0c;助力大家在项目交付路上更顺畅&#xff0c;早日以高质量交付结果&#xff0c;找到百万年薪工作。 ​项目管理甘特图扫描Q群二维码下载Q群5330…

MySQL--表的使用--0409

目录 1.表的基本操作 1.1 创建表 2. 查看表结构 3.修改表 3.1 新增一列 3.2 修改列属性 3.3 修改名字 3.3.1 修改表名字 3.3.2 修改表内列名字 3.4删除 3.4.1 删除列 3.4.2 删除表 1.表的基本操作 查看自己目前在哪个数据库里面 mysql> select database(); 1.1 创…

SpringBoot整合 EasyES (八)

一直在坑自己家人&#xff0c;对&#xff0c;说的就是你&#xff0c;大A. 上一章简单介绍了SpringBoot整合ES 实现简单项目(七), 如果没有看过,请观看上一章 Mybatis 有增强性的 MybatisPlus, ES 有增强性的吗? 有的&#xff0c; easy-es ​ Easy-Es&#xff08;简称EE&…

java捕获编译时异常exception和运行时错误error的方法

背景 最近使用jacob的时候&#xff0c;由于编译没问题&#xff0c;运行时报如下&#xff0c;我 查看代码发现是调用jacob文件时&#xff0c;是下面的方法报错&#xff0c; ComThread.Release(); 这个方法编译不报错&#xff0c;是因为doCoUninitialize使用native修饰的&#…

java 通过 spring 官网创建springboot项目

文章java简单一写一个springboot入门案例带大家用idea工具工具创建了一个springboot简单的小案例 但有时 我们idea如果连不上网 就会有点问题 我们可以采用另一种创建方式 但这里的前提肯定就是 你的计算机是要有网的 然后访问 https://spring.io/ 打开spring的官网 在 Project…

去了字节跳动,才知道年薪40W的测试有这么多?

今年大环境不好&#xff0c;内卷的厉害&#xff0c;薪资待遇好的工作机会更是难得。最近脉脉职言区有一条讨论火了&#xff1a; 哪家互联网公司薪资最‘厉害’&#xff1f; 下面的评论多为字节跳动&#xff0c;还炸出了很多年薪40W的测试工程师 我只想问一句&#xff0c;现在的…

数据结构进阶:前缀和与差分

数据结构进阶&#xff1a;前缀和与差分基础前缀和基础差分区间乘积前缀置换经典差分性质题目前缀和变种高次前缀和高维前缀和 (SOSDP)蓝桥杯已经结束&#xff0c;打下来很难受。自己对于算法的掌握还是不够&#xff0c;遂继续开启博客书写&#xff0c;激励自己学习。本系列文章…