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

Sort_Algorithm

排序算法

  • 前言
  • 插入排序
  • 折半插入排序
  • 希尔排序
  • 冒泡排序
  • 快速排序
  • 选择排序
  • 堆排序
  • 归并排序


前言

排序算法:将一堆数据元素按关键字递增或者递减的顺序,进行排序。


排序算法的评价指标:时间复杂度,空间复杂度,算法稳定性。
算法稳定性: 关键字相同的元素在排序之后相对位置不变。
内部排序:数据都在内存中,数据量不大,能放在内存中(关注时、空复杂度)
外部排序:数据量太大,无法放入全部内存,数据放在在磁盘中(关注磁盘读写次数)

插入排序

算法思想:每次将一个待排序的元素按其关键字大小插入到前面已经排好的子序列中,知道其全部记录插入完成。

void Insert_sort1(int* a,int n)
{for (int i = 1; i < n; i++){if (a[i] < a[i - 1]){//后小于前int j = i - 1;//标记前int temp = a[i];//保存后while (j >= 0 && a[j]>temp)/*后移,腾位,不能写成a[j]<a[i],因为第一次移位(i=j+1)后,a[i]就被覆盖了,并不是原先的值,这也是为什么要保存a[i]的值的原因*/{a[j+1] = a[j];--j;}//当a[j]<temp时循环跳出,此时腾出了j+1这个位置a[j+1] = temp;}}
}

对于排序算法,要明确知道所定义的每一个变量的含义,以及在循环过程中的变化情况,死记硬背是万不可行,要掌握核心思想,仔细体会在细节的处理。

折半插入排序

在前面已有序序列中查找,待插入元素位置,因为前面已经是有序序列所以可用折半查找,折半查找效率O(logn)。

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

分析优化情况,实际上这样优化只是减少了之前在while循环中的比较次数,总体时间复杂度还是O(n^2),因为依然要移动大量元素。想到这里,能不能在链表中用折半插入排序呢?答案是:不可以!
原因在于折半查找,利用了数组能够通过小标随机访问的特性,而链表无法做到随机访问,只能从前往后遍历,所以无法应用折半查找,但可以利用插入排序。

希尔排序

对待排序表,按一定增量进行分割成子表,对每个子表进行直接插入排序,增量d=d/2。
不断缩小增量,最后d=1时为直接插入排序,因为前面的每次排序致使元素已经基本有序,而直接插入排序,当元素基本有序时,时间复杂度较低,这也就是希尔排序时间复杂度降低的原因。

/*
算法思想:缩小增量的直接插入排序,利用直接插入排序在元素基本有序时,时间复杂度接近O(n),来降低时间复杂度
每次对小规模的子表进行排序,最后一次的子表已经是表本身
理解希尔排序代码,首先要充分理解直接插入排序的思想
*/
int shell_sort(int* a, int n)
{int num = 0;for (int d = n / 2; d >= 1; d /= 2)//增量设置,每次÷2,终值为1,直接插入排序{for (int i = d; i < n; i++)//对i不可以进每次加d操作,对i的遍历,已经从0开始变为d开始{int j = i - d;//原先是减一,现在为减dint temp = a[i];if (a[i]<a[i - d]){num++;for (j = i - d; j >= 0 && a[j] > temp; j -= d)//循环每次减da[j + d] = a[j];a[j + d] = temp;//参照插入排序,1变d}}}return 1;
}

不稳定排序,只能用于线性表,不能用于链表。

冒泡排序

从后往前或从前往后两两比较相邻元素的值,若为逆序,则交换,直到序列比较完。
每一趟排序,是最小的元素冒到最前。每一趟确定一个元素的位置。
稳定排序,适用于链表

#include<stdbool.h>
void swap(int* a, int j)
{int temp = a[j];a[j] = a[j - 1];a[j - 1] = temp;
}int Bubble_sort(int* a, int n)
{for (int i = 0; i < n-1; i++){bool flag = false;for (int j = n -1; j >i; j--)//j>i,i前的元素已经有序,从后往前冒泡,前面元素有序{if (a[j - 1] > a[j])//左大于右才交换,稳定{swap(a,j);flag = true;//标记一趟循环是否进行过交换}}if (flag == false)//没有进行交换,说明表中元素已有序,提前退出return 1;}return 1;
}

注意两个for循环的n-1,对i的n-1是最后一个元素不判断
对j的n-1是从最后一个元素开始判断是否逆序,逆序则交换,直到j<=i

快速排序

分治思想,每次选一位置元素作为枢轴,进行数组划分,划分结果要让枢轴之前都<=,枢轴之后都>,这样也就确定了一个枢轴元素的位置,并接着以此枢轴划分为两个子数组,对子数组再进行划分,最终将所有元素排好序。

int Partition(int*, int, int);
void Quick_sort(int* a,int low,int high)
{if (low < high)//递归跳出{int pivotpos = Partition(a, low, high);//划分Quick_sort(a, low, pivotpos - 1);//枢轴以左Quick_sort(a, pivotpos + 1, high);//枢轴以右}
}
int Partition(int* a, int low, int high)//时间复杂度O(n),对表用low,high指针扫描一遍
{int pivot = a[low];while (low < high)//low,high指针相遇时跳出,共同所指位置即枢轴元素应放位置,此时前都比其小,后都比其大{while (low < high&&a[high] >= pivot) --high;//当出现小于枢轴时跳出while,此时high所指就是小于枢轴a[low] = a[high];//low最初的值已经保存在pivot中,可视为low此时空出,直接放入,每次while只能交换一个值while (low < high&&a[low] <= pivot) ++low;//low指针右移找到比枢轴大的跳出while,low此时所指为大于枢轴的元素,下步移动a[high] = a[low];//在上面high的值已经被存入,所以视high为空,放入low值}//跳出最外层while,此时low=high,所指相同,且其原值已经被保存到别处,可视为空,则放入pivota[high] = pivot;//a[high]=pivot;是一样的return high;//return high;是一样的
}
/*
快排时间复杂度O(n*递归层数)
如果每次选择的枢轴元素都刚好是顺序的中间元素的值,则递归层数为logn
最好时间复杂度O(nlogn)
最坏O(n^2)
*/

跑一亿随机数排序时会崩。

int Partition(int*, int, int);
void Quick_sort(int* a,int low,int high)
{if (low < high){int pivotpos = Partition(a, low, high);Quick_sort(a, low, pivotpos - 1);Quick_sort(a, pivotpos + 1, high);}
}
int Partition(int* a, int low, int high)
{int pivot = a[low];while (low < high){while (low < high&&a[high] >= pivot) --high;a[low] = a[high];while (low < high&&a[low] <= pivot) ++low;a[high] = a[low];}a[high] = pivot;return high;
}

选择排序

每次选取未排序列的最小值,与当前未排序的第一个位置交换,知道最后一个元素。

void Choice_sort(int* a, int n)
{for (int i = 0; i < n-1; i++){int min=i;for (int j = i+1; j < n; j++)//在二层for循环外无判断,所以内层for始终都要被执行{if (a[j] < a[min])min = j;//min保存最小值下标,用小标处理相对于用值处理要简单}//找到最小a[j],与a[i]交换if (min!=i)//若当前a[i]就是未排序中最小,则不用交换{int temp = a[i];a[i] = a[min];a[min] = temp;}}
}
/*
不稳定,也使用于链表
无论待排序列是否有序,时间复杂度都是  n(n-1)/2  ->  O(n^2)
*/

堆排序

 /*
大根堆,小根堆(完全二叉树)逻辑视角,因为是完全二叉树,可以用数组存(存储视角)
根>=左右孩子
根<=左右孩子
i的左孩子 2i
i的右孩子 2i+1
i的父节点 i/2(向下取整)
构建和维护大根堆
检查非终端节点 i<=(n/2),是否满足大根堆的要求
*/
void HeadAdjust(int*, int, int);
void BuildMaxHeap(int* a, int len)
{for (int i = len / 2; i > 0; i--)//从后往前遍历非终端结点HeadAdjust(a, i, len);
}
//将以k为根的子树调整为大根堆(局部微调)
void HeadAdjust(int* a, int k, int len)
{int root = a[k];//暂存子树的根节点,注意是子树for (int i = 2 * k; i <= len; i *= 2)//i=2*k,所以此时i表达k的左孩子{if (i < len&&a[i] < a[i + 1])//取左右孩子的较大值i++;if (root  >= a[i])break;//根大于较大值,说明该子树满足大根堆,退出else //否则交换二者{a[k] = a[i];k = i;//进行交换,则改变了其他子树的大根堆,所以要更新k值,继续向下检查}}a[k] = root;
}
void Heap_Sort(int* a, int len)
{BuildMaxHeap(a, len);for (int i = len; i >= 0; i--){int temp = a[i];a[i] = a[0];a[0] = temp;//大根堆,所以和堆顶元素交换HeadAdjust(a, 0, i - 1);//交换后,堆顶元素到了叶子结点不必再考虑它,修正大根堆}
}

构建大根堆,每次选择堆顶元素,已选元素与叶子交换,就不再看,维护其他结点构成大根堆,大根堆逐渐缩小,最后只剩一个根结点时,其实已经变成小根堆。

不稳定排序
时间复杂度O(nlogn)

归并排序

把两个或多个已经有序的序列合并成一个
所以分为“2路”归并和多路归并
m路归并,每次选出一个关键字需对比m-1次。
内部排序中一般采用2路归并

//递归实现
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<stdbool.h>
int* b;
void meger(int* a, int l, int mid, int r)
{//	int* b=(int*)malloc(sizeof(int)*n);//辅助数组b不能在这里申请,应定义为全局,首先定义全局指针,然后再main函数中申请空间 int k = l;int i, j;for (i = l, j = mid + 1; i <= mid&&j <= r;k++)//不能在for中进行i,j的增{if (a[i]>a[j])b[k] = a[j++];else b[k] = a[i++];}//循环结束条件就是i,j之一越界其子数组,只是其中一个下标越界while (i<=mid)b[k++] = a[i++];while (j<=r)b[k++] = a[j++];for (int i = l; i <= r; i++)//处理好的b赋给aa[i] = b[i];
}
void megersort(int* a, int l, int r)
{if (l >= r) return;int mid = (l + r) / 2;megersort(a, l, mid);megersort(a, mid + 1, r);meger(a, l, mid, r);
}
void pint(int* a, int n)
{for (int i = 0; i<n; i++)printf("%d ", a[i]);
}
int main()
{clock_t s, f;srand(time(0));int n;scanf("%d", &n);b = (int*)malloc(4 * n);int* a = (int*)malloc(4 * n);for (int i = 0; i<n; i++)a[i] = rand() % 100 + 1;//pint(a, n);s = clock();megersort(a, 0, n - 1);f = clock();printf("time=%f\n", (float)(f - s)/1000);printf("\n");//pint(a, n);return 0;
}

递归结束:当划分的数组只有一个元素时,开始合并,并且只有一个元素的子数组必然是有序的
归并的过程就像形成一颗二叉树,二叉树有logn层,归并排序要logn趟,每趟都要O(n)时间,就像当于遍历一遍,时间复杂度为O(nlogn)
空间复杂度O(n),主要是要用到一个和原数组大小相同辅助数组,还有递归栈但是栈只要logn,低阶舍去。
稳定排序。

相关文章:

Sort_Algorithm

排序算法前言插入排序折半插入排序希尔排序冒泡排序快速排序选择排序堆排序归并排序前言 排序算法&#xff1a;将一堆数据元素按关键字递增或者递减的顺序&#xff0c;进行排序。 排序算法的评价指标&#xff1a;时间复杂度&#xff0c;空间复杂度&#xff0c;算法稳定性。 算…...

【初探人工智能】2、雏形开始长成

【初探人工智能】2、雏形开始长成【初探人工智能】2、雏形开始长成安装Flask封装Web接口雏形设置接收参数功能验证聊天写代码代码补全生成图片写在后面笔者初次接触人工智能领域&#xff0c;文章中错误的地方还望各位大佬指正&#xff01; 【初探人工智能】2、雏形开始长成 在…...

【LeetCode】剑指 Offer(2)

目录 写在前面&#xff1a; 题目&#xff1a; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 写在前面&#xff1a; 今天的每日一题好难&#xff0c;我不会dp啊啊啊啊啊啊。 所以&am…...

【JavaSE】Lambda、Stream(659~686)

659.每天一考 1.写出获取Class实例的三种常见方式 Class clazz1 String.class; Class clazz2 person.getClass(); //sout(person); //xxx.yyy.zzz.Person... Class clazz3 Class.forName(String classPath);//体现反射的动态性2.谈谈你对Class类的理解 Class实例对应着加载…...

有限差法(Finite Difference)求梯度和Hessian Matrix(海森矩阵)的python实现

数学参考 有限差方法求导&#xff0c;Finite Difference Approximations of Derivatives&#xff0c;是数值计算中常用的求导方法。数学上也比较简单易用。本文主要针对的是向量值函数&#xff0c;也就是f(x):Rn→Rf(x):\mathbb{R^n}\rightarrow \mathbb{R}f(x):Rn→R当然&…...

day33 贪心算法 | 1005、K次取反后最大化的数组和 134、加油站 135、分发糖果

题目 1005、K次取反后最大化的数组和 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&#xff09; 以这种方式修改…...

《蓝桥杯每日一题》递推·AcWing 3777. 砖块

1.题目描述n 个砖块排成一排&#xff0c;从左到右编号依次为 1∼n。每个砖块要么是黑色的&#xff0c;要么是白色的。现在你可以进行以下操作若干次&#xff08;可以是 0 次&#xff09;&#xff1a;选择两个相邻的砖块&#xff0c;反转它们的颜色。&#xff08;黑变白&#xf…...

mysql读写分离(maxscale)

1. 环境架构 需要三台服务器。192.168.2.10&#xff08;master&#xff09;192.168.2.20&#xff08;slave&#xff09;192.168.2.30&#xff08;maxscale&#xff09; 2. 部署mysql主从同步 mysql主从同步可以参考mysql主从同步 3. 部署maxscale服务 MaxScale中间件软件 …...

第八章 - 数据分组( group by , having , select语句顺序)

第八章 - 数据分组 group by数据分组过滤分组 having分组排序groub by语句的一些规定select语句顺序数据分组 在使用group by进行分组时&#xff0c;一般都会配合聚合函数一起使用&#xff0c;实现统计数据的功能。比如下面例子&#xff0c;需要按性别计算人数。按性别进行分组…...

Git(GitHub,Gitee 码云,GitLab)详细讲解

目录第一章 Git 概述1.1 何为版本控制1.2 为什么需要版本控制1.3 版本控制工具1.4 Git 简史1.5 Git 工作机制1.6 Git 和代码托管中心第二章 Git 安装第三章 Git 常用命令3.1 设置用户签名3.2 初始化本地库3.3 查看本地库状态3.3.1 首次查看&#xff08;工作区没有任何文件&…...

策略模式(Strategy Pattern)

编写鸭子项目&#xff0c;具体要求如下&#xff1a; 1&#xff09; 有各种鸭子&#xff08;比如 野鸭、北京鸭&#xff0c;水鸭等&#xff0c;鸭子有各种行为&#xff0c;比如 叫&#xff0c;飞行等&#xff09; 2&#xff09;显示鸭子的信息 传统方案解决鸭子问题 1&#xff0…...

《Qt6开发及实例》6-2 Qt6基础图形的绘制

目录 一、绘图框架设计 二、绘图区的实现 2.1 PaintArea类 2.2 PaintArea类讲解 三、主窗口的实现 3.1 MainWidget类 3.2 MainWidget类讲解 3.3 槽函数编写 3.5 其他内容 一、绘图框架设计 界面 两个类 ​ 二、绘图区的实现 2.1 PaintArea类 ​paintarea.h #ifndef…...

LeetCode 382. 链表随机节点

原题链接 难度&#xff1a;middle\color{orange}{middle}middle 题目描述 给你一个单链表&#xff0c;随机选择链表的一个节点&#xff0c;并返回相应的节点值。每个节点 被选中的概率一样 。 实现 SolutionSolutionSolution 类&#xff1a; Solution(ListNodehead)Solution…...

iOS开发AppleDeveloper中给别人授权开发者权限后,对方一直显示不了我的开发账号team

在iOS开发经常出现多人协作开发的情况。这时我们通常要发邮件邀请别的用户为开发者或者app管理就可以开发我们自己的项目了。但是这次我给别人授权开发者权限后&#xff0c;发现别人权限中没有证书相关权限如图&#xff1a;并且别人登录该账号后&#xff0c;在xcode中只有一个看…...

FreeRTOS数据类型和编程规范

目录 数据类型 变量名 函数名 宏的名 数据类型 每个移植的版本都含有自己的portmacro.h头文件&#xff0c;里面定义了2个数据类型 TickType_t FreeRTOS配置了一个周期性的时钟中断&#xff1a;Tick Interrupt每发生一次中断&#xff0c;中断次数累加&#xff0c;这被称为t…...

【python知识】win10下如何用python将网页转成pdf文件

一、说明 本篇记录一个自己享用的简单工具。在大量阅读网上文章中&#xff0c;常常遇到一个专题对应多篇文章&#xff0c;用浏览器的收藏根本不够。能否见到一篇文章具有搜藏价值&#xff0c;就转到线下&#xff0c;以备日后慢慢消化吸收。这里终于找到一个办法&#xff0c;将在…...

C语言常见关键字

写在前面 这个博客是结合C语言深度解剖这本书和我以前学的知识综合而成的,我希望可以更见详细的谈一下C语言的关键字,内容有点多,有错误还请斧正. 常见关键字 下面我们说下C语言的关键字,所谓的关键字是指具有特定功能的单词,我们可以使用关键字来帮助我们完成不同的事物.C语…...

【MT7628】固件开发-SDK4320添加MT7612E WiFi驱动操作说明

解压5G WiFi MT7612E驱动1.1解压指令 tar -xvf MT76x2E_MT7620_LinuxAP_V3.0.4.0_P2_DPA_20160308.tar.bz2 1.2解压之后会出现以下两个目录 rlt_wifi rlt_wifi_ap 1.3将解压后的文件拷贝到系统下 拷贝路径 RT288x_SDK/source/linux-2.6.36.x/drivers/net/wireless 内核中打开驱…...

如何从手工测试进阶自动化测试?阿里10年测开经验分享...

随着行业的竞争加剧&#xff0c;互联网产品迭代速度越来越快&#xff0c;QA 与测试工程师都需要在越来越短的测试周期内充分保证质量。可是&#xff0c;App 测试面临着很多挑战&#xff0c;比如多端发布、多版本发布、多机型发布等等&#xff0c;导致了手工测试很难完全胜任。因…...

C++复习笔记11

1. vector是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是可以动态改变的&#xff0c;而且它的大小会被…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

OCR MLLM Evaluation

为什么需要评测体系&#xff1f;——背景与矛盾 ​​ 能干的事&#xff1a;​​ 看清楚发票、身份证上的字&#xff08;准确率>90%&#xff09;&#xff0c;速度飞快&#xff08;眨眼间完成&#xff09;。​​干不了的事&#xff1a;​​ 碰到复杂表格&#xff08;合并单元…...

鸿蒙HarmonyOS 5军旗小游戏实现指南

1. 项目概述 本军旗小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;采用DevEco Studio实现&#xff0c;包含完整的游戏逻辑和UI界面。 2. 项目结构 /src/main/java/com/example/militarychess/├── MainAbilitySlice.java // 主界面├── GameView.java // 游戏核…...