排序算法(基础)大全

一、排序算法的作用:

排序算法的主要作用是将一组数据按照特定的顺序进行排列,使得数据更加有序和有组织。

1. 查找效率通过将数据进行排序,可以提高查找算法的效率。在有序的数据中,可以使用更加高效的查找算法,如二分查找、插值查找等,减少了查找的时间复杂度。

2. 统计分析:在排序过程中,可以对数据进行各种统计分析,如计算各种统计量、查找中位数、众数等。有序的数据更加便于进行统计分析和数据挖掘。

3. 数据压缩和编码:排序算法可以将数据重新排列,进而提供更好的数据压缩和编码方式,减少存储空间和传输带宽。

4. 数据归并和合并:在某些应用中,需要将多个有序的数据集合进行归并或合并,排序算法提供了这样的功能。例如,在合并两个有序的数组时,可以使用归并排序算法。

5. 数据的可视化和展示:有序的数据更容易进行可视化展示,可以更加直观地表达数据的分布和关系。

6. 数据库和文件系统中的索引:数据库和文件系统中的索引结构通常需要对数据进行排序,以提高查询和检索的效率。

总之,排序算法能够对数据进行有序排列,提高数据的组织性和可读性,提高查找和统计等操作的效率,是计算机科学和实际应用中的基础算法之一。

二、基础排序算法: 

(1)选择排序:

故名思义,选择排序算法就是有选择地进行排序。其算法思想是:
1、将数组分成【已排序区】【待排序区】
2、每一轮从【待排序区】中选择一个最小的元素放到【已排序区】
3、直到【待排序区】没有元素为止

其算法的时间复杂度无论好坏都为O(n^2)

稳定性:不稳定

其过程如图:

关键代码实现: 
#define swap(a,b){\ //交换a,b__typeof(a) __c=(a);\  //将a赋值给__c,同时,__c的类型与a的类型一样(a)=(b);\ //将b赋值给a(b)=__c;\ //将__c赋值给b
}
void selection_sort(int *arr,int l,int n){ //选择排序for(int i=l;i<n-1;i++){ //从下标0开始int ind=i; //假设下标为ind的数组元素最小for(int j=i+1;j<n;j++){if(arr[ind]>arr[j])ind=j; //如果有比下标ind更小的,则更新下标ind}swap(arr[i],arr[ind]); //将两个元素交换}return;
}
(2)插入排序:

故名思义,插入排序就是不断进行插入调整的排序。其算法思想是:
1、将数组分成【已排序区】和【待排序区】
2、将【待排序区】后面第一个元素,向前插入到【已排序区】并进行调整
3、直到【待排序区】没有元素为止
其算法的时间复杂度最好的情况下为O(n),最坏的情况下或平均情况下为O(n^2)

稳定性:稳定

其过程如图:

关键代码实现:
#define swap(a,b){\ //交换a,b__typeof(a) __c=(a);\(a)=(b);\(b)=__c;\
}
void insert_sort(int *arr,int b,int n){ //插入排序,b=0for(int i=b+1;i<n;i++){ //待排序区从1开始int j=i; //记录已排序区的最大下标while(j>b&&arr[j]<arr[j-1]){ //对新插入到已排序区的元素进行排序swap(arr[j],arr[j-1]);j-=1;}}return;
}
(3)希尔排序:

希尔排序(Shell Sort)是插入排序的一种改进版本,也称为递减增量排序。它通过将原始数组分割成多个子序列,对每个子序列进行插入排序,然后逐步缩小子序列的范围,最终完成排序。

希尔排序的基本算法思想:

  1. 选择一个增量序列,通常选择n/2、n/4、n/8...,直到增量为1。

  2. 对每个增量进行插入排序,将间隔为增量的元素分为一组,对每组进行插入排序

  3. 缩小增量,重复第2步的操作,直到增量为1,即进行最后一次插入排序。

其算法的时间复杂度最好的情况下是O(nlogn),最坏的情况下是O(n^2)

稳定性:不稳定

其过程如图:

 关键代码实现:
#define swap(a,b){\ //交换a,b__typeof(a) __c=(a);\ //将__c的类型在编译时,转换为与a相同的类型并赋值(a)=(b);\ //赋值交换(b)=__c;\ //赋值交换
}
void insert_sort(int *arr,int b,int n,int step){ //插入排序,b为起始下标,n为最大下标int ind=b; //记录要开始进行插入排序的点for(int i=b+step;i<n;i+=step){ //每次对间隔为step的元素排序if(arr[i]<arr[ind])ind=i;    //记录数组下标大而数据小的元素}while(ind>b){ swap(arr[ind],arr[ind-step]); //交换元素ind-=step; //每次对间隔为step的元素进行排序}for(int i=b+2*step;i<n;i+=step){int j=i;while(arr[j]<arr[j-step]){swap(arr[j],arr[j-step]);j-=step;}}return;
}
void shell_sort(int *arr,int b,int n){int k=2,bc=(n-b),step;do{step=bc/k==0?1:(bc/k);for(int i=b,I=b+step;i<I;i++){insert_sort(arr,i,n,step);}k*=2;}while(step!=1);return;
}
(4)快速排序: 

快速排序是通过选择一个基准元素,将数组分成两个子数组,一组小于基准元素,另一组大于基准元素。然后对两个子数组分别递归地进行快速排序,最终将整个数组排序。

快速排序的基本算法思想:
1. 选择一个基准元素,通常选择数组的第一个最后一个元素。
2. 定义两个指针,一个指向数组的第一个元素,一个指向数组的最后一个元素。
3. 移动左指针,直到找到一个大于等于基准元素的元素。
4. 移动右指针,直到找到一个小于等于基准元素的元素。
5. 交换左指针和右指针所指向的元素。
6. 重复步骤3-5,直到左指针和右指针相遇
7. 将基准元素与左指针所指向的元素互换位置。
8. 进行递归,对基准元素左边的子数组和右边的子数组进行快速排序。

其算法的时间复杂度最好的情况为O(nlogn),最坏的情况为O(n^2)。

其稳定性:不稳定

其过程如图:

关键代码实现: 
#define swap(a,b){\__typeof(a) __c=(a);\(a)=(b);\(b)=__c;\
}
void quick_sort(int *arr,int l,int r){if(r-l<=2){if(r-l<=1)return;if(arr[l]>arr[l+1])swap(arr[l],arr[l+1]);return;}int x=l,y=r-1,z=arr[l];while(x<y){while(x<y&&z<=arr[y])--y;if(x<y)arr[x++]=arr[y];while(x<y&&arr[x]<=z)++x;if(x<y)arr[y]=arr[x];}arr[x]=z;quick_sort(arr,l,x);quick_sort(arr,x+1,r);return;
}
int main(){
(5)归并排序:

归并排序(Merge sort)是一种经典的排序算法,它采用分治法的思想将问题分解为更小的子问题,并且通过递归的方式解决这些子问题。然后将子问题的解合并起来,最终得到原问题的解。

归并排序的基本算法思想:

1. 每次将数组不断地二分为两个子数组,直到每个子数组只剩下一个元素。
2. 然后将两个子数组逐个合并起来,形成一个有序的新数组。

3.合并的方式是比较两个子数组的第一个元素,将较小的元素放入新数组中,并移动指针,继续比较下一个元素。
4. 重复上述步骤,直到将所有的子数组都合并起来,得到最终的有序数组。

归并排序的时间复杂度:最好的情况下:O(nlogn);最坏的情况下:O(nlogn)。

这是一种稳定的排序算法,适用于各种数据类型。但是归并排序需要额外的存储空间来存储临时数组,空间复杂度为O(n)。

其过程如图:

原数组:[5,4,2,7,1,6,8,3]

关键代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define SMALL 1000000
__attribute__((constructor))
void __init_Rand__(){srand(time(0));
}
bool check(int *arr,int l,int r){for(int i=l+1;i<r;i++){if(arr[i]<arr[i-1])return false;}return true;
}
#define swap(a,b){\__typeof(a) __c=(a);\(a)=(b);\(b)=__c;\
}
#define TEST(func,arr,n){\printf("TEST:%s",#func);\int *temp=(int *)malloc(sizeof(int)*n);\memcpy(temp,arr,sizeof(int)*n);\long long b=clock();\func(temp,0,n);\long long e=clock();\if(check(temp,0,n)){\printf("\tOK");\}else{\printf("\tNO");\}\printf("\t%lldms\n",(e-b)*1000/CLOCKS_PER_SEC);\free(temp);\
}
int *getRandData(int n){int *arr=(int *)malloc(sizeof(int)*n);for(int i=0;i<n;i++){arr[i]=rand()%100+1;}return arr;
}
int *buff; //额外存储空间
void merge_sort(int *arr,int l,int r){ r为数组长度,l为开始位置,初始为0if(r-l<=1)return; //如果只有一个元素,返回结果int mid=(l+r)/2; //每次都将数组二分merge_sort(arr,l,mid); //递归二分前半段的数组merge_sort(arr,mid,r); //递归二分后半段的数组int p1=l,p2=mid,k=0;//p1记录第一个数组元素下标,p2记录中间元素下标,k记录当前位置,便于排序while(p1<mid||p2<r){ //前半段数组范围、后半段数组范围if(p2==r||(p1<mid&&arr[p1]<=arr[p2])){ buff[k++]=arr[p1++];}else{buff[k++]=arr[p2++];}}for(int i=l;i<r;i++)arr[i]=buff[i-l];return;
}
int main(){int *arr=getRandData(SMALL);buff=(int *)malloc(sizeof(int)*SMALL);TEST(merge_sort,arr,SMALL);free(buff);return 0;
}
(6)基数排序:

基数排序是一种非比较型的排序算法,它将数据按照位数进行分组,分别对每个位数进行排序,直到最高位数排序完毕。基数排序可以用于对非负整数进行排序。

基数排序的基本算法思想如下:

1. 将待排序的数据从最低位开始,按照个位数进行分组。
2. 对每个分组进行计数排序,将数据按照个位数的大小进行排序。
3. 将所有分组的数据按照排序结果进行合并
4. 重复步骤1-3,按照位数、位数等依次进行排序,直到最高位数排序完毕。

基数排序的时间复杂度:最好的情况下:O(k*n);最坏的情况下:O(k*n)。其中k是最大数的位数,n是待排序数据的个数。

基数排序的空间复杂度是O(n+k)。

基数排序的优点是稳定性好,适用于数据量较大且每个数位数较小的情况。然而,基数排序的缺点是需要占用大量的额外空间,且对于负数无法直接排序。

基数排序过程如图:

关键代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define K 65536
#define SMALL 1000000
__attribute__((constructor))
void __init_Rand__(){srand(time(0));
}
#define swap(a,b){\__typeof(a) __c=(a);\(a)=(b);\(b)=__c;\
}
bool check(int *arr,int l,int r){for(int i=l+1;i<r;i++){if(arr[i]<arr[i-1])return false;}return true;
}
#define TEST(func,arr,n){\printf("TEST:%s",#func);\int *temp=(int *)malloc(sizeof(int)*n);\memcpy(temp,arr,sizeof(int)*n);\long long b=clock();\func(temp,0,n);\long long e=clock();\if(check(temp,0,n)){\printf("\tOK");\}else{\printf("\tNO");\}\printf("\t%lldms\n",(e-b)*1000/CLOCKS_PER_SEC);\free(temp);\
}
int *getRandData(int n){int *arr=(int *)malloc(sizeof(int)*n);for(int i=0;i<n;i++){arr[i]=rand()%100+1;}return arr;
}
void radix_sort(int *arr,int l,int r){int *cnt=(int *)malloc(sizeof(int)*K);int *temp=(int *)malloc(sizeof(int)*r);memset(cnt,0,sizeof(int)*K);for(int i=0;i<r;i++)cnt[arr[i]%K]+=1;for(int i=1;i<K;i++)cnt[i]+=cnt[i-1];for(int i=r-1;i>=l;i--)temp[--cnt[arr[i]%K]]=arr[i];memcpy(arr,temp,sizeof(int)*r);memset(cnt,0,sizeof(int)*K);for(int i=0;i<r;i++)cnt[arr[i]/K]+=1;for(int i=1;i<K;i++)cnt[i]+=cnt[i-1];for(int i=r-1;i>=l;i--)temp[--cnt[arr[i]/K]]=arr[i];memcpy(arr,temp,sizeof(int)*r);free(temp);free(cnt);return;
}
int main(){int *arr=getRandData(SMALL);TEST(radix_sort,arr,SMALL);free(arr);return 0;
}

文章到此结束!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动手学深度学习73 课程总结和进阶学习

1. 课程总结和进阶学习 https://c.d2l.ai/stanford-cs329p/ https://paperswithcode.com https://www.bilibili.com/video/BV1nA41157y4/?vd_sourceeb04c9a33e87ceba9c9a2e5f09752ef8 怎么建立知识库 2. QA 20 算法提取的特征和人的不一样&#xff0c;互补 21 很难预测未…

WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇

WebRTC视频 01 - 视频采集整体架构 WebRTC视频 02 - 视频采集类 VideoCaptureModule WebRTC视频 03 - 视频采集类 VideoCaptureDS 上篇 WebRTC视频 04 - 视频采集类 VideoCaptureDS 中篇&#xff08;本文&#xff09; WebRTC视频 05 - 视频采集类 VideoCaptureDS 下篇 一、前言…

【弱监督视频异常检测】2024-ESWA-基于扩散的弱监督视频异常检测常态预训练

2024-ESWA-Diffusion-based normality pre-training for weakly supervised video anomaly detection 基于扩散的弱监督视频异常检测常态预训练摘要1. 引言2. 相关工作3. 方法论3.1. 使用扩散自动编码器进行常态学习3.2. 全局-局部特征编码器3.2.1 局部块3.2.2 全局块3.2.3 协同…

ONLYOFFICE8.2版本测评,团队协作的办公软件

文章目录 引言ONLYOFFICE产品简介功能与特点1. 实时协作2. 兼容性3. 模板库4. 评论和修订5. 安全性 体验与测评功能测试 邀请用户使用项目介绍结尾了解更多 引言 在数字化办公的浪潮中&#xff0c;效率和协作成为了工作的核心。ONLYOFFICE作为一个强大的办公套件&#xff0c;正…

Day18 Nim游戏

你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。 你们轮流进行自己的回合&#xff0c; 你作为先手 。 每一回合&#xff0c;轮到的人拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。 假设你们每一步都是最优解。请编写一个函数&#xff…

【论文复现】STM32设计的物联网智能鱼缸

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STM32设计的物联网智能鱼缸 【1】项目功能介绍【2】设计需求总结【3】项目硬件模块组成 1.2 设计思路【1】整体设计思路【2】ESP8266工作模式…

3D意识(3D Awareness)浅析

一、简介 3D意识&#xff08;3D Awareness&#xff09;主要是指视觉基础模型&#xff08;visual foundation models&#xff09;对于3D结构的意识或感知能力&#xff0c;即这些模型在处理2D图像时是否能够理解和表示出图像中物体或场景的3D结构&#xff0c;其具体体现在编码场景…

day-83 最少翻转次数使二进制矩阵回文 II

思路 关键在于1的个数要为4的倍数&#xff0c;首先镜像的四个位置肯定一定为4的倍数&#xff0c;如果行和列为奇数则需要单独考虑&#xff0c;如果行和列皆为奇数&#xff0c;那么中心的那个数一定为0 解题过程 再单独考虑如果行和列为奇数&#xff0c;具体参考灵神。如果diff…

算法沉淀一:双指针

目录 前言&#xff1a; 双指针介绍 对撞指针 快慢指针 题目练习 1.移动零 2.复写零 3.快乐数 4.盛水最多的容器 5.有效三角形的个数 6.和为s的两个数 7.三数之和 8.四数之和 前言&#xff1a; 此章节介绍一些算法&#xff0c;主要从leetcode上的题来讲解&#xff…

《InsCode AI IDE:编程新时代的引领者》

《InsCode AI IDE&#xff1a;编程新时代的引领者》 一、InsCode AI IDE 的诞生与亮相二、独特功能与优势&#xff08;一&#xff09;智能编程体验&#xff08;二&#xff09;多语言支持与功能迭代 三、实际应用与案例&#xff08;一&#xff09;游戏开发案例&#xff08;二&am…

GitLab 如何降级?

本分分享 GitLab 降级的流程和注意事项。极狐GitLab 为 GitLab 的中文发行版&#xff0c;本文以私有化部署的极狐GitLab 为例来演示整个过程。 【极狐GitLab 推出 GitLab 老旧版本的专业升级服务【https://dl.gitlab.cn/cm33bsfv】&#xff0c;可以让 12.x、13.x、14.x、15.x …

【动手学电机驱动】 STM32-FOC(7)MCSDK Pilot 上位机控制与调试

STM32-FOC&#xff08;1&#xff09;STM32 电机控制的软件开发环境 STM32-FOC&#xff08;2&#xff09;STM32 导入和创建项目 STM32-FOC&#xff08;3&#xff09;STM32 三路互补 PWM 输出 STM32-FOC&#xff08;4&#xff09;IHM03 电机控制套件介绍 STM32-FOC&#xff08;5&…

IDEA2024:右下角显示内存

使用场景&#xff1a; 实时知晓idea内存使用情况 解决方案: 开启内存显示 View -> Apperance -> Status Bar Widgets -> Memory Indicator 效果如下&#xff1a;

2024140读书笔记|《作家榜名著:生如夏花·泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下,终于停泊在我的心头

2024140读书笔记|《作家榜名著&#xff1a;生如夏花泰戈尔经典诗选》——你从世界的生命的溪流浮泛而下&#xff0c;终于停泊在我的心头 《作家榜名著&#xff1a;生如夏花泰戈尔经典诗选》[印]泰戈尔&#xff0c;郑振铎译&#xff0c;泰戈尔的诗有的清丽&#xff0c;有的童真&…

c# 调用c++ 的dll 出现找不到函数入口点

今天在调用一个设备的dll文件时遇到了一点波折&#xff0c;因为多c 不熟悉&#xff0c;调用过程张出现了找不到函数入口点&#xff0c;一般我们使用c# 调用c 文件&#xff0c;还是比较简单。 [DllImport("AtnDll2.dll",CharSet CharSet.Ansi)]public static extern …

Python_爬虫3_Requests库网络爬虫实战(5个实例)

目录 实例1&#xff1a;京东商品页面的爬取 实例2&#xff1a;亚马逊商品页面的爬取 实例3&#xff1a;百度360搜索关键词提交 实例4&#xff1a;网络图片的爬取和存储 实例5&#xff1a;IP地址归地的自动查询 实例1&#xff1a;京东商品页面的爬取 import requests url …

WebSocket协议在Java中的整合

1. 常见的消息推送方式 2.WebSocket API 3.基于WebSocket的实战&#xff08;实时聊天室&#xff09; 这里以解析后端代码为主&#xff0c;前端不作为重点&#xff0c;若想复现项目&#xff0c;请从作者的仓库中拉取代码 WebSocket-chatRoom: 基于WebSocket协议实现一个简单的…

蓝桥杯每日真题 - 第15天

题目&#xff1a;&#xff08;钟表&#xff09; 题目描述&#xff08;13届 C&C B组B题&#xff09; 解题思路&#xff1a; 理解钟表指针的运动&#xff1a; 秒针每分钟转一圈&#xff0c;即每秒转6度。 分针每小时转一圈&#xff0c;即每分钟转6度。 时针每12小时转一圈…

在 Node.js 中解决极验验证码:使用 Puppeteer 自动化

近年来&#xff0c;极验验证码在区分真实用户和自动化系统方面越来越先进&#xff0c;使其成为网页抓取和自动化的重大障碍。如果您正在使用 Node.js 并致力于在自动化流程中解决极验验证码&#xff0c;那么使用 Puppeteer 是一种有效的方法。Puppeteer 提供了一个高级 API 来控…

centos7 升级openssl 与升级openssh 安装卸载 telnet-server

前言&#xff1a; 服务器被安全扫描&#xff0c;扫出了漏洞需要修复&#xff0c;根据提示将openssh升级为9.8p1的版本&#xff0c;同时需要升级openssl&#xff0c;但是升级openssh可能会导致ssh连接失败&#xff0c;从而无法继续操作&#xff0c;特别是远程机房尤为危险&#…