重生之“我打数据结构,真的假的?”--6.排序

1.排序的概念

排序:所谓排序,就是使⼀串记录,按照其中的某个或某些关键字的⼤⼩,递增或递减的排列起来的 操作。

1.1排序分类

2.排序算法实现 

2.1插入排序

直接插⼊排序是⼀种简单的插⼊排序法,其基本思想是:把待排序的记录按其关键码值的⼤⼩逐个插 ⼊到⼀个已经排好序的有序序列 中,直到所有的记录插⼊完为⽌,得到⼀个新的有序序列 。

 

实际中我们玩扑克牌时,就⽤了插⼊排序的思想

2.1.1直接插入排序 

当插⼊第 i(i>=1) 个元素时,前⾯的 array[0],array[1],…,array[i-1] 已经排好序,此时 ⽤ array[i] 的排序码与 array[i-1],array[i-2],… 的排序码顺序进⾏⽐较,找到插⼊位置 即将 array[i] 插⼊,原来位置上的元素顺序后移

void insertsort(int* arr, int n)
{int i = 0;int end;int tmp;for (i = 1; i < n; i++){end = i - 1;tmp = arr[i];           while (end >= 0){if (arr[end] >= tmp){arr[end + 1] = arr[end];--end;}else{break;}}arr[end + 1] = tmp;}
}                

特点总结: 

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

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

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

2.1.2希尔排序

希尔排序法⼜称缩⼩增量法。希尔排序法的基本思想是:先选定⼀个整数(通常是gap = n/3+1或n/2),把 待排序⽂件所有记录分成各组,所有的距离相等的记录分在同⼀组内,并对每⼀组内的记录进⾏排 序,然后gap=gap/3+1得到下⼀个整数,再将数组分成各组,进⾏插⼊排序,当gap=1时,就相当于 直接插⼊排序。 它是在直接插⼊排序算法的基础上进⾏改进⽽来的,综合来说它的效率肯定是要⾼于直接插⼊排序算 法的。

void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){//推荐写法:除3gap = gap / 3 + 1;for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}}

 

希尔排序的时间复杂度估算:

外层循环: 外层循环的时间复杂度可以直接给出为: O(log2 n) 或者 O(log3 n) ,即 O(log n) 内层循环:

假设⼀共有n个数据,合计gap组,则每组为n/gap个;在每组中,插⼊移动的次数最坏的情况下为 1 + 2 + 3 + .... + ( gap − ,⼀共是gap组,因此: n 1)) 总计最坏情况下移动总数为: gap ∗ [1 + 2 + 3 + .... + ( − gap n 1)] gap取值有(以除3为例):n/3 n/9 n/27 ...... 2 1

• 当gap为n/3时,移动总数为: ∗ 3 n (1 + 2) = n

• 当gap为n/9时,移动总数为: ∗ 9 n (1 + 2 + 3 + .... + 8) = ∗ 9 n = 2 8(1 + 8) 4n

• 最后⼀躺,gap=1即直接插⼊排序,内层循环排序消耗为n 通过以上的分析,可以画出这样的曲线图: 因此,希尔排序在最初和最后的排序的次数都为n,即前⼀阶段排序次数是逐渐上升的状态,当到达 某⼀顶点时,排序次数逐渐下降⾄n,⽽该顶点的计算暂时⽆法给出具体的计算过程 希尔排序时间复杂度不好计算,因为 gap 的取值很多,导致很难去计算,因此很多书中给出的希尔排 序的时间复杂度都不固定。《数据结构(C语⾔版)》--- 严蔚敏书中给出的时间复杂度为: 

 

2.2选择排序 

2.2.1直接选择排序

 选择排序的基本思想: 每⼀次从待排序的数据元素中选出最⼩(或最⼤)的⼀个元素,存放在序列的起始位置,直到全部待 排序的数据元素排完 。

1. 在元素集合 array[i]--array[n-1] 中选择关键码最⼤(⼩)的数据元素

2. 若它不是这组元素中的最后⼀个(第⼀个)元素,则将它与这组元素中的最后⼀个(第⼀个)元素 交换

3. 在剩余的 array[i]--array[n-2](array[i+1]--array[n-1]) 集合中,重复上述步 骤,直到集合剩余 1 个元素

 

void sellectsort(int* arr, int n)
{int begin = 0;int end = n - 1;while (begin < end){int min = begin;int max = begin;for (int i = begin; i <= end; i++){if (arr[i] > arr[max])max = i;if (arr[i] < arr[min])min = i;}if (begin==max)max= min;swap(&arr[min], &arr[begin]);swap(&arr[max], &arr[end]);begin++;end--;}
}

特点总结

1. 直接选择排序思考⾮常好理解,但是效率不是很好。实际中很少使⽤

2. 时间复杂度: O(N ) 2

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

 2.2.2堆排序 

堆排序(Heapsort)是指利⽤堆积树(堆)这种数据结构所设计的⼀种排序算法,它是选择排序的⼀ 种。它是通过堆来进⾏选择数据。需要注意的是排升序要建⼤堆,排降序建⼩堆。 在⼆叉树章节我们已经实现过堆排序,可移步至重生之“我打数据结构,真的假的?”--5.堆(无习题)-CSDN博客

2.3交换排序

2.3.1冒泡排序

前⾯在算法题中我们已经接触过冒泡排序的思路了,冒泡排序是⼀种最基础的交换排序。之所以叫做 冒泡排序,因为每⼀个元素都可以像⼩⽓泡⼀样,根据⾃⾝⼤⼩⼀点⼀点向数组的⼀侧移动。

void bubblesort(int* arr, int n)   //冒泡排序
{bool exchange = false;for (int i = 0; i < n; i++){for (int j = 0; j < n - i; j++){if (arr[j - 1] > arr[j]){int tmp = arr[j];arr[j] = arr[j - 1];arr[j - 1] = tmp;exchange = true;}}if (exchange == false)        //如果第一遍没排序,证明原数组有序,不用继续了{break;}}
}

• 时间复杂度: O(N ) 2

• 空间复杂度: O(1) 

2.3.2 快速排序  

快速排序是Hoare于1962年提出的⼀种⼆叉树结构的交换排序⽅法,其基本思想为:任取待排序元素 序列中的某元素作为基准值,按照该排序码将待排序集合分割成两⼦序列,左⼦序列中所有元素均⼩ 于基准值,右⼦序列中所有元素均⼤于基准值,然后最左右⼦序列重复该过程,直到所有元素都排列 在相应位置上为⽌。

int partsort(int* arr, int left, int right)
{int key = left;while (left < right){while (left < right && arr[right] >= arr[key])right--;while (left < right && arr[left] <= arr[key])left++;swap(&arr[left], &arr[right]);}swap(&arr[left], &arr[key]);return left;
}void quicksort(int* arr, int begin, int end)
{if (begin >= end)return;int key = partsort(arr, begin, end);quicksort(arr, begin, key - 1);quicksort(arr, key+1, end);}

快速排序特性总结:

1. 时间复杂度: O(nlogn)

2. 空间复杂度: O(logn) 

2.4 归并排序

归并排序(MERGE-SORT)是建⽴在归并操作上的⼀种有效的排序算法,该算法是采⽤分治法(Divide and Conquer)的⼀个⾮常典型的应⽤。将已有序的⼦序列合并,得到完全有序的序列;即先使每个 ⼦序列有序,再使⼦序列段间有序。若将两个有序表合并成⼀个有序表,称为⼆路归并。 归并排序核 ⼼步骤:

 

void _mergesort(int* arr, int begin, int end, int* brr)
{if (begin != end){int mid = (begin + end) / 2;int begin1 = begin;int begin2 = mid + 1;int end1 = mid;int end2 = end;_mergesort(arr, begin1, end1, brr);_mergesort(arr, begin2, end2, brr);int i = begin;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] < arr[begin2]){brr[i++] = arr[begin1++];}else{brr[i++] = arr[begin2++];}}while(begin1<=end1)brr[i++] = arr[begin1++];while (begin2 <= end2)brr[i++] = arr[begin2++];memcpy(arr+begin, brr+begin, sizeof(int) * (end - begin + 1));        //用于整数数组间的元素传递,第三个参数为要传的元素个数,需要<string.h>头文件}elsereturn;
}void mergesort(int* arr, int n)
{int* brr = (int*)malloc(sizeof(int) * n);int begin = 0;int end = n - 1;_mergesort(arr, begin, end, brr);
}

归并排序特性总结:

1. 时间复杂度: O(nlogn)

2. 空间复杂度: O(n) 

3. 排序算法复杂度及稳定性分析

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的 相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,⽽在排序后的序列中,r[i]仍在r[j]之 前,则称这种排序算法是稳定的;否则称为不稳定的。

 

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

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

相关文章

【Nginx】Windows生成ssl证书,Nginx反向代理HTTPS

下载 OpenSSL 环境 Windows、Linux, 证书我是在Windows上生成的自签证书。 https://slproweb.com/products/Win32OpenSSL.htmlWin64 OpenSSL v3.3.1 EXE&#xff08;这个&#xff09; | MSISelect Additional Tasks页面勾选 The OpenSSL binaries (/bin) directory 然后将Op…

一篇文章学完Python基础

1. 字符串 str1 "Hello" str2 " World" print(str1 str2) # 输出&#xff1a;HelloWorld 1.1 字符替换 text "Hello, World!" new_text text.replace("World", "Python") print(new_text) # 输出&#xff1a;…

2024第八届自然语言处理与信息检索国际会议 (NLPIR 2024)即将召开!

2024第八届自然语言处理与信息检索国际会议 (NLPIR 2024)将于2024年12月13-15日在日本冈山的冈山大学举行。NLPIR 2024将为自然语言处理与信息检索领域的专家学者提供一个交流与合作的平台&#xff0c;推动该领域的学术进步和技术创新。同时&#xff0c;本次会议也将为相关企业…

Golang 高性能 Websocket 库 gws 使用与设计(一)

前言 大家好这里是&#xff0c;白泽&#xff0c;这期分析一下 golang 开源高性能 websocket 库 gws。 视频讲解请关注&#x1f4fa;B站&#xff1a;白泽talk 介绍 gws&#xff1a;https://github.com/lxzan/gws &#xff5c;GitHub &#x1f31f; 1.2k&#xff0c;高性能的 …

0724,select +tcp 聊天室喵

目录 TCP协议喵 723__01&#xff1a;使用select实现一个基于UDP的一对一即时聊天程序。 001: 002: TIMEWAI OR BUG 721作业&#xff1a; 01&#xff1a;在一对一聊天的基础上&#xff0c;使用select实现一对多的回显服务。&#xff08;回显服务即接收到客户端发送的数…

Pyppeteer 的使用

puppeteer 是基于Node.js 开发的一个工具, 有了它&#xff0c;我们可以利用 JavaScript 控制 Chrome 浏览器的一些操作。当然&#xff0c; puppeteer 也可以用于网络爬虫&#xff0c;其 API 及其完善&#xff0c;功能非常强大。 Pyppeteer 其实是 puppeteer 的 python 实现&…

.net 连接达梦数据库开发环境部署

.net 开发环境部署 1. 环境准备 测试工具 Visual Studio2022 数据库版本 dm8 2. 搭建过程 1 &#xff09;创建新项目 2 &#xff09;选择创建空项目 3 &#xff09;配置新项目 4 &#xff09;右键 DM1 新建一个项 5 &#xff09;加 载 驱 动 &#xff0c; 新 建 …

0722_驱动3 地址映射驱动点灯

一、为什么需要地址映射 在芯片手册上查看到的地址属于物理地址&#xff0c;在硬件层 在内核空间地址属于虚拟地址&#xff0c;在内核层 在驱动中&#xff0c;操作的是虚拟地址 需要将物理地址《--mmu内存管理单元--》虚拟地址映射 二、映射API接口 void *ioremap(unsigned lon…

backtrace

介绍 arm平台的调用栈与x86平台的调用栈大致相同&#xff0c;稍微有些区别&#xff0c;主要在于栈帧的压栈内容和传参方式不同。在arm平台的不同程序&#xff0c;采用的编译选项不同&#xff0c;程序运行期间的栈帧也会不同。有些工具在对arm的调用栈回溯时&#xff0c;可能会…

电商项目之如何判断线程池是否执行完所有任务

文章目录 1 问题背景2 前言3 4种常用的方法4 代码4.1 isTerminated()4.2 线程池的任务总数是否等于已执行的任务数4.3 CountDownLatch计数器4.4 CyclicBarrier计数器 1 问题背景 真实生产环境的电商项目&#xff0c;常使用线程池应用于执行大批量操作达到高性能的效果。应用场景…

Dify中语音和文字间转换问题的一种暂时注释方式

本文主要解释了Dify中语音和文字间转换可能会遇到的问题&#xff0c;并给出了一种暂时注释的解决方案。 一.文本转语音可能问题 本地部署文本转语音时&#xff0c;如果遇到如下问题&#xff0c;安装ffmpeg即可。但是如果安装后&#xff0c;重启系统还是遇到这个问题该如何办&…

分库分表——从理论到最佳实践

目录 1、为什么要分库分表&#xff1f;2、切分方案有哪些&#xff1f;2.1 分库2.1.1 垂直分库2.1.2 水平分库 2.2 分表2.2.1 垂直分表2.2.2 水平分表 2.3 分库分表 3、数据水平分片方法3.1 Hash分片3.2 一致性Hash分片3.3 Range分片 4、分库分表的挑战4.1 分布式id4.2 分布式事…

LLM:归一化 总结

一、Batch Normalization 原理 Batch Normalization 是一种用于加速神经网络训练并提高稳定性的技术。它通过在每一层网络的激活值上进行归一化处理&#xff0c;使得每一层的输入分布更加稳定&#xff0c;从而加速训练过程&#xff0c;并且减轻了对参数初始化的依赖。 公式 …

分类模型——逻辑回归和Fisher线性判别分析

个人学习笔记&#xff0c;课程为数学建模清风付费课程 目录 一、引例 二、逻辑回归 2.1线性概率模型 2.2Fisher线性判别分析 2.3两点分布&#xff08;伯努利分布&#xff09; 2.4连接函数的取法 2.5如何求解 2.6如何用于分类 三、SPSS 3.1二元分类 3.1.1逻辑回…

MySQL内如何改变编码格式

查找数据库的编码格式&#xff1a; show variables like character%;具体内容时这些 在创建表时设定编码格式&#xff1a; create database <要创建的数据库的名字> charset utf8; 修改数据库默认编码&#xff1a; set character_set_databaseutf8mb4; character_…

eclipse ui bug

eclipse ui bug界面缺陷&#xff0c;可能项目过多&#xff0c;特别maven项目过多&#xff0c;下载&#xff0c;自动编译&#xff0c;加载更新界面异常 所有窗口死活Restore不回去了 1&#xff09;尝试创建项目&#xff0c;还原界面&#xff0c;失败 2&#xff09;关闭所有窗口&…

将TP5链接导入笔影个人博客代码

首先第一步&#xff0c;打开界面 第二步&#xff0c;这里卡住了&#xff0c;无法看到源代码&#xff0c;我们使用其他软件看看源代码 调试乱码&#xff0c;因为没有找到相应的笔影个人博客源码。源码在桌面上。询问百度&#xff0c;说了有的没的一大堆。 尝试的结果就是失败…

时间复杂度与O(n)

文章目录 1 复杂度分析1.1 时间复杂度1.1.1 循环执行次数1.1.2 大O(n)表示法 1.2 空间复杂度 1 复杂度分析 1.1 时间复杂度 ​ 时间复杂度用来表示算法运行时间的长短&#xff0c;用来定性的描述程序的运行时间。要了解时间复杂度&#xff0c;我们需要先了解程序执行的次数。…

机器学习(二十二):精度和召回率

一、倾斜数据集 倾斜数据集&#xff1a;一个数据集中的正面和负面例子的比例非常不平衡&#xff0c;比如数据集中&#xff0c;结果为1的占比20%&#xff0c;结果为0的占比80% 例子&#xff1a;如果数据集的结果中只有0.5%是1&#xff0c;其余结果是0。有一个模型的预测准确度…

【信创】udisk2服务异常导致U盘使用中自动移除问题解决

原文链接&#xff1a;【信创】udisk2服务异常导致U盘使用中自动移除问题解决 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在信创终端操作系统上由于udisk2服务异常导致U盘等移动设备在使用中自动移除问题的排查文章。udisk2是一个管理存储设备的服务&#xf…