数据结构——冒泡、选择、插入和希尔排序

2024-08-24 18:52

本文主要是介绍数据结构——冒泡、选择、插入和希尔排序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

引言

冒泡排序

1.算法思想

2.算法步骤

3.代码实现

4.复杂度分析

选择排序

1.算法思想

2.算法步骤

3.代码实现

(1)优化前

(2)优化后

4.复杂度分析

插入排序

1.算法思想

2.算法步骤

3.代码实现

4.复杂度分析

希尔排序

1.算法思想

2.算法步骤

3.代码实现

4.复杂度分析

结束语


引言

在数据处理、算法优化等领域中,排序是基础且关键的一环。本文将要探讨的四种排序算法:冒泡排序、选择排序、插入排序和希尔排序

求点赞收藏关注!!!

冒泡排序

1.算法思想

冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素为止,这意味着数列已经排序完成。

这个算法的名字由来是因为越小(或越大)的元素会经由交换慢慢“浮”到数列的顶端(或底部)。

2.算法步骤

1.比较相邻的元素。如果第一个比第二个大(或小,根据排序顺序要求),就交换它们两个。

2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数(或最小的数)。

3.针对所有的元素重复以上的步骤,除了已完成排序元素。

4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较

注意:如果一轮之后,元素并没有发生任何交换,此时说明此时排序已经完成,那么我们可以提前结束循环。

我们来看个动图就能很直观的理解什么是冒泡排序:

3.代码实现

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void bubble_sort(int arr[], int sz)
{// 外层循环,控制排序的轮数for (int i = 0; i < sz - 1; i++){// 定义一个标志位,用于判断是否在这一轮中有元素交换int flag = 0;// 内层循环,进行实际的元素比较和交换for (int j = 0; j < sz - i - 1; j++){// 如果当前元素大于后一个元素,则交换它们if (arr[j] > arr[j + 1]){// 设置标志位为1,表示发生了交换flag = 1;Swap(&arr[j], &arr[j + 1]);}}// 如果这一轮没有发生任何交换// 说明数组已经有序,可以提前结束排序if (flag == 0){break;}}
}

4.复杂度分析

时间复杂度:最坏情况是数组完全逆序,此时每一轮都需要进行 n - 1 次比较,并且每一轮都会进行至少一次交换.因此,总的比较次数和交换次数都接近 n (n - 1) / 2,其中 n 是数组的长度。所以,最坏情况下的时间复杂度是 O(n ^ 2) 。

空间复杂度:由于没有开辟额外的空间大小,因此空间复杂度为O(1)。

选择排序

1.算法思想

选择排序(Selection Sort)是一种简单直观的排序算法。通过不断选择剩余元素之中的最小(或最大)元素,然后与起始位置的元素交换(起始位置在每一次选择后都向后移动一位),直到整个序列排序完成。

2.算法步骤

1.在未排序序列中找到最小(大)元素。遍历未排序的数组,找到最小(或最大)的元素。

2.存放到排序序列的起始位置。将找到的最小(或最大)元素与未排序序列的第一个元素交换位置(如果第一个元素就是最小(大)元素,则它自己和自己交换)。

3.从剩余未排序元素中继续寻找:在剩下的未排序元素中继续执行步骤1和步骤2,直到所有元素都被排序。

 看动图直观的感受一下:

3.代码实现

(1)优化前
void SelectSort(int* arr, int len)
{for (int i = 0; i < len - 1; i++){// 假设当前位置i的元素是最小的,记录其索引为miniint mini = i;for (int j = i + 1; j < len; j++){// 如果发现更小的元素,则更新mini为当前更小元素的索引if (arr[j] < arr[mini]){mini = j;}}swap(&arr[mini], &arr[i]);}
}
(2)优化后

我们可以对上面的代码进行点优化,我们可以同时选择最大与最小的元素,同时往起始与结尾位置交换。

注意:同时交换可能会改变原先最大或者最小元素的位置。因此我们需要进行判断。

代码如下:

//交换两个数据
void Swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}void SelectSort(int* arr, int n)
{int begin = 0;		// 未排序部分的起始索引int end = n - 1;	// 未排序部分的结束索引while (begin < end){int maxi = begin;int mini = begin;// 遍历未排序部分,找到最小值和最大值for (int i = begin + 1; i <= end; i++){if (arr[i] < arr[mini]){mini = i;	// 更新最小值的位置}if (arr[i] > arr[maxi]){maxi = i;	// 更新最大值的位置}}// 将当前范围的最小值交换到未排序部分的开始位置Swap(&arr[begin], &arr[mini]);// 如果begin与maxi重合,则更新maxiif (maxi == begin){maxi = mini;}// 将当前范围的最大值交换到未排序部分的结束位置Swap(&arr[end], &arr[maxi]);// 缩小未排序部分的范围++begin;--end;}
}

4.复杂度分析

时间复杂度:由于每次外层循环中的内层循环需要遍历几乎所有未排序的元素,因此时间复杂度为O(n^2)。

空间复杂度:由于没有开辟额外的空间大小,因此空间复杂度为O(1)。

插入排序

1.算法思想

插入排序(Insertion Sort)是一种简单直观的排序算法。它模拟了我们日常生活中整理扑克牌或排序书籍的过程。其基本思想是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、元素个数加一的有序数据,直到全部待排序的数据元素插完,排序完成。

2.算法步骤

1.将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

2.遍历未排序部分,将扫描到的每个元素插入有序序列的适当位置。

3.依次重复1,2步骤,直至插入完成。

 动图演示如下:

3.代码实现

void InsertSort(int* arr, int n)
{for (int i = 0; i < n - 1; i++){int end = i;// tmp 存储当前需要插入的元素的值int tmp = arr[end + 1];// 内层循环,将比 tmp 大的元素向后移动一位// 为 tmp 找到正确的插入位置while (end >= 0){if (arr[end] > tmp){arr[end + 1] = arr[end];end--;}else{break;}}// 将 tmp 插入到找到的正确位置arr[end + 1] = tmp;}
}

4.复杂度分析

时间复杂度:当处于最坏情况时,由于每次插入都会移动数据,因此时间复杂度为O(n^2)。

空间复杂度:由于没有开辟额外的空间大小,因此空间复杂度为O(1)。

希尔排序

1.算法思想

希尔排序(Shell Sort)是插入排序的一种更高效的改进版本,也称为缩小增量排序。基本思想是将待排序的数组元素按照某种增量(gap)进行分组,对每组使用插入排序算法进行排序。随着增量的逐渐减少,每组包含的元素越来越多,当增量减至1时,整个数组被视为一组进行最后的插入排序,从而完成排序过程。

2.算法步骤

1.选择一个增量 gap ,对数据进行分组,每间隔gap个元素分为一组,一共gap组。

2.以gap为基准单位,对其进行插入排序。

3.逐渐缩小gap的范围,直至gap为1,相当于进行一次正常的插入排序。

 动图演示所下所示:

3.代码实现

void ShellSort(int* arr, int n)
{// 初始化增量gap为数组长度n,用于分组int gap = n;while (gap > 1){// 逐渐减少增量gap = gap / 3 + 1;// 对每个分组进行插入排序for (int i = 0; i < n - gap; i++){int end = i;int tmp = arr[end + gap];while (end >= 0){// 如果当前位置的元素大于tmp// 则将当前位置的元素向后移动gap位if (arr[end] > tmp){arr[end + gap] = arr[end];end -= gap;}else{break;}}// 将tmp插入到找到的正确位置arr[end + gap] = tmp;}}
}

4.复杂度分析

时间复杂度:希尔排序的时间复杂度一般较为难计算,通过大量测验一般认为其时间复杂为O(N^1.3)。

空间复杂度:由于没有开辟额外的空间大小,因此空间复杂度为O(1)。

结束语

本篇博客是数据结构——排序 的第一篇。

感谢各位大佬能阅读本文。

求点赞收藏关注!!!十分感谢!!!

这篇关于数据结构——冒泡、选择、插入和希尔排序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103320

相关文章

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

使用Python在Excel中插入、修改、提取和删除超链接

《使用Python在Excel中插入、修改、提取和删除超链接》超链接是Excel中的常用功能,通过点击超链接可以快速跳转到外部网站、本地文件或工作表中的特定单元格,有效提升数据访问的效率和用户体验,这... 目录引言使用工具python在Excel中插入超链接Python修改Excel中的超链接Python

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig