数据结构与算法(排序算法)

news2024/12/27 8:37:53

我本将心向明月,奈何明月照沟渠。

排序的概念

1. 排序是指将一组数据,按照特定的顺序进行排列的过程。
2. 这个过程通常是为了使数据更加有序,从而更容易进行搜索、比较或其他操作。

常见的排序算法

插入排序  

1. 把待排序的记录,按其关键码值的大小,逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
2. 通俗的来说,就是分为两堆数据,第一堆已经按顺序排列好了,第二堆是无序的,然后从无序数据堆中取出第一个数据插入到第一堆进行排序,一直重复,直到第二堆没有数据。
3. 我们玩扑克牌时,就用了插入排序的思想。

直接插入排序 

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void InsertSort(int* arr, int n);
void PrintSort(int* arr, int n);

void InsertSort(int* arr, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;//已经排序的序列最后一位的序号
		int tmp = arr[end + 1];//待排序的序列第一位的数值
		while (end >= 0)
		{
			if (arr[end] > tmp)
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else
			{
				break;
			}
		}
		end++;
		arr[end] = tmp;
	}
}

void PrintSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = { 1,5,2,6,8,7,9,3,0,4 };
	int n = sizeof(arr) / sizeof(int);
	PrintSort(arr, n);
	InsertSort(arr, n);
	PrintSort(arr, n);
	return 0;
}
//1 5 2 6 8 7 9 3 0 4
//0 1 2 3 4 5 6 7 8 9

下面是对直接插入排序的总结:

1. 元素集合越接近有序,直接插入排序算法的时间效率越高。

2. 时间复杂度(默认最差的情况):O(N^2)。数组有序且为降序的情况下时间复杂度最差,所以很难达到最差的情况。

3. 空间复杂度:O(1)。

底层逻辑 

1. 直接插入排序本质上是把一个数组分为两部分,前面部分默认已排序,后面部分默认未排序。

2. 直接插入排序依靠两个循环嵌套实现。

3. 外层循环负责找到已排序数组的最后一位和未排序数组的第一位

4. 内层循环负责进行逐个比较,待排序元素和有序数组的倒数第一个元素进行比较,如果符合要求,那么待排序的元素就往有序数组的倒数第一个元素后面插入,如果不符合要求,那么有序数组的倒数第一个元素往后移动一次,然后用待排序元素和有序数组的倒数第二个元素比较,循环往复。

希尔排序 

1. 由于直接插入排序在完全逆序的情况下时间复杂度最大,故我们可以进行改进,使用希尔排序降低时间复杂度。

2. 希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数距离(通常是gap = n/3+1),把待排序文件所有记录分成各组,所有的距离相等的记录分在同一组内,并对每一组内的记录进行排序。然后gap=gap/3+1进行迭代得到下一个整数距离,再将数组分成各组,进行插入排序,当gap=1时,就相当于直接插入排序。

3. 它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的。

4. 当 gap > 1 时都是预排序,目的是让数组更接近于有序。当 gap == 1 时就是直接插入排序,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。

代码实现 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void ShellSort(int* arr,int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap/3+1;
		for (int i = 0; i < n-gap; i++)
		{
			int end = i;
			int tmp = arr[end + gap];
			while (end >= 0)
			{
				if (arr[end] > tmp)
				{
					arr[end + gap] = arr[end];
					end = end - gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tmp;
		}
	}
	
	return 0;
}
void PrintSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[10] = { 5,1,7,3,4,2,6,0,9,8 };
	int i = sizeof(arr) / sizeof(arr[0]);
	PrintSort(arr, i);
	ShellSort(arr, i);
	PrintSort(arr, i);
	return 0;
}

底层逻辑 

1. 外层循环的时间复杂度:O(log n)。

2. 内层循环的时间复杂度:O(n)。

3. 希尔排序时间复杂度不好计算,因为 gap 的取值很多(最优为3),导致很难去计算,因此很多书中给出的希尔排序的时间复杂度都不固定。

选择排序  

直接选择排序

1. 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

2. 在元素集合 array[ i ] 到 array[ n-1 ] 中选择关键码最小的数据元素,若它不是这组元素中的第一个元素,则将它与这组元素中的第一个元素交换,在剩余的array[ i+1 ] 到 array[ n-1]集合中,重复上述步骤,直到集合剩余 1 个元素。

代码实现 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void Swap(int* a, int* b)
{
	int mid = *a;
	*a = *b;
	*b = mid;
}
void SelectSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		int begin = i;
		int mini = i;
		for (int j = i + 1; j < n; j++)
		{
			if (arr[j] < arr[mini])
			{
				mini = j;
			}
		}
		Swap(&arr[begin], &arr[mini]);
	}
}
void PrintSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[10] = { 5,1,7,3,4,2,6,0,9,8 };
	int i = sizeof(arr) / sizeof(arr[0]);
	PrintSort(arr, i);
	SelectSort(arr, i);
	PrintSort(arr, i);
	return 0;
}

底层逻辑 

 

堆排序

1. 堆排序是指利用堆这种数据结构所设计的⼀种排序算法,它是选择排序的⼀种。它是通过堆来进行选择数据。

2. 需要注意的是排升序要建大堆,排降序建小堆。

代码实现 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void PrintSort(int* arr, int n);
void Swap(int* a, int* b);
void UpAdjust(int* arr, int child);
void DownAdjust(int* arr, int parent, int n);

void Swap(int* a, int* b)
{
	int mid = *a;
	*a = *b;
	*b = mid;
}
void UpAdjust(int* arr, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (arr[child] < arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
void DownAdjust(int* arr, int parent, int n)
{
	int child = 2 * parent + 1;
	while (child < n)
	{
		if ((child + 1 < n) && (arr[child] > arr[child + 1]))
		{
			child++;
		}
		if (arr[child] < arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		UpAdjust(arr, i);//对数组的每一个元素进行建堆
	}
	int end = n - 1;
	while (end > 0)
	{
		Swap(&arr[0], &arr[end]);
		DownAdjust(arr, 0, end);
		end--;
	}
}
void PrintSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = { 1,5,2,6,8,7,9,3,0,4 };
	int n = sizeof(arr) / sizeof(int);
	PrintSort(arr, n);
	HeapSort(arr, n);
	PrintSort(arr, n);
	return 0;
}

底层逻辑 

1. 把数组重建为小堆,那么最后输出的是倒序数组。

2. 数组重建小堆时,是用循环把每一个数组元素进行向上调整算法。(相当于把每一个元素向堆中尾插,查完之后用向上调整算法)

3. 数组进行调整时,交换第一个元素和最后一个元素,然后有效数组元素减一,此时最小的元素就到了队尾,然后再对第一个元素进行向下调整算法,此时又变成了小堆。循环以往,直到有效数组里面只有一个元素。

4. 此时就变成了倒序的数组。

5. 时间复杂度为:O( n*log(n) )。

交换排序

冒泡排序

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void PrintSort(int* arr, int n);
void PopSort(int* arr, int n);

void PopSort(int* arr,int n)
{
	int a = 0, b = 0;
	for (a = 0; a < n - 1; a++)
	{
		for (b = 0; b < n - 1 - a; b++)
		{
			if (arr[b] > arr[b + 1])
			{
				int mid = 0;
				mid = arr[b + 1];
				arr[b + 1] = arr[b];
				arr[b] = mid;
			}
		}
	}
}

void PrintSort(int* arr, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = { 1,5,2,6,8,7,9,3,0,4 };
	int n = sizeof(arr) / sizeof(int);
	PrintSort(arr, n);
	PopSort(arr, n);
	PrintSort(arr, n);
	return 0;
}

底层逻辑

1. 每次都是相邻的两个数进行比较。
2. 一共构造两层循环。
3. 一般都是从前到后进行比较,所以每次确定的数在最后一个。
4. 外层循环(N-1)次。
5. 内层循环(N-1-A)次。(其中A为外层循环的次数)

6. 时间复杂度为:O(N^2)。

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

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

相关文章

思科实现网络地址转换(NAT)和访问控制列表(ACL)和动态路由配置并且区分静态路由和动态路由配置。

实验拓扑(分为静态路由和动态路由两种) 静态路由互通 动态路由互通 实验背景 这个是想实现外网与内网的连接跟网络的探讨&#xff0c;最终实现互通以及使用并且在网络地址转换后能使用网络然后再这个基础上再配置访问控制列表和网络地址转换的的学习过程。 实验需了解的知识…

开发一套ERP 第八弹 RUst 插入数据

更全面的报错,方便检查错误在哪里,现代高级语言越来越智能 还是得看下原文档怎么操作的 src 目录为crate 的根目录 想在crate 中模块相互引入需要在 main 中声明,各个模块,然后才能在各个模块中相互引入和使用 原始工程引入,避免直接使用 lib.rs 回合cargo 中的一些 工程管理出…

课程答疑微信小程序设计与实现

私信我获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 课程答疑微信小程序设计与实现 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了课程答疑微信小程序设计与实现的开发全过程。通过分析…

【时间之外】IT人求职和创业应知【53】-东莞也转型

目录 新闻一&#xff1a;Freysa挑战赛&#xff1a;人类智慧与策略战胜AI&#xff0c;奖金高达4.7万美元 新闻二&#xff1a;中国生成式AI用户规模突破2.3亿&#xff0c;行业应用广泛 新闻三&#xff1a;2024东莞智能终端新技术推广会圆满举行&#xff0c;聚焦AI与智能终端融…

ARP欺骗-监控网络

kali: 使用arp-scan -l 查看同个局域网 windows arp -a 查看地址的物理地址 192.168.21.2 对应的是00-50-56-f5-d5-f0 攻击利用: 我们要让目标ip的流量经过我的网卡,从网关出去 使用的开启 echo 1 > /proc/sys/net/ipv4/ip_forward 当为0时&#xff0c;我们不转发&…

Cesium 当前位置矩阵的获取

Cesium 位置矩阵的获取 在 3D 图形和地理信息系统&#xff08;GIS&#xff09;中&#xff0c;位置矩阵是将地理坐标&#xff08;如经纬度&#xff09;转换为世界坐标系的一种重要工具。Cesium 是一个强大的开源 JavaScript 库&#xff0c;用于创建 3D 地球和地图应用。在 Cesi…

网络编程项目1

基于TCP通信控制红色机械臂和蓝色机械臂的运作 1、项目要求&#xff1a;通过w&#xff08;红色臂角度增大&#xff09;s&#xff08;红色臂角度减小&#xff09;d&#xff08;蓝色臂角度增大&#xff09;a&#xff08;蓝色臂角度减小&#xff09; #include <myhead.h> #…

使用GitZip for github插件下载git仓库中的单个文件

背景&#xff1a;git仓库不知道抽什么疯&#xff0c;下载不了单个文件&#xff0c;点击下载没有反应&#xff0c;遂找寻其他方法&#xff0c;在这里简单记录下。 使用GitZip for github插件下载仓库中的单个文件 1、首先在浏览器安装插件&#xff0c;并确保为打开状态。 2、然…

Y20030022基于PHP+MYSQL疫苗预约管理网站的设计与实现 源码 初稿

旅游度假区微信小程序 1.摘要2.研究背景和意义3. 系统功能4.界面展示5.源码获取 1.摘要 疫苗预约管理系统是为了提供一个高效、便捷、安全的平台&#xff0c;方便用户进行疫苗预约接种&#xff0c;并优化疫苗接种的管理工作。通过该系统&#xff0c;用户可以随时随地进行预约操…

C#中判断两个 List<T> 的内容是否相等

ET实现游戏中邮件系统逻辑思路&#xff08;服务端&#xff09;_游戏邮件系统设计-CSDN博客 场景&#xff1a;今天遇到一个BUG&#xff0c;在服务器重启的时候&#xff08;体验服&#xff09;&#xff0c;玩家之前接收的邮件又重新接收了一次&#xff0c;但是两封邮件的ID是不同…

算法编程题-优势洗牌

算法编程题-优势洗牌 原题描述方法一、排序二分查找思路简述代码实现复杂度分析 方法二、红黑树思路简述代码实现复杂度分析 方法三、贪心思路简述代码实现复杂度分析 摘要&#xff1a;本文将对LeetCode原题优势洗牌进行介绍&#xff0c;从最容易想到的方法开始&#xff0c;循序…

【从零开始的LeetCode-算法】3264. K 次乘运算后的最终数组 I

给你一个整数数组 nums &#xff0c;一个整数 k 和一个整数 multiplier 。 你需要对 nums 执行 k 次操作&#xff0c;每次操作中&#xff1a; 找到 nums 中的 最小 值 x &#xff0c;如果存在多个最小值&#xff0c;选择最 前面 的一个。将 x 替换为 x * multiplier 。 请你…

ERROR in [eslint] Invalid Options ‘extensions‘ has been removed.

看着这个报错 感觉是版本不对引起的 ERROR in [eslint] Invalid Options: - Unknown options: extensions - extensions has been removed. ERROR in Error: Child compilation failed: [eslint] Invalid Options: - Unknown options: extensions - extensions has b…

SpringCloud书单推荐

重新定义SpringCloud实战 129 疯狂SpringCloud微服务架构实战 SpringBootSpringCloud微服务开发实战 点餐系统 SpringCloud微服务架构实战派 日访问量3000W平台 SpringCloud Alibaba微服务原理与实战 Spring CloudNginx 极简spring cloud实战 Spring Cloud 微服…

试题转excel;试题整理工具;试卷转excel;word转excel

一、问题描述 我父亲是一名教师&#xff0c;偶尔会需要将试卷转excel&#xff0c;方便管理处理一些特别重要的题目 于是&#xff0c;就抽空写一个专门将试题转excel的工具&#xff0c;便于各位教师从业者和教育行业的朋友更好的整理试题&#xff0c;减少一点重复枯燥的工作 …

Node.js Fastify装饰器:提升你的API性能与功能

在Node.js的世界中&#xff0c;Fastify以其卓越的性能和插件化架构脱颖而出&#xff0c;成为构建高效API的首选框架之一。Fastify的装饰器功能&#xff0c;允许开发者以声明式的方式增强和扩展核心对象&#xff0c;如请求&#xff08;Request&#xff09;和响应&#xff08;Res…

数据库管理-第267期 23ai:Oracle Data Redaction演示(20241128)

数据库管理267期 2024-11-286 数据库管理-第267期 23ai&#xff1a;Oracle Data Redaction演示&#xff08;20241128&#xff09;1 示例表及数据2 创建编校策略2.1 名字全编校2.2 电话部分编校 3 DML演示3.1 场景13.2 场景2 总结 数据库管理-第267期 23ai&#xff1a;Oracle Da…

C#VB.Net项目一键多国语言显示

如何在项目什么都不做一键支持多国语言显示 开始我们的一键快捷使用之旅 01.创建多语言项目 02.一键批量窗口开启本地化,添加选中内容添加Mu方法 03.一键快捷翻译 04.运行查看效果 01.创建多语言项目 创建多语言项目前,请先下载安装&#xff0c;注册并登录. 为了便于演示这…

像素流送api ue多人访问需要什么显卡服务器

关于像素流送UE推流&#xff0c;在之前的文章里其实小芹和大家聊过很多&#xff0c;不过今天偶然搜索发现还是有很多小伙伴&#xff0c;在搜索像素流送相关的问题&#xff0c;搜索引擎给的提示有这些。当然这些都是比较短的词汇&#xff0c;可能每个人真正遇到的问题和想获取的…

构建高可用系统设计OpenStack、Docker、Mesos和Kubernetes(简称K8s)

如果构建高可用、高并发、高效运维的大型系统 大型系统架构设计包括业务层设计、服务层设计、基础架层设计、存储层设计、网络层协同设计来完成。 一、业务层 根据主要业务范畴的分类和特征提取&#xff0c;抽象出独立的业务系统&#xff0c;分别统计系统的用户角色群体、访…