八大排序算法C语言实现

2023-05-16

1 插入排序
1.1 直接插入排序
基本原理:
将第n个数插入已经排序好的,长度为n-1的序列中。从n-1长度的序列中查找出待插入的元素应该插入的位置;给插入元素腾出空间。
操作方法:
从第2个数开始遍历到第n个数。插入第i个数时,先与第i-1个数进行比较。因为前i-1个数已经为有序序列,如果i-1号数数值小于第i号数,则仍然有序,无需操作。否则,先将第i号数暂存于A[0]出。然后从第i-1号位开始,从后往前进行比较,如果A[j]>A[0],则A[j]后移一位。当A[j]<=A[0]时,将A[0]中暂存的数值插入第j+1号位。

   void InsertSort(int A[], int n)
    {
    	int i,j;
    	for(i=2;i<=n;i++)
    	if(A[i]<A[i-1]){
    		A[0]=A[i];
    		for(j=i-1;A[j]>A[0];j--) A[j+1]=A[j];
    		A[j+1]=A[0];
    	}
    }

1.2 折半插入排序

基本原理:
将第n个数插入已经排序好的,长度为n-1的序列中。使用折半查找的方法找出待插入的位置,然后移动插入元素之后的元素。
操作方法:
与直接插入排序法类似,将第二层for循环中逐个元素进行比较的操作更改为折半查找。

void InsertSort2(int A[],int n)
{
	int i,j,low,mid,high;
	for(i=2;i<=n;i++){
		low=1;high=i-1;
		A[0]=A[i];
		while(low<=high){
			mid = (low+high)/2;
			if(A[0]<A[mid]) low=mid+1;
			else high=mid-1;
		}
		for(j=i-1;j>=high+1;j--) A[j+1]=A[j];
		A[high+1] =A[0];
	}
 } 

1.3 希尔排序
基本原理:
先将序列表分割为若干个形如L[i,i+d,……,i+kd]的子表,分别进行插入排序,当整个表中元素已经基本有序时,再对全体记录进行一次直接插入排序。
操作方法:
先取一个小于n的步长d,将表中的元素分为d1组,所有距离为d1的倍数的记录存放于同一组中,在各组中进行直接插入排序;然后取第二个步长,重复操作,直到所取到的d1为1,再进行直接插入排序。

//希尔排序
void ShellSort(int A[],int n)
{
	int dk,i,j;
	for(dk=n/2;dk>=1;dk/=2){
		for(i=dk+1;i<=n;++i)
			if(A[i]<A[i-dk]){
				A[0]=A[i];
				for(j=i-dk;j>0&&A[j]>A[0];j-=dk) A[j+dk]=A[j];
				A[j+dk]=A[0];
			}
		
	}
}

2 交换排序
2.1 冒泡排序
基本原理:
将n个元素两两进行比较,将两个数按升序进行排序,从第1个数遍历到第n个数后,能将n个数中最大的数置于第n位。按照此方法循环操作n-1次,每次减少一位已经排列好的数字。
操作方法:
一层for循环从0开始遍历到n-1;二层for循环n-1开始遍历到i+1,如果A[j]>A[j+1],则交换两数的序号。

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

2.2 快速排序
基本思想:
在序列中任意取一个元素p作为基准,通过一趟排序将排序表划分为两个部分,p左边的元素均小于p,p右边的元素均大于等于p。然后分别递归地对两个子表进行上述操作,知道每个部分只有一个元素或者为空。
实现方法:
假设划分函数已经完成。在QuickSort函数中调用划分函数,返回划分位置p,然后分别递归p的左边序列和p的右边序列。
在Partition函数中,取序列中第一位数作为p。将第high位数与p对比,如果A[high]>p,则指针前移high–;否则,将A[high]位数放置于第low位。将第low位数与p进行对比,如果A[low]<p,则指针后移,low++;否则,将第low位数放置于第high位。每一次while循环都会交换一次how和high位处的数。While循环结束后将p填入空缺的low号位,返回low。

//快速排序
int Partition(int A[],int low,int high)
{
	int p=A[low];
	while(low<high){
		while(low<high&&A[high]>p) high--;
		A[low]=A[high];
		while(low<high&&A[low]<p) low++;
		A[high]=A[low];
	}
	A[low]=p;
	return low;
}

void QuickSort(int A[],int low,int high)
{
	if(low<high){
		int p=Partition(A,low,high);
		QuickSort(A,low,p);
		QuickSort(A,p+1,high);
	}
}

3 选择排序
3.1 简单选择排序

基本原理:
从n个数中选出最小的数放置于第1号位。循环操作n-1次,每次减少一位已经放置好的数字。
操作方法:
一层for循环从0遍历到n-1,将第1位数暂存为min值。二层for循环从i+1遍历到n-1,将每个数分别与min值进行对比,如果A[j]<A[min],则替换min的数值。到第二层for循环执行完成后,再交换A[min]和A[i]的数值。

//简单选择排序
void SelectSort(int A[],int n)
{
	int i,j;
	for(i=0;i<n-1;i++){
		int min =i;
		for(j=i+1;j<n;j++)
			if(A[j]<A[min]) min=j;
	    if(min != i){
	    	int t=A[i];
	    	A[i] = A[min];
	    	A[min]=t;
		}
	}
}

3.2 堆排序
基本思想:
在排序过程中,将序列视为一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点的内在关系,在当前无序区中选择关键字最大的元素。
堆:(1)树的形状必须为完全二叉树
(2)每一个结点的键必须要大于它的所有结点的键
实现方法:
(1)构建堆,为给定数组构造一个大根堆
由于堆是完全二叉树,所以可以使用数组来实现堆,按照从上到下、从左到右的顺序来记录堆的元素。非叶子结点的键会在后[n/2]个位置。数组中,对于父母位置i来说,子女会占据2i和2i+1两个位置。
(2)删除最大键,将剩下的数组构建成堆;即,将最大值换到最末尾的位置,将剩下的部分构建成堆

//堆排序
void AdjustDown(int A[],int k,int len) 
{
	A[0]=A[k];//暂存根结点
	//调整该结点的两个孩子结点,及其孩子结点的子结点
	for(int i=k*2;i<=len;i*=2){
	    //有右结点,且右结点大于左结点
		if(i<len &&A[i+1]>A[i]) i++;
		//该结点大于左右孩子结点
		if(A[i]<=A[0]) break;
		//交换根结点和较大的孩子结点
		else{
			A[k]=A[i];
			k=i;
		}
	}
	A[k]=A[0];
}

void HeapSort(int A[],int len)
{
    //使用自底向上的方法构建堆,从最后一个非叶子结点依次遍历到根结点
	for(int i=len/2;i>0;i--)
	    AdjustDown(A,i,len);
	//将最大值换到最末尾,再构建堆,依次取最大值交换
	for(int j=len;j>1;j--){
		int t=A[1];
		A[1]=A[j];
		A[j]=t;
		AdjustDown(A,1,j-1);
	}
}

4 归并排序
基本思想:
将长度为n的序列表分为n个长度为1的有序序列表,再将n个有序序列表合并为1个长度为n的有序序列表。
实现方法:
MergeSort函数:将序列分成两个序列,两个序列再分别递归调用MergeSort函数,知道每个序列只有一个数时递归停止。然后调用Merge函数将有序序列合并。
Merge函数:将数组A中元素复制到B中,在从B中lowmid,mid+1high两段序列中选择较小的元素放入数组A。

void Merge(int A[],int low,int mid,int high)
{
	int B[N];
	int i,j,k;
	for( i=low;i<=high;i++) B[i]=A[i];
	for( i=low,j=mid+1,k=low;i<=mid&&j<=high;k++){
		if(B[i]<B[j]) A[k]=B[i++];
		else A[k]=B[j++];
	}
	while(i<=mid) A[k++]=B[i++];
	while(j<=high) A[k++]=B[j++];
	
}

void MergeSort(int A[],int low,int high)
{
	if(low<high){
		int mid=(low+high)/2;
		MergeSort(A,low,mid);
		MergeSort(A,mid+1,high);
		Merge(A,low,mid,high);
	}
}

5 时间复杂度及稳定性比较

算法最优最劣平均稳定性
插入O(n)O(n^2)O(n^2)稳定
折半O(n)O(nlogn)O(nlogn)稳定
希尔不稳定
冒泡O(n^2)O(n^2)O(n^2)稳定
快速O(nlogn)O(n^2)O(nlogn)不稳定
选择O(n^2)O(n^2)O(n^)不稳定
O(nlogn)O(nlogn)O(nlogn)不稳定
归并O(nlogn)O(nlogn)O(nlogn)稳定

6 适用场景
6.1 序列顺序无影响的排序
选择排序:对任何输入而言,选择排序都是一个O(n^2)的算法;键的交换次数为O(n);
冒泡排序:对任何输入而言,冒泡排序都是一个O(n^2)的算法;
归并排序:归并排序在最坏情况下,比较次数仍然十分接近排序算法理论上能够达到的最小次数。
归并排序递归关系式: C(n)=2C(n/2)+n-1,C(1)=0
如果情况最差,n=2^k,则:
C(n)=nlog2 n -n+1
(最小次数,nlog2 n! = nlog2 n =1.44n)
最坏情况,也需要n=2^k

6.2 适用于基本有序序列
插入排序:在序列有序时,只遍历一次序列,时间复杂度O(n);
折半插入排序:类似于插入排序

6.3适用于随机顺序

快速排序:
最优:如果所有的分裂点均位于相应数组的中点,此时为最优的情况,比较次数为n,此时:
C(n)=2C(n/2)+n,C(1)=0
n=2^k时,求得:C(n)=nlog2n
最劣:当A[0…n-1]是严格的递增数组,以A[0]为中轴,从左到右的扫描会停在1号位置,从右到左的扫描会停在0号位置,然后A[0] 再与它本身进行交换,此时总比较次数为:
C(n)=(n+1)+(n)+……+3=(n+1)(n+2)/2-3=O(n^2)
平均:设分裂点可能出现在任何位置s(0<=s<=n-1):
C(n)=2nlnn=O(nlogn)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

八大排序算法C语言实现 的相关文章

  • 制定通信协议

    制定通信协议 一 什么是制定通信协议 xff1f 客户端在和服务器进行通信的时候 xff0c 为了让双方都能辨别接收到的消息的内容 xff0c 由发送方和接收方而制定的相关约定 二 为什么制定通信协议 xff1f 在大型的网络游戏中 xff
  • C++ Primer Plus(嵌入式公开课)---1-3章

    1011 C 43 43 Primer Plus 名词解释数值范围 第1章 预备知识1 1 C 43 43 简介1 2 C 43 43 简史1 2 2 C语言编程原理1 2 3 面向对象编程1 2 4 C 43 43 和泛型编程1 2 5
  • Xilinx的Zynq系列,ARM和PL通过DMA通信时如何保证DDR数据的正确性。

    使用ZYNQ或者MPSoC的好处是可以通过PL逻辑设计硬件加速器 xff0c 对功能进行硬件加速 加速器和ARM之间的交互信息一般包含自定义加速指令传递 待计算数据以及计算结果 这三种交互信息为了实现高性能往往需要使用DMA进行通信 考虑两
  • vscode使用clangd开发c++,实现自动补全功能

    安装 在vscode中安装clangd插件 xff0c 如图所示安装插件 xff0c Enable插件clangd xff1b 如果之前安装过C C 43 43 插件的 xff0c 需要将Disable插件C C 43 43 在命令行安装c
  • 串口高波特率下如何稳定接收

    无论是蓝牙 WiFi xff0c 还是4G 5G xff0c 亦或是其它模组 xff0c 都支持AT指令 43 透传模式 AT指令模式下 xff0c 执行查询指令和操作 设置 指令 响应速度快 xff0c 逻辑交互明确 xff0c 不需要复
  • stm32 串口发送多字节数据(结构体版本)

    话不多说先上代码 typedef struct shuju u8 sj0 帧头 u8 sj1 u8 sj2 u8 sj3 u8 sj4 u8 sj5 u8 sj6 u8 sj7 u8 sj8 u8 sj9 帧尾 shuju 实际使用 shu
  • C++ Primer Plus(第六版)读书笔记

    文章目录 C 43 43 Primer Plus xff08 第六版 xff09 第1章 预备知识第2章 开始学习C 43 43 2 1 进入C 43 43 2 2 1 main 指令 2 2 C 43 43 语句2 2 2 赋值语句 第3
  • STM32 (5) 自己写库 构建库函数雏形1 寄存器结构体定义

    前面把基础部分讲得差不多 xff0c 比如说什么是寄存器 xff0c 寄存器映射 xff0c 怎么样来寄存器编程 xff0c 寄存器编程的时候应该参考官方的什么手册 xff0c 前面讲了什么是寄存器 怎么使用寄存器编程 寄存器编程的时候应该
  • 编译器优化对自定义延时程序的影响(volatile详解实验一)

    由此可见 xff08 C语言volatile关键字详解 xff09 xff0c 编译器优化会对自定义延时程序有影响 xff0c 我们深入汇编程序去探讨产生怎样的影响 xff01 首先是未加 volatie 使用和未使用编译器优化汇编程序的对
  • C语言之大小端转换

    include lt stdio h gt unsigned int reverse byte char c char num unsigned int r 61 0 int i for i 61 0 i lt num i 43 43 r
  • 世界坐标系、相机坐标系和图像坐标系的转换

    相机标定笔记 坐标系转换四个不同类型的坐标系1 世界坐标系2 相机坐标系3 图像物理坐标系4 图像像素坐标系 坐标转换世界坐标 相机坐标 xff08 刚性变换 xff09 绕 X X X 旋转
  • 【C++】strpbrk() 字符串检索函数

    strpbrk 字符串检索函数 需要包含头文件 string h xff1b 声明 span class token keyword char span span class token operator span span class t
  • 干货 | 手把手教你搭建一套OpenStack云平台

    1 前言 今天我们为一位朋友搭建一套OpenStack云平台 我们使用Kolla部署stein版本的OpenStack云平台 kolla是用于自动化部署OpenStack的一个项目 xff0c 它基于docker和ansible来实现 xf
  • 完全卸载nginx的详细步骤

    一个执着于技术的公众号 前言 在开局配置Nginx时有可能会配置错误 xff0c 报各种错误代码 看不懂或者懒得去看这个报错时 xff0c 其实最简单的方式是卸载并重装咯 今天就带大家一起学习下 xff0c 如何彻底卸载nginx程序 卸载
  • Windows 11的这19个新功能,你都知道吗?

    参考资料 xff1a https www windowslatest com 2021 10 06 windows 11 new features everything you need to know Windows 11 是 Windo
  • HttpClient 4.3 - 实现HTTP摘要认证(Digest authentication)

    HttpClient 4 实现HTTP摘要认证 HttpClient 4 实现HTTP摘要认证 什么是摘要认证用DefaultHttpClient实现HttpClient 4 3 实现 什么是摘要认证 说到摘要认证 Digest authe
  • 全国DNS服务器IP地址大全、公共DNS大全

    各省公共DNS服务器IP大全 名称各省公共DNS服务器IP大全 114 DNS114 114 114 114114 114 115 115阿里 AliDNS223 5 5 5223 6 6 6百度 BaiduDNS180 76 76 76
  • 如何在CentOS7上禁用或关闭SELinux

    介绍 SELinux 是内置于 Linux 内核中的强制访问控制 MAC 执行器 它限制了可能对系统构成威胁的个别服务的权限 没有 SELinux 的 CentOS 系统依赖于其所有特权软件应用程序的配置 单个错误配置可能会危及整个系统 为
  • 运维常用的 35 个Linux Shell 脚本,一定能帮到你!

    作为一名 Linux 工程师 xff0c 会写好的脚本不仅能提高工作效率 xff0c 还能有更多的时间做自己的事 最近在网上冲浪的时候 xff0c 也注意收集一些大佬写过的脚本 xff0c 汇总整理一下 xff0c 欢迎收藏 xff0c 与
  • 超好用的开源 IP 地址管理系统,告别传统 Excel 统计方式!

    来自 xff1a 释然IT杂谈 一 前言 xff1a 对于运维管理人员 xff0c ip地址进行管理很重要 xff0c 很多公司都是采用电子文档的形式 xff0c 以手工更新为主 xff0c 对ip地址和子网的实际使用情况无法进行有效的实时

随机推荐

  • Linux运维从入门到精通,看这一篇就够了~

    作为一名 Linux 运维工程师 xff0c 总是会有种 书到用时方恨少 的感觉 xff0c 其根本原因还是技能掌握的不够扎实 所以运维朋友一定要多学习 xff0c 提升技能 xff0c 下面分享一份专门针对运维朋友的资料包 xff0c 相
  • K8S CPU 请求和限制,是否有很好的选择?

    Limits 和 Requests 并不是 CPU 管理的灵丹妙药 xff0c 在某些情况下 xff0c 其他替代方案可能是更好的选择 在这篇博文中 xff0c 您将了解到 xff1a CPU requests 如何工作CPU limits
  • 作为一名Linux用户,你得了解这15个工具!

    来源 xff1a 浩道Linux 在普通人眼里 xff0c 使用Linux系统的用户本身已经很有 极客范儿 了 xff0c 但是在技术人员眼中 xff0c 这只是很普通的层级 使用本文推荐的几个Linux系统下的工具 xff0c 能让你瞬间
  • 虚拟网络namespace 到bridge

    前言 容器的网络是一大难点 xff0c 不管是docker 还是kubernetes 都绕不开计算机网络 以下的介绍主要以计算机网络的namespace 和bridge 两个方面来展开介绍 xff0c 方便深入理解容器的网络原理 1 nam
  • 用OpenCV实现目标追踪的八种方法(转)

    原文地址 xff1a http m elecfans com article 722414 html 编者按 xff1a 目标跟踪作为机器学习的一个重要分支 xff0c 加之其在日常生活 军事行动中的广泛应用 xff0c 很多国内外学者都对
  • turbostat超频检测工具

    介绍 turbostat为Intel提供的超频检测工具 xff0c 可以真正在Linux下获取睿频频率的工具 由下可知 xff1a 物理cpu个数为2 xff0c 核心数为14 xff0c 支持超线程 xff0c 逻辑cpu数为56 xff
  • C# HttpClient Digest 摘要认证 Cookie设置

    C HttpClient Digest 摘要认证 Cookie设置 1 创建凭证信息集 2 创建HttpClientHandler 3 创建HttpClient 4 发生请求 span class token comment 创建凭证信息集
  • MongoDB 批量操作(bulkWrite)

    一 概述 mongodb 3 2 版中的新版本提供了db collection bulkWrite 方法提供了执行批量插入 更新和删除操作的能力 mongodb 还支持批量插入 db collection insertMany 1 1 语法
  • Linux动态库的编译与使用(两种方式:链接进可执行程序、动态加载)

    第一步 xff1a 编写Linux程序库 文件1 动态库接口文件 span class token comment 动态库接口文件getmaxlen h span span class token macro property span c
  • ES 索引文档,按_id查找、更新、删除文档

    一 索引 xff08 新建 xff09 文档 通过使用 index API xff0c 文档可以被 索引 存储和使文档可被搜索 但是首先 xff0c 我们要确定文档的位置 正如我们刚刚讨论的 xff0c 一个文档的 index type 和
  • ES排序

    排序 为了按照相关性来排序 xff0c 需要将相关性表示为一个数值 在 Elasticsearch 中 xff0c 相关性得分 由一个浮点数进行表示 xff0c 并在搜索结果中通过 score 参数返回 xff0c 默认排序是 score
  • ES基于completion suggest实现搜索提示

    Term Suggester xff0c 基于编辑距离 xff0c 对analyze过的单个term去提供建议 xff0c 并不会考虑多个term 词组之间的关系 quert gt queryPhrase Suggester xff0c 在
  • 时间间隔宏计算

    对结果按时间间隔分桶 span class token macro property span class token directive keyword define span TIME INTERVAL a b a lt lt 32 4
  • 容器环境下IP跨网闸映射kafka部署

    一 listeners 和 advertised listeners 在公司内网部署 kafka 集群只需要用到 listeners xff0c 内外网需要作区分时才需要用到advertised listeners listeners 学名
  • C/C++ 中头文件相互包含引发的问题(was not declared in this scope)

    问题引入 最近遇到一个问题 xff0c 重构的代码编译报定义的某个宏was not declared in this scope xff0c 但是明明已经引入了包含此宏的头文件 问题分析 转载内容 我把问题脱离于项目简单描述一下 xff1a
  • 字符的全排列、字符的组合

    一 字符的全排列 题目描述 输入一个字符串 按字典序打印出该字符串中字符的所有排列 例如输入字符串abc 则打印出由字符a b c所能排列出来的所有字符串abc acb bac bca cab和cba 输入描述 输入一个字符串 长度不超过9
  • HTTP带用户名和密码请求

    import java io IOException import org apache commons codec binary Base64 import com cn mid system urls UrlUtils import o
  • n*m的格子中正方形个数和长方形个数

    问题描述 1 xff0e 设有一个nm方格的棋盘 xff08 1 m n 100 xff09 求出该棋盘中包含多少个正方形 多少个长方形 xff08 不包括正方形 xff09 例如 xff1a 当n 61 2 xff0c m 61 3时 正
  • Linux数字权限

    linux系统文件夹 从左至右 xff0c 第一位数字代表文件所有者的权限 xff1b 第二位数字代表同组用户的权限 xff1b 第三位数字代表其他用户的权限 而具体的权限是由数字来表示的 xff1a 读取的权限等于4 xff0c 用r表示
  • 八大排序算法C语言实现

    1 插入排序 1 1 直接插入排序 基本原理 xff1a 将第n个数插入已经排序好的 xff0c 长度为n 1的序列中 从n 1长度的序列中查找出待插入的元素应该插入的位置 xff1b 给插入元素腾出空间 操作方法 xff1a 从第2个数开