【数据结构】排序(3)—堆排序归并排序

news2025/2/23 21:01:34

                                 

目录

     一. 堆排序

      基本思想  

      代码实现

   向上调整算法

   向下调整算法

      时间和空间复杂度

      稳定性

    二. 归并排序

      基本思想

      代码实现

      时间和空间复杂度

      稳定性



     一. 堆排序

                 堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似            完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)            它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序

          注意:排升序要建大堆,排降序建小堆  

               大顶堆:每个节点的值都大于或等于其子节点的值

               小顶堆:每个节点的值都小于或等于其子节点的值;

          提示:此次以排升序建大堆为例

           基本思想  

               将待排序的序列构造成一个大根堆。此时,整个序列的最大值就是堆顶的根结点。将它         移走(就是将其与堆数组的末尾元素交换,此时末尾元素就是最大值),然后把剩余的n-1个         序列重新构造成一个堆,就会得到n个元素中的次大值。如此反复执行,便能得到一个有序列。

          算法步骤:          

             ① 创建一个堆 Heap[0……n-1];

             ② 把堆首(最大值)和堆尾互换;

             ③ 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应置;

             ④ 重复步骤 2,直到堆的尺寸为 1。

         图示:

    代码实现

         向上调整算法

            思想方法:从第一个结点开始(视为左孩子或右孩子),先找该结点的父结点,在与父节点比较,大的与父结点交换,成为新的父节点;这样依次往下,直到最后一个节点。

         知道孩子结点找父节点:左孩子、 右孩子:parent = (child - 1) / 2 

        图解:

                 

               

void AdjustUp(int* a, int child)
{
	int parent = (child - 1) / 2; //找父节点
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]); //与父结点交换
			child = parent; //往后走到下一个结点
			parent = (parent - 1) / 2;
		}
		else
			break;
	}
}

     向下调整算法

            思想方法:从最后一个元素开始(视为父节点),先找其孩子节点(左孩子或右孩子),与其孩      子结点比较,与大的一方(左孩子或右孩子)交换;依次往上,直到第一个结点。

           知道父节点找孩子:child = parent * 2 + 1

        图解:

          

          

void AdjustDown(int* 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;
		}
		else
			break;
	}
}

      

  通过向上调整或向下调整算法建堆后,进行堆排序,此程序为向下调整建堆。

   图解:

               

  

void AdjustDown(int* 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;
		}
		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--;
	}
}

   时间和空间复杂度

            时间复杂度:O(nlogn)

            空间复杂度:O(1)

   稳定性

            堆排序:不稳定排序
 

  二. 归并排序

       基本思想

             将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段            间有序。若将两个有序表合并成一个有序表,称为二路归并

      算法步骤:         

      ① 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;

      ② 设定两个指针,最初位置分别为两个已经排序序列的起始位置

      ③ 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;

      ④ 重复步骤 3 直到某一指针达到序列尾;

      ⑤ 将另一序列剩下的所有元素直接复制到合并序列尾

        图示

       

       代码实现

                   

void _MergeSort(int* a, int* tmp, int left, int right)
{
	if (left >= right)
		return;
	int mid = (left + right) / 2;
	_MergeSort(a, tmp, left, mid); //递归左边
	_MergeSort(a, tmp, mid+1, right); //递归右边
	// 将a数组元素归并到tmp数组,再拷贝回a数组
	int left1 = left, right1 = mid;
	int left2 = mid + 1, right2 = right;
	int index = left;
	while (left1 <= right1 && left2 <= right2)
	{
		if (a[left1] <= a[left2])
			tmp[index++] = a[left1++];
		else
			tmp[index++] = a[left2++];
	}
	while(left1 <= right1)   //左>右,将左区间剩余元素拷贝到tmp数组
		tmp[index++] = a[left1++];
	while(left2 <= right2)   //左<右,将右区间剩余元素拷贝到tmp数组
		tmp[index++] = a[left2++];
	//拷贝回原数组
	memcpy(a + left, tmp + left, sizeof(int) * (right - left + 1));
}

//归并排序
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	_MergeSort(a, tmp, 0, n - 1);
	free(tmp);
}

       

时间和空间复杂度

         时间复杂度:O(nlogn)

         空间复杂度:O(n)   归并排序时需要和待排序记录个数相等的存储空间

稳定性

      归并排序:稳定排序

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

lambda表达式在实际开发中的使用

作为写代码已经两年的程序员了&#xff0c;lambda已经是再熟悉不过了。其实在众多的编程语言中&#xff0c;python javascript java中都有lambda的影子。包括比较新的编程语言golang&#xff0c;到最后发现其实各种语言的语法和特性都是相互抄袭的&#xff0c;所以在接触新技术…

drone和gogs安装

背景介绍 什么是 Drone&#xff1f; Drone 是一个面向忙碌的开发团队的自助持续集成和持续交付平台。官网地址&#xff1a; https://www.drone.io/同时&#xff0c;Drone 是使用 Golang 语言进行编写。所有的编译、测试的流程都在 Docker 容器中执行。Drone 通过使用简单的 YA…

直线导轨坏了可以维修吗?

直线导轨是工业自动化设备中常用的零部件&#xff0c;其性能和使用寿命对设备的稳定运行和产能有着直接的影响&#xff0c;在生产中&#xff0c;由于各种原因&#xff0c;直线导轨会出现各种问题&#xff0c;那么&#xff0c;直线导轨的维修方法究竟是怎样的呢&#xff1f;我们…

竞赛选题 深度学习 opencv python 实现中国交通标志识别_1

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 &#x1f525; 优质…

【安鸾靶场】实战渗透

文章目录 前言一、租房网 (150分)二、企业网站 (300分)三、SQL注入进阶 (550分) 前言 最近看到安鸾的靶场有些比较有意思就打了一下午&#xff0c;有一定难度。 一、租房网 (150分) http://106.15.50.112:8031/ 刚打开burp就报了thinkphp的代码执行 直接getshell flag&a…

邮件注册(一)验证码发送

通过邮箱实现注册&#xff0c;用户请求验证码完成注册操作。 导入依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><g…

PACS系统 PACS系统源码一种用于存储、管理和传输医学影像数据的系统

医用软件中的影像归档与传输系统软件&#xff08;Picture Archiving and Communication System&#xff0c;简称PACS&#xff09;是一种用于存储、管理和传输医学影像数据的系统。其主要功能包括&#xff1a; 影像存储&#xff1a;PACS可以将医学影像数据以数字化的形式存储在服…

C语言之自定义类型_结构体篇(2)

目录 结构体传参 结构体实现位段&#xff08;位段的填充&可移植性&#xff09; 什么是位段 位段的大小计算 位段的内存分配 位段的跨平台问题 位段的应用 今天接着我们继续自定义类型结构体。&#x1f642;&#x1f642; 结构体传参 在我们初阶结构体我们学习过结…

Spring web security

儅使用spring的web security時&#xff0c;默認會轉向自帶的spring security example page。而不會轉向error page。 TODO: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> &l…

城市、机场、服务区等场景下的智慧公厕建设诀窍揭秘

在如今繁忙的生活节奏中&#xff0c;人们对于公共服务设施的需求越来越高。而智慧公厕正是把传统公共厕所转变为智慧化的场所&#xff0c;得到了极大的欢迎。目前&#xff0c;各行各业均对公共厕所进行信息化、智慧化、数字化的升级&#xff0c;尤其是在机场、服务区和城市等场…

基于SSM的电子相册系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

6.MySql连接SqlYog

MySql连接SqlYog SqlYog和navicat均是数据可视化工具&#xff0c;熟悉其一即可 SqlYog下载安装 连接&#xff0c;密码和端口号一定要正确&#xff01;&#xff01;&#xff01; 2.保存到数据库 创建数据库&表 创建数据库 创建成功 创建表 点击保存 查看表数据的…

基于javaweb的智慧社区设计与实现

目录 前言 一、技术栈 二、系统功能介绍 客户信息管理 客户信息管理 社区信息管理 车位租买支付 前台车位信息 车位预定提交 问卷调查管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理…

【Spring篇】Bean的三种配置和实例化方法

&#x1f38a;专栏【Spring】 &#x1f354;喜欢的诗句&#xff1a;天行健&#xff0c;君子以自强不息。 &#x1f386;音乐分享【如愿】 &#x1f384;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f33a;bean基本配置&#x1f33a;bean别名配置&#x1f33a…

RStudion | 基础使用教程(初学者详细) | 基本设置 | 快捷操作 | 脚本运行 | 画图

RStudion | 基础使用教程 | 基本设置 | 快捷操作 | 脚本运行 | 画图 一、RStudio界面布局二、RStudio基础设置2.1 general | 常规设置2.2 Code | 代码2.3 Console | 控制台2.4 Appearance | 外观2.5 Pane Layout | 排版布局2.6 Packages | R包2.7 R Markdown2.8 Python2.9 Swea…

反爬虫机制与反爬虫技术(一)

反爬虫机制与反爬虫技术一 1、网络爬虫的法律与道德问题2、反爬虫机制与反爬虫技术2.1、User-Agent伪装2.2、代理IP2.3、请求频率控制2.4、动态页面处理2.5、验证码识别3、反爬虫案例:豆瓣电影Top250爬取3.1、爬取目标3.2、库(模块)简介3.3、翻页分析3.4、发送请求3.5、提取…

【Python+requests+unittest+excel】实现接口自动化测试框架

一、框架结构&#xff1a; 工程目录 二、Case文件设计 三、基础包 base3.1 封装get/post请求&#xff08;runmethon.py&#xff09; 1 import requests2 import json3 class RunMethod:4 def post_main(self,url,data,headerNone):5 res None6 if header …

Javascript文件上传

什么是文件上传 文件上传包含两部分&#xff0c; 一部分是选择文件&#xff0c;包含所有相关的界面交互。一部分是网络传输&#xff0c;通过一个网络请求&#xff0c;将文件的数据携带过去&#xff0c;传递到服务器中&#xff0c;剩下的&#xff0c;在服务器中如何存储&#xf…

TL-ER3220G端口映射设置

1、打开IE浏览器或其它浏览器&#xff0c;在地址栏输入192.168.1.1登录路由器的Web管理界面&#xff1b; 2、打开后弹出密码输入框&#xff0c;输入路由器的用户名和密码&#xff0c;出厂默认值为admin/admin&#xff0c;成功登录后将看到路由器的系统状态信息&#xff1b; 3、…

2023 年 Web 安全最详细学习路线指南,从入门到入职(含书籍、工具包)【建议收藏】

第一个方向&#xff1a;安全研发 你可以把网络安全理解成电商行业、教育行业等其他行业一样&#xff0c;每个行业都有自己的软件研发&#xff0c;网络安全作为一个行业也不例外&#xff0c;不同的是这个行业的研发就是开发与网络安全业务相关的软件。 既然如此&#xff0c;那其…