【C/C++数据结构 - 2】:稳定性与优化揭秘,揭开插入排序、希尔排序和快速排序的神秘面纱!

文章目录

  • 排序的稳定性
  • 插入排序
    • 插入排序的优化
  • 希尔排序
  • 快速排序

排序的稳定性

稳定排序:排序前2个相等的数在序列中的前后位置顺序和排序后它们2个的前后位置顺序相同。(比如:冒泡、插入、基数、归并)

非稳定排序:排序前2个数的相对位置在排序后会发生改变。(比如:选择、快速、希尔、堆等)

插入排序

插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。

插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。

在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。

void Insertion_Sort(int a[], int len)
{//外层循环 - 插入数据量for (int i = 1; i < len; i++){//内层循环 - 每一趟需要做的事情for (int j = i - 1; j > -1; j--){if (a[j]>a[j + 1]){int temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;}}}
}

插入排序的优化

在下面函数中,通过使用一个临时变量temp来保存当前需要插入的元素。外层循环通过对整个待排序序列进行遍历,从第二个元素开始(下标为1),将当前元素保存在temp中。

然后,内层循环从当前元素的前一个元素开始向前遍历,直到找到合适的位置插入temp。在内层循环中,如果当前遍历到的元素大于temp,就将该元素后移一位,给temp腾出位置。

内层循环结束后,将temp插入到合适的位置,即将其赋值给a[j+1],这样就完成了一次元素的插入。

通过这种方式,不断地将元素逐个地插入到已排序的序列中,最终得到一个完全有序的序列。

void Insertion_Sort(int a[], int len)
{int temp, i, j;//外层循环 - 插入数据量for (i = 1; i < len; i++){temp = a[i];//内层循环 - 每一趟需要做的事情for (j = i - 1; j > -1 && a[j] > temp; j--){a[j + 1] = a[j];}//移动结束a[j + 1] = temp;}
}

希尔排序

希尔排序(Shell Sort)是一种改进的插入排序算法,也被称为“缩小增量排序”(Diminishing Increment Sort)。希尔排序通过将待排序序列分割成多个子序列来进行排序,最终将这些子序列逐步合并为一个有序序列。

希尔排序的核心思想是通过定义一个增量序列(也称为间隔序列),将待排序序列划分成若干个子序列,并对这些子序列分别进行插入排序。随着排序的进行,增量序列会不断减小,直到变为1,此时对整个序列进行一次插入排序,最终完成排序。

希尔排序的步骤如下:

  • 首先确定一个增量序列,一般选择初始增量为序列长度的一半,然后每次将增量折半,直到增量变为1。

  • 对每个增量进行插入排序,即将待排序序列划分成若干个子序列,对每个子序列进行插入排序。

  • 在每次插入排序中,按照增量的大小,将元素分组,对每组进行插入排序。

  • 不断缩小增量,重复步骤2和步骤3,直到增量为1,进行最后一次插入排序,完成排序。

举个例子:

  • 如下图所示,现有一序列:8、5、7、3、6、1、2、8,选择初始增量为序列长度的一般,即初始增量为4(分为四个组,标红数字所示)。
    在这里插入图片描述
  • 第一次交换(组别增量为4)
    • 8和6为一组,5和1为一组……,队每组中的数比较排序,(例:第一组排序,8比6大,则8、6互换位置,以此类推)排序后的结果如下图所示。
      在这里插入图片描述
  • 第二次交换(组别增量由4变为2)如下图所示。
    在这里插入图片描述
    • 先对1组进行比较,首先6作为已序。
    • 第一次比较:1组的第一个数(6)与第二个数(2)进行比较,2<6小,插入到6的位置,6换到2的位置。
    • 第二次比较:1组的第二个数(6)与第三个数(8)进行比较,6<8,则不进行插入。
    • 第三次比较:1组的第三个数(8)与第4个数(7)进行比较,8>7,所以7插入到8的位置,8换到7的位置。
    • 最终1组排序的结果如下:
      在这里插入图片描述
    • 同理,对2组进行比较后的结果如下图所示。
      在这里插入图片描述
  • 第三次交换(组别增量从2变为1)
    在这里插入图片描述
    • 组别增量变为1之后,对整体做插入排序,结果如下。
      在这里插入图片描述

希尔排序函数:

//希尔排序
void Shell_Sort(int a[], int len)
{int temp, i, j, n = 0;//增量分组int jump = len >> 1;while (jump != 0){//外层循环 - 插入数据量for (i = jump; i < len; i++){temp = a[i];//内层循环for (j = i - jump; j >= 0 && a[j]>temp; j -= jump){a[j + jump] = a[j];n += 1;}//移动结束a[j + jump] = temp;}//增量更新jump >>= 1;}
}

分别在优化后的插入排序函数和希尔排序中定义一个变量n,用来统计各自进行数据交换的次数,结果如下:

在这里插入图片描述

插入排序交换的次数约是希尔排序交换次数的两倍!

快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。

快速排序的核心思想是通过分治法将一个大的待排序序列逐步地分割成小的子序列,然后对这些子序列进行排序,最终得到一个有序序列。具体步骤如下:

  1. 选择一个基准元素(pivot),可以是序列中的任意一个元素。
  2. 将序列分为两部分,小于等于基准元素的部分和大于基准元素的部分。可以通过两个指针 i 和 j 来实现,开始时 i 指向序列的第一个元素,j 指向序列的最后一个元素。
    • 从左向右找出第一个大于基准元素的元素,记为 a。
    • 从右向左找出第一个小于等于基准元素的元素,记为 b。
    • 如果 i < j,则交换 a 和 b 的位置,然后继续找下一对 a 和 b。
    • 如果 i >= j,则停止查找。
  3. 将基准元素与 j 所指向的元素交换位置,即将基准元素放在合适的位置。
  4. 递归地对基准元素左边和右边的子序列进行快速排序。

以下是一个使用 C 语言实现的快速排序代码示例:

#include <stdio.h>// 交换两个元素的值
void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}// 快速排序的递归函数
void quickSort(int arr[], int low, int high)
{if (low < high) {int pivot = arr[low];  // 选择第一个元素作为基准元素int i = low, j = high;while (i < j){while (i < j && arr[j] > pivot) {j--;}while (i < j && arr[i] <= pivot) {i++;}if (i < j) {swap(&arr[i], &arr[j]);}}swap(&arr[low], &arr[i]);quickSort(arr, low, i - 1);  // 对左边子序列进行快速排序quickSort(arr, i + 1, high); // 对右边子序列进行快速排序}
}// 打印数组元素
void printArray(int arr[], int size) 
{for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");
}int main() 
{int arr[] = {8, 5, 7, 3, 6, 1, 2, 8};int size = sizeof(arr) / sizeof(arr[0]);printf("原始数组:");printArray(arr, size);quickSort(arr, 0, size - 1);printf("排序后数组:");printArray(arr, size);return 0;
}

输出结果:

在这里插入图片描述

分析程序:
代码首先定义了一个 swap 函数用于交换两个元素的值。然后,quickSort 函数使用递归实现了快速排序的具体操作。最后,在 main 函数中创建一个待排序的数组,并调用 quickSort 函数对数组进行排序。最终,通过调用 printArray 函数打印排序后的数组。

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

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

相关文章

UVa658 It’s not a Bug, it’s a Feature!(Dijkstra)

题意 给出一个包含n个bug的应用程序&#xff0c;以及m个补丁&#xff0c;每个补丁使用两个字符串表示&#xff0c;第一个串表示补丁针对bug的情况&#xff0c;即哪些bug存在&#xff0c;以及哪些bug不存在&#xff0c;第二个串表示补丁对bug的修复情况&#xff0c;即修复了哪些…

进化算法------微生物进化算法(MGA)

前言 该文章写在GA算法之后&#xff1a;GA算法 遗传算法 (GA)的问题在于没有有效保留好的父母 (Elitism), 让好的父母不会消失掉. Microbial GA (后面统称 MGA) 就是一个很好的保留 Elitism 的算法. 一句话来概括: 在袋子里抽两个球, 对比两个球, 把球大的放回袋子里, 把球小…

ARMv5架构对齐访问异常问题

strh非对齐访问 在ARMv5架构中&#xff0c;对于strh指令&#xff08;Store Halfword&#xff09;&#xff0c;通常是要求对地址进行对齐访问的。ARMv5架构对于半字&#xff08;Halfword&#xff09;的存储操作有对齐要求&#xff0c;即地址必须是2的倍数。 如果尝试使用strh指…

2024北京国际光刻设备及光掩膜技术展览会

2024北京国际光刻设备及光掩膜技术展览会 Beijing Photolithography Equipment and Mask Application Technology Exhibition2024 基本信息 时间&#xff1a;2024年7月24-26日 地点&#xff1a;北京国家会议中心 展会简介 微电子技术的发展一直是光刻设备和技术变革的动力&…

二、使用DockerCompose部署RocketMQ

使用DockerCompose进行部署 RocketMQ的部署方式以及各自的特点 单master模式 只有一个 master 节点&#xff0c;如果master节点挂掉了&#xff0c;会导致整个服务不可用&#xff0c;线上不宜使用&#xff0c;适合个人学习使用。 多master模式 和kafka不一样&#xff0c;Rocke…

vue3 状态管理pinia

1. 什么是Pinia Pinia 是 Vue 的专属的最新状态管理库 &#xff0c;是 Vuex 状态管理工具的替代品 特点优势: 提供更加简单的API(去掉了mutation)提供符合组合式风格的API(和Vue3新语法统一)去掉modules的概念,每一个store都是一个独立的模块配合TypeScript更加友好,提供可靠的…

网站的常见攻击与防护方法

在互联网时代&#xff0c;几乎每个网站都存在着潜在的安全威胁。这些威胁可能来自人为失误&#xff0c;也可能源自网络犯罪团伙所发起的复杂攻击。无论攻击的本质如何&#xff0c;网络攻击者的主要动机通常是谋求经济利益。这意味着无论您经营的是电子商务项目还是小型商业网站…

【Redis】Set集合相关的命令

目录 命令SADDSMEMBERSSISMEMBERSCARDSPOPSMOVESREMSINTERSINTERSTORESUNIONSUNIONSTORESDIFFSDIFFSTORE 命令 SADD 将⼀个或者多个元素添加到set中。注意&#xff0c;重复的元素⽆法添加到set中。 SADD key member [member ...]SMEMBERS 获取⼀个set中的所有元素&#xff0…

vector Autosar someip和vsomeip协议调试总结

someip是现代车辆通信的主流通信协议知一&#xff1b; someip的主要涉及模型以及协议结构&#xff0c;我就不做多的做介绍了&#xff0c;如有需要请读者自行进行百度学些&#xff1b; 虽然someip协议已经基本成熟&#xff0c;但有多个实现版本&#xff0c;现在使用较多的主要…

④. GPT错误:导入import pandas as pd库,存储输入路径图片信息存储错误

꧂ 问题最初꧁ 用 import pandas as pd 可是你没有打印各种信息input输入图片路径 print图片尺寸 大小 长宽高 有颜色占比>0.001的按照大小排序将打印信息存储excel表格文件名 表格路径 图片大小 尺寸 颜色类型 占比信息input输入的是文件就处理文件 是文件夹&#x1f4c…

数据结构与算法—单链表

目录 一、链表 1、链表的概念及结构 2、分类 二、实现单向链表 1、声明链表结构体 2、输出 3、头插&尾插 4、头删尾删 5、查找 6、指定位置插入 7、删除指定节点 8、删除指定节点的后一个节点 9、单链表的销毁 完整版 LList.h LList.c text.c 一、链表 …

spring中事务相关面试题(自用)

1 什么是spring事务 Spring事务管理的实现原理是基于AOP&#xff08;面向切面编程&#xff09;和代理模式。Spring提供了两种主要的方式来管理事务&#xff1a;编程式事务管理和声明式事务管理。 声明式事务管理&#xff1a; Spring的声明式事务管理是通过使用注解或XML配置来…

LocalDateTime与时间戳

众所周知&#xff0c;如果想把 LocalDateTime 转为时间戳&#xff0c;需要先指定时区&#xff0c;然后才能转为时间戳&#xff0c;例如&#xff1a; LocalDateTime localDateTime LocalDateTime.now(); ZonedDateTime zonedDateTime localDateTime.atZone(ZoneId.systemDe…

BI工具:让数据分析井然有序一望而知

BI&#xff08;Business Intelligence&#xff09;工具是一类专门用于数据分析和决策支持的软件工具。 它们能够将企业内部和外部的数据进行整合、处理和可视化&#xff0c;帮助用户从海量数据中获取有价值的见解和洞察&#xff0c;并以直观、易懂的方式展示给决策者和相关人员…

ios app开发环境搭建

Xcode是Apple iOS的应用市场app store移动应用的开发工具&#xff0c;支持不同设备、不同应用场景的开发&#xff0c;本文主要描述xcode开发工具开发环境的搭建。 如上所示&#xff0c;在macos中&#xff0c;使用app store安装xcode开发工具 如上所示&#xff0c;在macos中&…

【网络协议】聊聊ifconfig

我们知道在linux是ifconfig查看ip地址&#xff0c;但是ip addr也可以查看 IP 地址是一个网卡在网络世界的通讯地址&#xff0c;相当于我们现实世界的门牌号码。 从IP地址的划分来看&#xff0c;C类地址只可以容纳254个&#xff0c;而B类6W多&#xff0c;那么又没有一种折中的…

design compiler中的drc规则详解

design compiler中的drc规则详解 DRC是什么&#xff1f;DRC分类各个DRC的含义写在最后 DRC是什么&#xff1f; 本文讨论的DRC即是Design Rule Constraint,而不是Design Rule Check&#xff0c;后者是物理端或者后端的一个关键步骤。 DRC分类 DRC为DC中的一个约束大类&#x…

设计模式——21. 中介者模式

1. 说明 中介者模式(Mediator Pattern)是一种行为设计模式,它允许对象之间通过一个中介者对象进行通信,而不是直接相互引用。这种模式有助于减少对象之间的直接关联,从而提高系统的可维护性和松耦合性。中介者模式将对象之间的交互集中在一个中介者对象中,该对象负责协调…

windows DOM 命令手册

Windows 打开windows中特定程序 win R > cmd > Enter # 打开 dos 窗口 win R > devmgmt.msc > Enter # 打开设备管理器 win R > services.msc > Enter # 打开服务管理器 基础命令 help-查看某个命令帮助信息 # 查看…

自动化办公篇之python

1、如果没有安装xlwings库&#xff0c;先在控制台pip install xlwings,然后点击运行&#xff0c;创建四个空excel表 。 import xlwings as xw app xw.App(visibleTrue,add_bookFalse) for dept in ["技术部","销售部","运营部","财务部&q…