数据结构初阶--排序1

目录

  • 前言
  • 冒泡排序
    • 思路
    • 代码实现
  • 选择排序
    • 思路
    • 代码实现
  • 插入排序
    • 思路
    • 代码实现
  • 希尔排序
    • 思路
    • 代码实现
  • 堆排序
    • 思路
      • 向上调整建堆
      • 向下调整建堆
    • 代码实现

前言

排序在我们的日常生活中无处不在,比如对若干个学生的期末成绩,可以依据姓氏,学号,某科成绩,总成绩等进行排名,富豪榜的排名,游戏中的战力排名,甚至是在日常生活中的扑克牌,我们也会依据其数字大小等对其进行排序,所以我们在学习编程的过程中,排序一定是十分重要并且对于我们十分有帮助的东西,所以本篇文章,将对几大重要排序算法–冒泡排序,插入排序,希尔排序,选择排序,堆排序,快速排序,归并排序进行讲解。

冒泡排序

冒泡排序,几乎是所有编程初学者接触到的第一种排序算法,虽然由于其时间复杂度过大没有什么实际的应用价值,但其还是有很强的教学意义的。

思路

冒泡排序的基本思路就是相邻的两个元素两两比较,不断地将较大/小的值往后放,一趟下来最后一个元素就是最大/小值,然后再重复此过程即可。

代码实现

冒泡排序的代码实现如下

void BubbleSort(int arr[], int n)
{for (int i = 0; i < n; i++){for (int j = 1; j < n - i; j++){if (arr[j - 1] > arr[j]){int temp = arr[j - 1];arr[j - 1] = arr[j];arr[j] = temp;}}}
}

冒泡排序的时间复杂度是O(N^2),可见消耗是十分大的。

选择排序

选择排序和冒泡排序的思想是类似的。

思路

选择排序和冒泡排序唯一的不同就是,冒泡排序是比较相邻的元素,而选择排序是将一个元素和它后面所有的元素进行比较.也没有什么难度。

代码实现

选择排序的代码实现如下

void SelectSort(int arr[], int n)
{for (int i = 0; i < 9; i++){for (int j = i + 1; j < 10; j++){if (arr[i] > arr[j]){int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}}
}

选择排序的时间复杂度是O(N^2),时间消耗和冒泡一样,也是十分巨大的。

插入排序

插入排序的思想就和我们平时打扑克牌时理牌的思路差不多

思路

我们平时在打扑克牌时,我们一般是摸一张整理一张,这样可以保证我每次放进一张牌之前的牌都是有序的,然后将我们要插入的牌从后往前(之所以不从前往后,是因为我们插入牌,相当于插入数据的时候,需要将后面的所有数据依次往后挪动,为这个数据(牌)留出一个位置)依次进行比较,放入合适的位置。

代码实现

插入排序的代码实现如下

void InsertSort(int arr[], int n)
{for (int i = 0; i < n - 1; i++){// 2 3 4 3int end = i;int temp = arr[end + 1];while (end >= 0){if (arr[end] > temp){arr[end + 1] = arr[end];end--;}else{break;}}arr[end + 1] = temp;}}

插入排序的算法也是O(N^2),但是它有别于前两个算法,因为数据越接近有序,它的时间效率就越高,不像前两个排序一样就算有序仍然要进行比较。而且它还能作为接下来要讲的一个很强的排序–希尔排序的辅助实现。

希尔排序

希尔排序是对直接插入排序的优化。

思路

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成n/gap个
组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后,取重复上述分组和排序的工作。当到达gap=1时,所有记录在统一组内排好序。
当gap>1时叫做预排序,目的是使数组接近有序,因为假设我们考虑一个最坏的情况,数组最开始是降序排列的,我们要将其升序排列,相当于位于第一个位置的最大的数要放到最后的位置去,如果我们用插入排序的思想去排,那么要比较长度次才能将这个数放到最后去,这样消耗是十分大的,但是我们可以增大比较的数据之间的间隔,以此来减小比较的次数,
这样假设有10个数据,如图

  1. 我们要将9放到正确的位置(即0的位置),如果使用插入排序的思想,需要比较9次才能成功。但如果我们用希尔排序的思想,间隔gap(假设为3)进行比较,这样比较2次就能到达正确的位置,如果数据量很大,这样操作能大大节省时间。

    然后我们再往后,从8开始往后依次间隔为3比较,即图中的8,5,2。然后再是7,4,1这一组,这样就完成了一次预排序了。当然我们也可以将这三次分组比较进行合并,即9和6比完了就轮到8和5比,然后就到7和4比,然后就又轮到第一组,以此类推
  2. 在进行完一次预排序后,我们逐步的缩小gap的值,我们不难发现规律,当gap越小时,其预排序后越接近有序
  3. gap减小为1时,就是直接插入排序,至此排序就完成了。

代码实现

希尔排序的代码实现如下

void ShellSort(int arr[], int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;for (int i = 0; i < n - gap; i++){int end = i;int temp = arr[end + gap];while (end >= 0){if (arr[end] > temp){arr[end + gap] = arr[end];end -= gap;}else{break;}}arr[end + gap] = temp;}}
}

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的希尔排序的时间复杂度都不固定。

堆排序

学习堆排序前我们要首先了解什么是堆。

堆其实就是一种二叉树,堆满足以下两种性质:
1. 堆中某个节点的值总是不大于或不小于其父节点的值;
2.堆总是一棵完全二叉树。

思路

要实现堆排序,我们首先要实现一个堆,然后才能进行后续操作,而堆虽然是一个完全二叉树,但在本质上,还是以数组的形式存储的.这里我们要用两种算法–向上调整建堆和向下调整建堆

向上调整建堆

向上调整建堆在插入数据以前必须要保证之前的数组满足是一个大堆或者小堆,向上调整建堆,顾名思义,就是要将插入到尾部的数据在其祖先这条线路上进行迭代调整,如图圈出来的部分就是我们要调整的部分。

我们不难发现这是一个小堆,那么此时我们就要将插入的3放到正确的位置上去,我们经过如图的操作即可实现,最终3会到根节点的位置。

向下调整建堆

向下调整建堆,其实就是调整根节点的位置,但在这之前要保证其左右子树都是大堆或者小堆

然后我们要比较父亲和左右孩子的大小,如果是小堆,我们就要选出左右孩子种较小的那个,比如图中的10,我们就要和5进行对调,如果和9进行对调,9变成父节点比5大,就不满足小堆了。所以正确的方法是如图所示的路径。

在学习完这两种算法后我们就要来尝试实现堆排序了。

1。首先我们通过向上/向下调整算法建立一个小堆(大堆也行,这里用小堆举例)。建立的思路就是依次往数组里放入数据,最开始只有一个数据的时候我们可以看做是一个堆,以此类推,我们就能满足每次插入数据之前都是一个堆
2.在创建完堆后,我们后续操作出来的数组是升序还是降序就取决于这是一个大堆还是小堆,我们第一步这说的是建立小堆,那么我们最终得到的数组也只能是降序,反之则是升序,这是为什么呢?
我们建立了小堆,最小的数就在根节点的位置,但由于其物理上是数组,如果我们直接在根节点把这个最小的数取出来,后面的所有数据父子关系就全乱了。所以正确的思路是把其根节点与最后一个数据交换,保证其堆的结构大致不变(即左右子树还是堆),接着我们根据这个特性首先想到向下调整算法继续选出次小的数,再和倒数第二个数交换,这样以此类推,我们就会发现数组就成为降序排列了。

代码实现

堆排序的代码实现如下

void AdjustUp(int arr[],int child)
{int parent = (child - 1) / 2;while (child > 0){if (arr[parent] < arr[child]){Swap(&arr[parent], &arr[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}
void AdjustDown(int arr[], int n,int parent)
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && arr[child + 1] > arr[child]){child = child + 1;}if (arr[parent] < arr[child]){Swap(&arr[parent], &arr[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void HeapSort(int arr[], int n)
{//向上调整建堆for(int i=1;i<n;i++)AdjustUp(arr,i);//升序--建大堆//降序--建小堆int end = n - 1;while (end > 0){Swap(&arr[0], &arr[end]);AdjustDown(arr, end, 0);end--;}}

本篇内容到这里就结束了,如有出入,欢迎指正。

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

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

相关文章

C# Linq 详解二

目录 概述 七、OrderBy 八、OrderByDescending 九、Skip 十、Take 十一、Any 十二、All C# Linq 详解一 1.Where 2.Select 3.GroupBy 4.First / FirstOrDefault 5.Last / LastOrDefault C# Linq 详解二 1.OrderBy 2.OrderByDescending 3.Skip 4.Take 5.Any 6.All C#…

WebSocket从入门到精通

WebSocket 是什么&#xff1f; WebSocket是HTML5规范提出的一种协议&#xff1b;目前除了IE浏览器&#xff0c;其他浏览器都基本支持。它是一种协议&#xff0c;万变不离其宗&#xff0c;也是基于TCP协议的&#xff0c;和HTTP协议是并存的两种协议。HTML5 Web Sockets规范定义了…

SpringBoot 整合RabbitMQ

SpringBoot 整合 RabbitMQ 概念 2007 年发布&#xff0c;是一个在 AMQP(高级消息队列协议)基础上完成的&#xff0c;可复用的企业消息系统&#xff0c;是当前最主流的消息中间件之一。 RabbitMQ是一个由erlang开发的AMQP&#xff08;Advanced Message Queue 高级消息队列协议…

gma 2 教程(二)数据操作:3. 支持生成的栅格格式信息

为了方便了解和选择输出栅格格式、配置高级创建选项&#xff0c;下表列出了gma可以生成&#xff08;复制/创建/转换&#xff09;的所有栅格格式的主要信息&#xff1a; 格式名生成模式支持数据类型扩展名多维栅格支持色彩映射表支持的数据类型多波段支持压缩模式AAIGrid复制By…

微擎后台getshell,低权限也可以

/web/index.php?csite&aeditor 这个文件可以编辑html&#xff0c;然后前台会解析成php 没测试最新版 比如编辑专题&#xff1a;/web/index.php?csite&aeditor&dopage&multiid0 上架抓包 改html内容为php 复制前台url 访问之 博客原文&#xff1a; 微擎后…

4、Kubernetes 架构、理解 k8s 架构

kubeadm 用于初始化 Cluster。 kubectl 是 Kubernetes 命令行工具。通过 kubectl 可以部署和管理应用,查看各种资源,创建、删除和更新各种组件。 kubelet 运行在 Cluster 所有节点上,负责启动 Pod 和容器。 Kubernetes Cluster 由 Master 和 Node 组成,节点上运行着若干 Ku…

Python——— 面向对象

&#xff08;一&#xff09;初识面向对象 Python完全采用了面向对象的思想&#xff0c;是真正面向对象的编程语言&#xff0c; 完全支持面向对象的基本功能&#xff0c;例如&#xff1a;继承、多态、封装等。 Python 支持面向过程、面向对象、函数式编程等多种编程范 式。 Pyth…

6.2Java EE——Spring的入门程序

下面通过一个简单的入门程序演示Spring框架的使用&#xff0c;要求在控制台打印“张三&#xff0c;欢迎来到Spring”&#xff0c;实现步骤具体如下。 1、在IDEA中创建名称为chapter06的Maven项目&#xff0c;然后在pom.xml文件中加载需使用到的Spring四个基础包以及Spring依赖…

SpringCloud Alibaba微服务分布式架构组件演变

文章目录 1、SpringCloud版本对应1.1 技术选型依据1.2 cloud组件演变&#xff1a; 2、Eureka2.1 Eureka Server &#xff1a; 提供服务注册服务2.2 EurekaClient &#xff1a; 通过注册中心进行访问2.3 Eureka自我保护 3、Eureka、Zookeeper、Consul三个注册中心的异同点3.1 CP…

Amazon 上的数字孪生:使用 L3 预测性数字孪生来预测“行为”

在上一篇博文中&#xff0c;我们讨论了数字孪生的定义和框架&#xff0c;这与我们的客户在其应用中使用数字孪生的方式一致。我们将数字孪生定义为“单个物理系统的动态数字表示&#xff0c;它通过数据进行动态更新以模仿物理系统的真实结构、状态和行为&#xff0c;从而加快获…

2023 node 接入腾讯云短信服务,实现发送短信功能

1、在 腾讯云开通短信服务&#xff0c;并申请签名和正文模板 腾讯云短信 https://console.cloud.tencent.com/smsv2 a、签名即是短信的开头。例如 【腾讯云短信】xxxxxxx&#xff1b; b、正文模板即短信内容&#xff0c; 变量部分使用{1}&#xff0c; 数字从1开始累推。例如&a…

(数组与矩阵) 剑指 Offer 03. 数组中重复的数字 ——【Leetcode每日一题】

❓ 剑指 Offer 03. 数组中重复的数字 难度&#xff1a;简单 找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请找出…