元旦特辑: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和max
		for (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和max
		for (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;
		}
		else
			break;
	}
}

//堆排序
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:小江目前只是个新手小白。欢迎大家在评论区讨论哦!有问题也可以讨论的!期待大家的互动!!!

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


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Centos安装Kafka(KRaft模式)

1. KRaft引入 Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;它可以处理消费者在网站中的所有动作流数据。其核心组件包含Producer、Broker、Consumer&#xff0c;以及依赖的Zookeeper集群。其中Zookeeper集群是Kafka用来负责集群元数据的管理、控制器的选举等。 由…

c++ 简单实用万能异常捕获

多层捕获异常&#xff0c;逐渐严格。并打印出错信息和位置&#xff1a;哪个文件&#xff0c;哪个函数&#xff0c;具体哪一行代码。 #include <stdexcept> // 包含标准异常类的头文件try {int a 2 / 0; }catch (const std::runtime_error& e) {// 捕获 std::runt…

浅谈 JSON 对象和 FormData 相互转换,打通前端与后端的通信血脉

前言 大家都知道&#xff0c;前端在和后台进行交互联调时&#xff0c;肯定避免不了要传递参数&#xff0c;一般情况下&#xff0c;params 在 get 请求中使用&#xff0c;而 post 请求下&#xff0c;我们有两种常见的传参方式&#xff1a; JSON 对象格式和 formData 格式&#x…

AtCoder Beginner Contest 334 G

G.Christmas Color Grid 2&#xff08;枚举&#xff0c;Tarjan&#xff09; 题意&#xff1a; 本题与问题 E E E类似。有一个 H H H行和 W W W列的网格&#xff0c;每个单元格都被涂成红色或绿色。用 ( i , j ) (i,j) (i,j)表示从上到下第 i i i行、从左到右第 j j j列的单元…

UIToolKit使用心得

起因 因为那个uitoolkit自己写了一套graphView&#xff0c;所以想着来用用但是用完之后发现也不过如此 怎么构建自己的组件 我在继承Node之后想修改node的样式该怎么办呢是这样的。先用pick点击默认的node节点元素- 在pick默认创建的node节点之后&#xff0c;可以把它的uxml…

跨境电商迎来综合竞争力比拼时代 五大趋势解读跨境2024

过去几年&#xff0c;跨境电商成为外贸出口增长的一大亮点&#xff0c;随着年底国务院办公厅《关于加快内外贸一体化发展的若干措施》的发布&#xff0c;跨境电商在促进经济发展、助力内外贸一体化发展方面的价值更加凸显。 这是跨境电商变化最快的时代&#xff0c;也是跨境电…

CCSK认证:开启云安全领域的黄金大门

&#x1f31f;你是否对云安全领域充满热情&#xff1f;是否希望提升自己在云安全领域的专业性和竞争力&#xff1f;CCSK认证是你的不二之选&#xff01; &#x1f525;CCSK简介&#xff1a; CCSK是国际云安全联盟&#xff08;Cloud Security Alliance&#xff0c;CSA&#xff…

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

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

【已解决】 ubuntu apt-get update连不上dl.google.com

在终端使用apt-get update时&#xff0c;连接dl.google.com超时&#xff0c;一直卡在0%&#xff0c;原因是当前ip无法ping到google&#xff08;墙&#xff09;。 解决方法&#xff1a; dl.google.com国内可用IP 选一个&#xff0c;然后按以下命令操作&#xff1a; cd ~ vim …

RSA加密解密——用shell加密java解密

功能描述 使用shell opensll对明文进行RSA加密&#xff0c;将密文用java的RSA工具对密文解密。这应该是全网第一个同时用到shell和java的RSA加密解密教程。中间有很多坑&#xff0c;都踩过了&#xff0c;可以放心使用代码。 正确的实现流程 shell端 首先生成公钥私钥 &…

飞企互联-FE企业运营管理平台 登录绕过漏洞复现

0x01 产品简介 飞企互联-FE企业运营管理平台是一个基于云计算、智能化、大数据、物联网、移动互联网等技术支撑的云工作台。这个平台可以连接人、链接端、联通内外&#xff0c;支持企业B2B、C2B与O2O等核心需求&#xff0c;为不同行业客户的互联网转型提供支持。 0x02 漏洞概…

大数据Doris(四十五):物化视图选择最优

文章目录 物化视图选择最优 物化视图选择最优 下面详细解释一下第一步最优物化视图是被如何选择出来的。 这里分为两个步骤: 对候选集合进行一个过滤。只要是查询的结果能从物化视图数据计算(取部分行,部分列,或部分行列的聚合)出都可以留在候选集中,过滤完成后候选集合…

图像中的傅里叶变换及低通与高通滤波

傅里叶变换 高频&#xff1a;在图像中变化剧烈的灰度分量&#xff0c;如边界。 低频&#xff1a;在图像中变化缓慢的灰度分量。 OpenCV中函数为cv2.dft()和cv2.idft()&#xff0c;输入图像要先转换成np.float32格式。得到的结果频率为0的部分会在左上角&#xff0c;为方便处理…

【yolofastest上手】

一、前言 yolofastest网上资料比较少&#xff0c;也没有视频教学&#xff0c;所以想要使用参考了很多资料&#xff0c;只能说各资料都不尽全&#xff0c;让刚接触的小白无从下手。 参考资料: github地址 yolo-fastest 快速上手 修改参数遇到的问题 能在ARM-CPU上实时识别图像的…

MES系统中的电子看板:真正实现数字化车间可视化

在生产制造过程中&#xff0c;看板管理扮演着至关重要的角色。通过看板&#xff0c;我们能够实时了解生产情况、物料需求、质量预警等信息&#xff0c;从而更好地控制生产过程。作为万界星空科技MES管理系统中的一个基本模块&#xff0c;看板管理为企业的生产管理提供了有力支持…

【Pytorch】学习记录分享10——PyTorchTextCNN用于文本分类处理

【Pytorch】学习记录分享10——PyTorchTextCNN用于文本分类处理 1. TextCNN用于文本分类2. 代码实现 1. TextCNN用于文本分类 具体流程&#xff1a; 2. 代码实现 # coding: UTF-8 import torch import torch.nn as nn import torch.nn.functional as F import numpy as np…

嵌入式科普(8)ESP-IDF newlib相关介绍和对比分析

一、目的/概述 二、资料来源 三、ESP-IDF简介 3.1 ESP-IDF FreeRTOS 3.2 ESP-IDF heap_caps 3.3 ESP-IDF newlib 四、对比 嵌入式科普(8)ESP-IDF newlib相关介绍和对比分析 一、目的/概述 1、在我的嵌入式科普(6)你听说过FreeRTOS heap6吗&#xff1f;…

图文证明 牛顿-莱布尼茨公式

牛顿-莱布尼茨公式 牛顿-莱布尼茨公式是微积分中的基本定理之一&#xff0c;它描述了函数的导数和不定积分之间的关系。 该公式通常用来计算定积分。设函数f(x)在区间[a, b]上连续&#xff0c;且F(x)是f(x)在该区间上的一个原函数 即F’(x) f(x)。则牛顿-莱布尼茨公式表示为&…

一篇五分生信临床模型预测文章代码复现——Figure 10.机制及肿瘤免疫浸润(九)——ssGSEA——倒数第三节

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

143.【Nginx-02】

Nginx-02 (五)、Nginx负载均衡1.负载均衡概述2.负载均衡的原理及处理流程(1).负载均衡的作用 3.负载均衡常用的处理方式(1).用户手动选择(2).DNS轮询方式(3).四/七层负载均衡(4).Nginx七层负载均衡指令 ⭐(5).Nginx七层负载均衡的实现流程 ⭐ 4.负载均衡状态(1).down (停用)(2)…