元旦特辑:Note6---选择排序


目录

前言❌

1. 基本思想⚠️

2. 直接选择排序🟢

2.1 思路分析✳️

2.2 代码实现❎

2.2.1 sort.h

2.2.2 sort.c

2.2.3 test.c

2.3 问题解决❇️

2.3.1 sort.c修改

2.4 特性总结✅

3. 堆排序🔵

3.1 代码实现🏧

3.2 特性总结🛜

4. 选择排序和插入排序性能对比🅿️

后语⭕️


前言❌

Hey young fella! Welcome to my channel!  前面一篇博客,我们学习了插入排序的2种实现方法。今天也是类似的,今天我们将一起学习选择排序的2种实现:直接选择排序+堆排序。


1. 基本思想⚠️

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置直到全部待排序的数据元素排完

2. 直接选择排序🟢

2.1 思路分析✳️

目标:实现升序

思路:暴力选取

把数据遍历一遍,依次将最大(小)的,次大(小)的,次次大(小)的放到对应的前三位(每次选取都要遍历一遍)然后重复上述步骤,直到最后就剩下1个数据


当然,我们也可以优化一下:
第一次遍历选出最大的和最小的放到头和尾的位置
第二次遍历选出次大的和次小的放到头+1和尾-1的位置

......

2.2 代码实现❎

2.2.1 sort.h

#pragma once
#include<stdio.h>
#include<stdlib.h>//打印
void PrintArray(int* a, int n);
//直接插入排序
void SelectSort(int* a, int n);

2.2.2 sort.c

#include"sort.h"
//打印
void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++)printf("%d ", a[i]);printf("\n");
}//交换
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}//直接插入排序
void SelectSort(int* a, int n)
{int begin = 0, end = n - 1,i;while (begin < end){int min = begin, max = begin;//一次排2个min和maxfor (i = begin + 1; i <=end; i++){if (a[i] < a[min])min = i;if (a[i] > a[max])max = i;}Swap(&a[begin], &a[min]);Swap(&a[end], &a[max]);begin++;end--;}
}

2.2.3 test.c

#include"sort.h"
//直接插入排序
void testSelectSort()
{int a[] = { 3,2,6,8,9,7,5,10,1,4 };int n = sizeof(a) / sizeof(int);SelectSort(a, n);PrintArray(a, n);
}
int main()
{testSelectSort();return 0;
}


2.3 问题解决❇️

我们发现,排序结果怎么有点不对呢?5,6的顺序怎么反了?

通过调试,我们发现最后一次排序的时候,交换那里出现了问题:max和begin位置重合了
min和begin交换完之后,排序是正确的;但是,end和max又交换了一次,导致顺序出错

所以,我们需要判断一下max和begin是否重合,重合了就不交换max和end;没重合就交换

2.3.1 sort.c修改

//交换
void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}//直接插入排序
void SelectSort(int* a, int n)
{int begin = 0, end = n - 1,i;while (begin < end){int min = begin, max = begin;//一次排2个min和maxfor (i = begin + 1; i <=end; i++){if (a[i] < a[min])min = i;if (a[i] > a[max])max = i;}Swap(&a[begin], &a[min]);//判断max和begin位置是否重合if (begin != max)Swap(&a[end], &a[max]);begin++;end--;}
}


2.4 特性总结✅

1. 直接选择排序思考非常好理解,但是效率不是很好(后面会性能对比)。实际中很少使用

2. 时间复杂度:O(N^2)

最好的情况下也是O(N^2):接近有序or有序
但是,我们不知道有序还是无序,还是需要遍历并且选出max和min交换--->O(N^2)

3. 空间复杂度:O(1)

4. 稳定性:不稳定

3. 堆排序🔵

之前的博客我们详细介绍过了堆排序的实现,这里就不再详述了,直接上代码。需要详述的小伙伴可以点击下方链接🔗:

Note3---初阶二叉树~~-CSDN博客文章浏览阅读1.1k次,点赞59次,收藏51次。这篇博客,我们一起来了解并学习数据结构中的初阶的二叉树的概念和性质;以及堆和堆堆应用二叉树的知识点和内容比较多,友友们一定要有耐心看完(跳到自己需要的部分也是OK的)。https://blog.csdn.net/2301_79184587/article/details/135033457

3.1 代码实现🏧

3.1.1 sort.h

//堆排序
void HeapSort(int* a, int n);

3.1.2 sort.c

//向下调整
void AdjustDown(int* a, int size, int parent)
{int child = parent * 2 + 1;while (child < size){if (a[child + 1] > a[child] && child + 1 < size)child++;if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 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--;}
}

3.1.3 test.c

//堆排序
void testHeapSort()
{int a[] = { 3,2,6,8,9,7,5,10,1,4 };int n = sizeof(a) / sizeof(int);HeapSort(a, n);PrintArray(a, n);
}
int main()
{testHeapSort();return 0;
}


3.2 特性总结🛜

1. 堆排序使用堆来选数,效率就高了很多。

2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(1)

4. 稳定性:不稳定

4. 选择排序和插入排序性能对比🅿️

// 测试排序的性能对比
void TestOP()
{srand(time(0));const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){a1[i] = rand()+i;a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];}int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin3 = clock();SelectSort(a3, N);int end3 = clock();int begin4 = clock();HeapSort(a4, N);int end4 = clock();int begin5 = clock();//QuickSort(a5, 0, N - 1);int end5 = clock();int begin6 = clock();//MergeSort(a6, N);int end6 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);
}
int main()
{TestOP();return 0;
}


我们发现,10万数据的时候,堆排序和希尔排序相差不大;100万个数据时,希尔排序的时间复杂度远超于堆排序的时间复杂度

后语⭕️

今天,我们学习了选择排序的实现和性能对比以及他们的特性总结。希望小伙伴们自己也可以练习一下,加强记忆和理解。

下一篇博客,我们将一起学习交换排序的相关知识点!请大家多多期待🙏

本次的分享到这里就结束了!!!

PS:小江目前只是个新手小白。欢迎大家在评论区讨论哦!有问题也可以讨论的!期待大家的互动!!!

公主/王子殿下,请给我点赞👍+收藏⭐️+关注➕(这对我真的很重要!!!


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

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

相关文章

什么是检索增强生成?

检索增强生成&#xff08;Retrieval Augmented Generation&#xff0c;RAG&#xff09;是指对大型语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;输出进行优化&#xff0c;使其能够在生成响应之前引用训练数据来源之外的权威知识库。LLM 用海量数据进行…

【开源】基于Vue+SpringBoot的就医保险管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 科室档案模块2.2 医生档案模块2.3 预约挂号模块2.4 我的挂号模块 三、系统展示四、核心代码4.1 用户查询全部医生4.2 新增医生4.3 查询科室4.4 新增号源4.5 预约号源 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVue…

安全配置审计概念、应用场景、常用基线及扫描工具

软件安装完成后都会有默认的配置&#xff0c;但默认配置仅保证了服务正常运行&#xff0c;却很少考虑到安全防护问题&#xff0c;攻击者往往利用这些默认配置产生的脆弱点发起攻击。虽然安全人员已经意识到正确配置软件的重要性&#xff0c;但面对复杂的业务系统和网络结构、网…

网际协议IPv4

基本介绍 网际协议IP是TCP/IP体系中两个重要的协议之一。IPv4虽有最终被IPv6取代的趋势&#xff0c;但它仍是当前使用的最重要的因特网协议。 与IP配套使用的还有3个协议&#xff1a; 地址解析协议ARP(Address Resolution Protocol)因特网控制报文协议ICMP(Internet Control …

MFC - 给系统菜单(About Dialog)发消息

文章目录 MFC - 给系统菜单(About Dialog)发消息概述笔记resource.h菜单的建立菜单项的处理MSDN上关于系统菜单项值的说法END MFC - 给系统菜单(About Dialog)发消息 概述 做了一个对话框程序, 在系统菜单(在程序上面的标题栏右击)中有"关于"的菜单. 这个是程序框架…

pytorch01:概念、张量操作、线性回归与逻辑回归

目录 一、pytorch介绍1.1pytorch简介1.2发展历史1.3pytorch优点 二、张量简介与创建2.1什么是张量&#xff1f;2.2Tensor与Variable2.3张量的创建2.3.1 直接创建torch.tensor()2.3.2 从numpy创建tensor 2.4根据数值创建2.4.1 torch.zeros()2.4.2 torch.zeros_like()2.4.3 torch…

C#中使用is关键字检查对象是否与给定类型兼容

目录 一、定义 二、示例 三、生成 在程序的开发过程中经常会使用类型转换&#xff0c;如果类型转换不成功则会出现异常&#xff0c;从抛出异常到捕获并处理异常&#xff0c;无形中增加了系统的开销&#xff0c;而且太过频繁地处理异常还会严重地影响系统的稳定性。is关键字可…

Vue3-29-路由-编程式导航的基本使用

补充一个知识点 路由配置中的 name 属性 &#xff1a; 可以给你的 路由 指定 name属性&#xff0c;称之为 命名路由。 这个 name 属性 在 编程式导航 传参时有重要的作用。 命名路由的写法如下 &#xff1a; 像指定 path 一样&#xff0c;直接指定一个 name 属性即可。{path:/d…

如何使用python脚本生成redis格式的数据包

用python脚本生成redis格式的数据包 &#xff08;1&#xff09;使用下述网站下载开源的生成gopher协议规则的包的工具 https://github.com/firebroo/sec_tools/tree/master/redis-over-gopher &#xff08;2&#xff09;首先要修改redis.cmd中的内容 flushall config set di…

考研长难句 DAY14分享

长难句分享第十四天解析 【词汇】&#xff1a; • modest [ˈmɑːdɪst] adj. &#xff08;建筑&#xff09;不大的 • efficient [ɪˈfɪʃnt] adj. &#xff08;因省时、省力或省钱等而&#xff09;收效大的 • square [skwer] adj. 平方的 • spread [spred] v. 摊开&…

QT 利用开源7z 实现解压各种压缩包,包括进度条和文件名的显示(zip,7z,rar,iso等50多种格式)

想做一个winRAR一样的解压软件吗?很简单,利用开源的7z库就能实现。我看网上其他人说的方法不敢苟同,误人子弟。以前自己在项目中使用过7z,这次又有需要,就想记录下来。如果你研究过如何用7z的话,一定知道7z的每一个GUID都代表了一种格式,50多种GUID也就有50多个格式,最…

【进收藏夹吃灰系列】Python学习指南

文章目录 [toc]Python基础字符串判断语句循环语句异常文件读写迭代器生成器闭包线程 个人主页&#xff1a;丷从心 系列专栏&#xff1a;进收藏夹吃灰系列 Python基础 字符串 【Python基础】字符串 判断语句 【Python基础】判断语句 循环语句 【Python基础】循环语句 异常 …