【C语言】数据结构——排序(一)

💗个人主页💗
⭐个人专栏——数据结构学习⭐
💫点击关注🤩一起学习C语言💯💫

目录

  • 导读:
  • 数组打印与交换
  • 1. 插入排序
    • 1.1 直接插入排序
      • 1.1.1 基本思想
      • 1.1.2 实现代码
      • 1.1.3 图解
    • 1.2 希尔排序
      • 1.2.1 基本思想
      • 1.2.2 实现代码
      • 1.2.3 图解
  • 2. 选择排序
    • 2.1 直接选择排序
      • 2.1.1 基本思想
      • 2.1.2 实现代码
      • 2.1.3 图解
    • 2.2 堆排序
      • 2.2.1 基本思想
      • 2.2.2 实现代码
      • 图解

导读:

我们在前面学习了单链表,顺序表,栈和队列,小堆,链式二叉树。
今天我们来学习排序,包括直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快排以及归并排序。
冒泡排序,快排和归并排序我们放在之后分析,今天主要来分析前面的。
关注博主或是订阅专栏,掌握第一消息。

数组打印与交换

为了方便我们来测试每个排序是否完成,我们来写个打印数组和交换两数的函数,方便我们后续的打印与交换。

void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}

1. 插入排序

插入排序分为直接插入排序和希尔排序。
基本思想:

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

1.1 直接插入排序

1.1.1 基本思想

直接插入排序是一种简单直观的排序算法,其基本思想是将待排序的元素一个个插入到已排好序的部分中,从而逐步构建已经排序的序列。

  1. 首先,将待排序序列的第一个元素视为已排序部分,可以认为该部分只包含一个元素。
  2. 然后,依次将后面的元素插入到已排序部分中的正确位置。假设要插入的元素为A,那么从已排序部分的最后一个元素开始向前遍历,如果当前元素大于A,则将当前元素后移一位;反之,找到A应该插入的位置,将其插入到该位置。
  3. 重复步骤2,直到所有的元素都被插入到已排序部分中。

直接插入排序的时间复杂度为O(n^2),其中n为待排序序列的长度。辅助空间复杂度为O(1),是一种稳定的排序算法。

1.1.2 实现代码

void InsertSort(int* a, int n)
{int i = 0;for (i = 0; i < n - 1; i++){int end = i;int tmp = a[end + 1];// end往前移动while (end >= 0){// 如果tmp小于a[end] 让a[end]往后移动//也就是移动到end+1的位置if (tmp < a[end]){a[end + 1] = a[end];end--;}else{break;}}//循环结束 此时找到了比tmp小的数值 //把tmp的值放在其后面a[end + 1] = tmp;}
}void TestInsertSort()
{int arr[10] = { 5, 1, 8, 7, 3, 9, 2, 0, 4, 6 };int sz = sizeof(arr) / sizeof(arr[0]);InsertSort(arr, 10);//打印PrintArray(arr, 10);
}
int main()
{TestInsertSort();return 0;
}

1.1.3 图解

在这里插入图片描述

1.2 希尔排序

1.2.1 基本思想

希尔排序(Shell Sort)是一种排序算法,也被称为缩小增量排序。
基本思想是将待排序的数组分成若干个子序列,分别进行插入排序,然后逐步缩小增量,直到增量为1时进行最后一次排序。希尔排序的关键在于如何选择增量序列

  1. 初始化增量序列,通常取数组长度的一半作为初始增量,然后每次再缩小增量为前一次的一半。
  2. 对每个增量序列进行插入排序,从增量序列的第一个元素开始,将其与对应增量序列的后续元素逐个比较并插入到正确的位置。
  3. 缩小增量,重复步骤2,直到增量为1。
  4. 最后一次插入排序完成后,数组已经基本有序,但并不是完全有序的,此时再进行一次插入排序,将数组完全排序。

希尔排序的优点是相对于简单插入排序来说,移动的元素较少,比较次数也相对较少,可以提高排序效率。但是希尔排序的时间复杂度依赖于增量序列的选择,不同的增量序列可能会导致不同的排序效果。

1.2.2 实现代码

void ShellSort(int* a, int n)
{int gap = n;//gap > 1 时是预排序,目的让他接近有序//gap == 1是直接插入排序,目的是让他有序while (gap > 1){gap = gap / 3 + 1;int i = 0;//特别主要i的范围,避免越界for (i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}void TestShellSort()
{int arr[10] = { 5, 1, 8, 7, 3, 9, 2, 0, 4, 6 };int sz = sizeof(arr) / sizeof(arr[0]);ShellSort(arr, 10);PrintArray(arr, 10);
}int main()
{TestShellSort();return 0;
}

1.2.3 图解

在这里插入图片描述

2. 选择排序

选择排序可以分为直接选择排序和堆排序。
基本思想:

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

2.1 直接选择排序

2.1.1 基本思想

直接选择排序算法的基本思想是找到待排序序列中的最小(或最大)元素,将它与序列的第一个元素交换位置,然后再从剩下的未排序序列中找到最小(或最大)元素,与序列的第二个元素交换位置,依次类推,直到整个序列排好序为止。

  1. 遍历待排序序列,假设第一个元素为当前最小(或最大)元素。
  2. 从当前元素的下一个位置开始遍历,如果找到比当前元素更小(或更大)的元素,则将其索引记为最小(或最大)元素的索引。
  3. 遍历完成后,将最小(或最大)元素与当前元素交换位置。
  4. 重复以上步骤,直到整个序列排好序为止。

直接选择排序算法的时间复杂度为O(n^2),其中n为序列的长度。

2.1.2 实现代码

void SelectSort(int* a, int n)
{int begin = 0;int end = n - 1;while (begin < end){int min = begin;int max = begin;for (int i = begin + 1; i <= end; i++){if (a[i] < a[min]){min = i;}if (a[i] > a[max]){max = i;}}// 把最小的值移到最前面Swap(&a[begin], &a[min]);// 如果max=begin代表第一个元素为最大值// 但是经过上个语句已经把第一个元素和最小的元素交换if (max == begin){max = min;}//最大值放到后面Swap(&a[end], &a[max]);++begin;--end;}
}
void TestSelectSort()
{int arr[10] = { 5, 1, 8, 7, 3, 9, 2, 0, 4, 6 };int sz = sizeof(arr) / sizeof(arr[0]);SelectSort(arr, 10);PrintArray(arr, 10);
}int main()
{TestSelectSort();return 0;
}

2.1.3 图解

在这里插入图片描述

2.2 堆排序

2.2.1 基本思想

堆排序算法的基本思想是利用堆的数据结构进行排序。堆是一种特殊的树状数据结构,分为大顶堆和小顶堆两种类型。
对于大顶堆,父节点的值大于或等于子节点的值;对于小顶堆,父节点的值小于或等于子节点的值。堆排序利用堆的性质,使得每次操作的时间复杂度为O(log n)。

  1. 构建初始堆:将待排序序列构建成一个大顶堆。
  2. 将堆顶元素(最大值)与堆的最后一个元素交换位置,然后堆的大小减1。这样就将最大值移到了序列的末尾。
  3. 对新的堆顶元素进行向下调整(即将堆的根节点调整到正确的位置),使得剩余的元素重新构建成一个大顶堆。
  4. 重复步骤2和步骤3,直到堆的大小为1,即完成排序。

主要思想是通过不断地交换堆顶元素和堆的最后一个元素,将最大值依次放到序列的末尾,同时不断地调整堆结构,使得剩余元素保持堆的性质。最后得到的序列就是按照从小到大排序的结果。
堆排序的时间复杂度是O(nlogn),其中n是序列的大小。堆排序是一种不稳定的排序算法,因为在构建大顶堆的过程中,相同大小的元素可能会交换位置。

2.2.2 实现代码

我们之前有实现过堆,所以我们在这里直接引用即可。

// 向下调整
void AdjustDown(int* a, int size, int parent)
{int child = parent * 2 + 1;while (child < size){// 假设左孩子大,如果解设错了,更新一下if (child + 1 < size && a[child + 1] < a[child]){++child;}// 交换父节点和子节点if (a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void HeapSort(int* a, int n)
{//向下调整建大堆for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}int end = n - 1;// 遍历循环while (end > 0){// 将当前最大元素(堆顶)放到数组末尾Swap(&a[0], &a[end]);// 重新调整剩余元素构建的堆AdjustDown(a, end, 0);--end;}
}
void TestHeapSort()
{int arr[10] = { 5, 1, 8, 7, 3, 9, 2, 0, 4, 6 };int sz = sizeof(arr) / sizeof(arr[0]);HeapSort(arr, sz);PrintArray(arr, 10);
}
int main()
{TestHeapSort();return 0;
}

图解

在这里插入图片描述

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

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

相关文章

H266/VVC量化编码技术概述

量化 量化&#xff1a; 是将信号的连续取值&#xff08;或大量可能的离散取值&#xff09;映射为有限多个离散幅值的过程&#xff0c;实现信号取值多对一的映射。在视频编码中&#xff0c;残差信号经过变换之后&#xff0c;变换系数往往具有较大的动态范围。因此&#xff0c;对…

中央集成式架构量产时代,openVOC方案将引发软件开发模式变革

2024年&#xff0c;中央计算区域控制架构正式进入规模化量产周期&#xff0c;汽车智能化正式迈入2.0时代&#xff0c;产业生态、应用创新、开发模式都将迎来巨大变革。 同时&#xff0c;随着ChatGPT引发的AIGC领域的爆发式增长&#xff0c;人工智能技术掀起全球万亿级信息化应…

右键菜单“以notepad++打开”,在windows文件管理器中

notepad 添加到文件管理器的右键菜单中 找到安装包&#xff0c;重新安装一般即可。 这里有最新版&#xff1a;地址 密码:f0f1 方法 在安装的时候勾选 “Context Menu Entry” 即可 Notepad的右击打开文件功能 默认已勾选 其作用是添加右键快捷键。即&#xff0c;对于任何…

Android---Kotlin 学习013

互操作性和可空性 Java 世界里所有对象都可能是 null&#xff0c;而 kotlin 里面不能随便给一个变量赋空值的。所有&#xff0c;kotlin 取调用 java 的代码就很容易出现返回一个 null&#xff0c;而 Kotlin 的接收对象不能为空&#xff0c;你不能想当然地认为 java 的返回值就…

鸿蒙APP的代码规范

鸿蒙APP的代码规范是为了确保代码质量、可读性和可维护性而定义的一系列规则和标准。以下是一些建议的鸿蒙APP代码规范&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 代码风格&#xff1a; 采用…

OpenCV-Python(21):轮廓特征及周长、面积凸包检测和形状近似

2. 轮廓特征 轮廓特征是指由轮廓形状和结构衍生出来的一些特征参数。这些特征参数可以用于图像识别、目标检测和形状分析等应用中。常见的轮廓特征包括&#xff1a; 面积&#xff1a;轮廓所包围的区域的面积。周长&#xff1a;轮廓的周长&#xff0c;即轮廓线的长度。弧长&…

防火墙什么用,软件防火墙与硬件防火墙有什么不一样

防火墙是一种网络安全技术&#xff0c;通过有机结合各类用于安全管理与筛选的软件和硬件设备&#xff0c;在计算机网络的内、外网之间构建一道相对隔绝的保护屏障&#xff0c;以保护用户资料与信息的安全性。 防火墙的作用的详细说明&#xff1a; 1.访问控制&#xff1a;防火…

06|调用模型:使用OpenAI API还是微调开源Llama2/ChatGLM?

06&#xff5c;调用模型&#xff1a;使用OpenAI API还是微调开源Llama2/ChatGLM&#xff1f; 让我们带着下面的问题来开始这一节课的学习。大语言模型&#xff0c;不止 ChatGPT 一种。调用 OpenAI 的 API&#xff0c;当然方便且高效&#xff0c;不过&#xff0c;如果我就是想用…

解决Java编译出现类名不匹配报错

当遇到Java编译错误时&#xff0c;很多时候都是由于类名与文件名不匹配导致的。在Java中&#xff0c;公共类的名称必须与其所在的文件名一致&#xff0c;包括大小写敏感。下面是我在编译第一个Java程序"HelloWorld"时遇到的问题和解决办法的记录。 问题描述 在终端…

HCIA-Datacom题库(自己整理分类的)——OSPF协议多选

ospf的hello报文功能是 邻居发现 同步路由器的LSDB 更新LSA信息 维持邻居关系 下列关于OSPF区域描述正确的是 在配置OSPF区域正确必须给路由器的loopback接配置IP地址 所有的网络都应在区域0中宣告 骨干区域的编号不能为2 区域的编号范围是从0.0.0.0到255.255.255.255…

第十二章 Sleuth分布式请求链路跟踪

Sleuth分布式请求链路跟踪 gitee:springcloud_study: springcloud&#xff1a;服务集群、注册中心、配置中心&#xff08;热更新&#xff09;、服务网关&#xff08;校验、路由、负载均衡&#xff09;、分布式缓存、分布式搜索、消息队列&#xff08;异步通信&#xff09;、数…

VisualStudio项目中多个同名文件处理

问题 在vs2019环境中&#xff0c;现在开发一个较大的C项目&#xff0c;它的源文件在多个文件夹中组织(在文件系统上)。在其中两个文件夹中&#xff0c;有几个同名的文件。如&#xff1a; .\ConsoleApplication1\JAMGEN_CONFIG_x4_test\firls.c .\ConsoleApplication1\NoiseCo…

YOLOv8训练自定义数据集和运行参数解读

1、YOLOv8深度学习环境搭建及安装 1.1. Yolov8介绍 设置操作类型 YOLOv8模型可用于各种任务&#xff0c;包括检测、分割和分类。这些任务的不同之处在于它们产生的输出类型和它们要解决的特定问题。 **检测:**检测任务涉及识别和定位图像或视频中感兴趣的对象或区域。YOLO模…

多模态大模型-CogVLm 论文阅读笔记

多模态大模型-CogVLm 论文阅读笔记 COGVLM: VISUAL EXPERT FOR LARGE LANGUAGEMODELS 论文地址 :https://arxiv.org/pdf/2311.03079.pdfcode地址 : https://github.com/THUDM/CogVLM时间 : 2023-11机构 : zhipuai,tsinghua关键词: visual language model效果:&#xff08;2023…

一键访问多功能数据解决方案:如何轻松构建和管理APITable智能多维表格

文章目录 前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c;是一款面向 API 的智能多维表格。它将复杂的可视化数据库、电子表格、实时在线协同、低代码开发技术四合为一&am…

《数据库开发实践》之触发器

一、什么是触发器&#xff1f; 1.概念&#xff1a; 简单来说触发器就是一种特殊的存储过程&#xff0c;在数据库服务器触发事件的时候会自动执行其SQL语句集。 2.构成四要素&#xff1a; &#xff08;1&#xff09;名称&#xff1a;要符合标识符命名规则 &#xff08;2&am…

[OCR]Python 3 下的文字识别CnOCR

目录 1 CnOCR 2 安装 3 实践 1 CnOCR CnOCR 是 Python 3 下的文字识别&#xff08;Optical Character Recognition&#xff0c;简称OCR&#xff09;工具包。 工具包支持简体中文、繁体中文&#xff08;部分模型&#xff09;、英文和数字的常见字符识别&#xff0c;支持竖…

基于Java+SpringBoot+vue实现图书借阅管理系统

基于JavaSpringBootvue实现图书借阅和销售商城一体化系统 &#x1f345; 作者主页 程序设计 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; 文章目录 基于JavaSpringBootvue实现图书借阅和销售商城一体化…

elasticsearch-hadoop.jar 6.8版本编译异常

## 背景 重新编译 elasticsearch-hadoop 包&#xff1b; GitHub - elastic/elasticsearch-hadoop at 6.8 编译 7.17 版本时很正常&#xff0c;注意设置下环境变量就好&#xff0c;JAVA8_HOME/.... 编译 6.8 版本时&#xff08;要求jdk8 / jdk9&#xff09;&#xff0c;出现…

腾讯云轻量服务器和云服务器CVM该怎么选?区别一览

腾讯云轻量服务器和云服务器CVM该怎么选&#xff1f;不差钱选云服务器CVM&#xff0c;追求性价比选择轻量应用服务器&#xff0c;轻量真优惠呀&#xff0c;活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三…