【初阶数据结构】排序——选择排序

news/2024/10/9 2:58:24/

目录

  • 前言
  • 选择排序
  • 堆排序

前言

对于常见的排序算法有以下几种:
在这里插入图片描述
下面这节我们来看选择排序算法

选择排序

基本思想:
  每一次从待排序的数据元素中遍历选出最大(或最小)的元素放在序列的起始位置,直到全部待排序的数据元素排完。

  当然,我们可以每一次排序时同时选出最小和最大的,分别放在序列的起始位置和终点位置,直到全部待排序的元素排列完,这样可以减少遍历次数。
排序过程(如图所示):
在这里插入图片描述

同样,用内外两层循环来控制整个过程:

  • 外循环:控制整个结束的条件,当begin>=end时就会结束。
  • 内循环:找到最大数和最小数的下标。

因此循环可写成:

while(begin < end)
{for(int i = begin + 1; i <= end; i++)//.......
}

完整代码如下:

void SelectSort(int* a, int n)//选择排序
{int begin = 0, end = n - 1;while (begin < end){int mini = begin, maxi = begin;for (int i = begin + 1; i <= end; i++){if (a[i] < a[mini])mini = i;if (a[i] > a[maxi])maxi = i;}Swap(&a[begin], &a[mini]);//交换了值,但是下标没变if (begin == maxi)maxi = mini;Swap(&a[end], &a[maxi]);begin++;end--;}
}

我们在两个交换函数中间加了一个判断条件:

if (begin == maxi)maxi = mini;

是为了可以避免以下这种情况的出现:
在这里插入图片描述
直接选择排序的特性总结

  1. 效率不算很好,实际中使用的较少
  2. 时间复杂度:O(N^2^)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

堆排序

  堆排序是指利用这种数据结构所设计的一种排序算法它是选择排序的一种。它通过堆来进行选择数据。
它分为了两个步骤:

  1. 建堆
    想要升序:建大堆
    想要降序:建小堆
  2. 利用堆删除思想来进行排序

下面我们来解释一下为什么升序是建立大堆:
我们给一个数组使其升序排列:

int arr[] = {20, 17, 4, 16, 5, 3};

我们脑子里第一想法应该是升序建小堆。
通过向下调整算法,建立小堆得:
在这里插入图片描述
  此时我们取第一个数出来即可得到最小值,但是当我们取出堆顶元素后,此时我们又要重新建一个小堆才能找到次小的数,但是这样时间复杂度变为了O(N2)。


但堆排其实是一个效率还不错的排序,因此我们可以逆向思维:

  1. 想要升序先建立大堆,然后将堆顶元素最后一个元素交换
  2. 然后最后一个值(也就是最大的值)不看做堆里面向下调整即可选出次大的数
  3. 重复以上步骤,最后形成的堆也就是排序好的数组。

具体过程如下图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

具体代码如下:

#include<stdio.h>
Swap(int* px, int* py)
{int tmp = *px;*px = *py;*py = tmp;
}void AdjustDown(HPDataType* a, int n, int parent)//向下调整建堆
{int child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child])//建大堆{child++;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;//更新父亲节点child = parent * 2 + 1;}elsebreak;}
}
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--;//再--}
}int main()
{int arr[] = { 20, 17, 4, 16, 5, 3 };int n = sizeof(arr) / sizeof(int);HeapSort(arr, n);for (int i = 0; i < n; i++){printf("%d ", arr[i]);}return 0;
}

堆排序特性总结:

  1. 堆排序使用堆来选数,效率比直接选择高。
  2. 时间复杂度:O(NlogN)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

感谢大家观看,如果大家喜欢,希望大家一键三连支持一下,如有表述不正确,也欢迎大家批评指正。
请添加图片描述


http://www.ppmy.cn/news/1536433.html

相关文章

【算法篇】回溯算法类(2)(笔记)

目录 一、LeetCode 题目 1. 子集II 2. 递增子序列 3. 全排列 4. 全排列 II 5. 重新安排行程 6. N皇后 7. 解数独 二、题目思路整理 一、LeetCode 题目 1. 子集II https://leetcode.cn/problems/subsets-ii/description/https://leetcode.cn/problems/subsets-ii/des…

erlang学习:Linux命令学习9

sed命令介绍 sed全称是&#xff1a;Stream EDitor&#xff08;流编辑器&#xff09; Linux sed 命令是利用脚本来处理文本文件&#xff0c;sed 可依照脚本的指令来处理、编辑文本文件。Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等 sed 的运行…

Qt QWidget控件

目录 一、概述 二、Qwidget常用属性及函数介绍 2.1 enable 2.2 geometry 2.3 windowTitle 2.4 windowIcon 2.5 cursor 2.6 font 设置字体样式 2.7 toolTip 2.8 focusPolicy焦点策略 2.9 styleSheet 一、概述 widget翻译而来就是小控件&#xff0c;小部件。…

linux文件编程_文件

1. 文件编程概述 之前在windows中对文件的操作是&#xff1a;打开文档—>编辑文档—>保存文档—>关闭文档 我们的Linux文件编程主要是利用代码对文件进行操作&#xff1a;文件创建、打开、编辑等自动化执行等 在Linux我们要使用编程调用api函数的方式进行文档的编辑…

Python获取json返回的字符串获取方法大全

1、使用 json.loads() 解析JSON字符串 import jsonjson_string {"name": "Alice", "age": 25, "city": "Beijing"} data json.loads(json_string)# 获取字符串值 name data[name] print("Name:", name) # 输…

✨机器学习笔记(六)—— ReLU、多分类问题、Softmax、Adam、反向传播

Course2-Week2: https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Advanced%20Learning%20Algorithms/week2机器学习笔记&#xff08;六&#xff09; 1️⃣ReLU&#xff08;Rectified Linear Unit&#xff09;2️⃣多分类问题3️⃣Softmax4️⃣Adam5…

如何实现 C/C++ 与 Python 的通信?

在现代编程中&#xff0c;C/C与Python的通信已经成为一种趋势&#xff0c;尤其是在需要高性能和灵活性的场景中。本文将深入探讨如何实现这两者之间的互通&#xff0c;包括基础和高级方法&#xff0c;帮助大家在混合编程中游刃有余。 C/C 调用 Python&#xff08;基础篇&#…

JAVA就业笔记3——第一阶段(3)

课程须知 A类知识&#xff1a;工作和面试常用&#xff0c;代码必须要手敲&#xff0c;需要掌握。 B类知识&#xff1a;面试会问道&#xff0c;工作不常用&#xff0c;代码不需要手敲&#xff0c;理解能正确表达即可。 C类知识&#xff1a;工作和面试不常用&#xff0c;代码不…