排序
排序算法简介
排序算法用作实现列表的排序,列表元素可以是整数,也可以是浮点数、字符串等其他数据类型。生活中有许多需要排序算法的场景,例如:
整数排序: 对于一个整数数组,我们希望将所有数字从小到大排序;
字符串排序: 对于一个姓名列表,我们希望将所有单词按照字符先后排序;
自定义排序: 对于任意一个 已定义比较规则 的集合,我们希望将其按规则排序;
1.冒泡排序
参考链接:https://leetcode.cn/leetbook/read/illustration-of-algorithm/phn3m1/
冒泡排序是最基础的排序算法,由于其直观性,经常作为首个介绍的排序算法。其原理为:
内循环: 使用相邻双指针 j , j + 1 从左至右遍历,依次比较相邻元素大小,若左元素大于右元素则将它们交换;遍历完成时,最大元素会被交换至数组最右边 。
外循环: 不断重复「内循环」,每轮将当前最大元素交换至 剩余未排序数组最右边 ,直至所有元素都被交换至正确位置时结束。
主要思想:依次对两个数比较大小,较大的数冒起来,较小的数压下来。
特点:简单易懂,排序稳定,但速度慢。
代码:
void bubbleSort(vector<int> &nums) { int N = nums.size(); for (int i = 0; i < N - 1; i++) { // 外循环 for (int j = 0; j < N - i - 1; j++) { // 内循环 if (nums[j] > nums[j + 1]) { // 交换 nums[j], nums[j + 1] swap(nums[j], nums[j + 1]); } } } }
2 选择排序
主要思想:针对冒泡排序,有一个地方可以优化,即在跑一趟的过程中,没必要两两交换,可以先记下最小值,跑完一趟后直接将最小值换到前面。
特点:比冒泡更快一些,但代价是跳跃性交换,排序不稳定。
/* 选择排序 */
void SelectionSort(int arr[], int length) { int index, temp; for (int i = 0; i < length; i++) { index = i; for (int j = i + 1; j < length; j++) { if (arr[j] < arr[index]) index = j; } if (index != i) { temp = arr[i]; arr[i] = arr[index]; arr[index] = temp; } } }
3 插入排序
主要思想:过程跟拿牌一样,依次拿N张牌,每次拿到牌后,从后往前看,遇到合适位置就插进去。最终手上的牌从小到大。
特点:当数据规模较小或者数据基本有序时,效率较高。
4 希尔排序
主要思想:设增量序列个数为k,则进行k轮排序。每一轮中,按照某个增量将数据分割成较小的若干组,每一组内部进行插入排序;各组排序完毕后,减小增量,进行下一轮的内部排序。
特点:针对插入排序的改进,当数据规模较大或无序时也比较高效。
5 堆排序
主要思想:将待排数组构建成一个最大堆,将堆顶最大元素换到后面,然后堆容量减1;类似进行N-1次操作即可。
6 快速排序
主要思想:分治思想。选一基准元素,依次将剩余元素中小于该基准元素的值放置其左侧,大于等于该基准元素的值放置其右侧;然后,取基准元素的前半部分和后半部分分别进行同样的处理;以此类推,直至各子序列剩余一个元素时,即排序完成。
注意:对于小规模数据(n<100),快排由于用了递归,其效率可能还不如插排。因此通常可以定义一个阈值,当递归的数据量很小时停止递归,直接调用插排。
7 归并排序
归并排序,顾名思义就是合并两个有序数组。常见的归并排序有两种,递归法(自上而下的合并)和非递归法(自底向上的合并),都需要新开一个大小为n的数组来中转。递归法比较简单,就是中间切一刀,左右分别递归排序,最后合并两个有序数组。非递归法就是先分别对相邻的两个元素合并排序,第二趟时候分别对相邻的四个元素合并排序(此时前两个元素和后两个元素已有序),第三趟时候对相邻的八个元素合并排序,依次类推直至有序数组长度超过数组总长度。两者相较,递归的归并排序代码更简洁,代价是时间和空间复杂度上都会更大(因为有递归的logn)。下面的代码是非递归方法,后续对比也按照这个版本。
主要思想:类似两个有序链表的合并,每次两两合并相邻的两个有序序列,直至整个序列有序。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-11-01 FreeRTOS(1):任务管理
2023-11-01 江科大STM32(1):第一个外设GPIO