堆排序,快速排序

news2024/9/23 7:23:40

目录

1.堆排序

2.快速排序

1.hoare版本

2.挖坑法

3.前后指针法

注意点


1.堆排序

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
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[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
		}
		else
		{
			break;
		}
		parent = child;
		child = parent * 2 + 1;
	}
}
void heapsort(int* a, int n)
{

	for (int i = (n - 1 -1) / 2; i >= 0; i--)
	{
		adjustdown(a, n, i);
	}
	for (int i = n-1; i > 0; i--)
	{
		Swap(&a[0], &a[i]);
		adjustdown(a, i, 0);
	}
}


void printarr(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}
void heaptest()
{
	int arr[] = { 4,7,1,9,3,6,5,8,3,2,0 };
	printarr(arr, sizeof(arr)/sizeof(int));
	heapsort(arr, sizeof(arr)/sizeof(int));
	printarr(arr, sizeof(arr)/sizeof(int));
}

        我们先用向下调整算法建堆。

        使用向下调整算法建堆的前提是,该节点的子树都是堆。那么我们从最后一个节点的父节点开始向下调整算法,这样因为两个子树都是叶子节点,因此满足条件。从后往前,一直遍历到父节点为根节点,那么就建好堆了。

        然后只需要不断将第一个和最后一个节点的值交换,把最大值放到末尾,然后不断从根节点向下建堆,即可每次都挑选出最大值,我们依次把他们放到末尾即可。 

2.快速排序

主逻辑,递归

1.hoare版本

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void printarr(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

int partsort(int* a, int left, int right)
{
	int keyi = left;
	while (left < right)
	{
		while (left < right &&a[left] <= a[keyi])
		{
			left++;
		}
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
		Swap(&a[left], &a[right]);//如果是因为left==right结束,交换值也并不影响结果
	}
	Swap(&a[keyi], &a[left]);
	return left;
}

void quicksort(int* a, int begin, int end)
{
	if (begin >= end)return;
	
	int keyi = partsort(a, begin, end);

	quicksort(a, begin, keyi-1);
	quicksort(a, keyi + 1, end);
}

void quicktest()
{
	int arr[] = { 4,7,1,9,3,6,5,8,3,2,0 };
	printarr(arr, sizeof(arr) / sizeof(int));
	quicksort(arr,0, sizeof(arr) / sizeof(int)-1);
	printarr(arr, sizeof(arr) / sizeof(int));
}

我们以左边第一个下标为keyi,因此先从右边开始找

1.先从右往左找到比a【keyi】小的值

2.再从左往右找到比a【keyi】大的值

交换这两个值。

3.不断重复以上过程直到相遇left == right

4.交换a【keyi】和a【left】

注意点

        1.我们在移动下标时,判断条件是a[left] <= a[keyi]left++

                                                        a[right] >= a[keyi] right--

        这是为了防止遇到与a【keyi】相等的值的时候,陷入死循环

        2.我们在寻找下标的小循环中也加入left<right的判断是因为防止极端情况。

        如果不判断就会越界,而且如果是因为left==right结束,交换值也并不影响结果

        同时因为这个极端情况原因,我们遍历是从最左边keyi处开始遍历,不然会忽略掉这种情况。也是注意点1中判断条件需要加=的原因

 

 3.我们再来谈谈为什么从一边开始调整要从另一边开始找起

以上面的情况为例子,

因为这样可以保证他们相遇时候所处在的值一定比a【keyi】小

情况1、left不动,right先移动与left相遇,此时a【keyi】还在原位

情况2.  right移动后找到小值,left移动后与right相遇,此时该位置的值比a【keyi】小

情况3,left与right先各自移动并且交换一次,然后right再移动和left相遇,此时因为已经交换过,a【left】处储存的值小于a【keyi】因此也符合

综上

2.挖坑法

 

int partsort(int* a, int left, int right)
{
	int key = a[left];
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			right--;
		}
		a[left] = a[right];
		while (left < right && a[left] <= key)
		{
			left++;
		}
		a[right] = a[left];
	}
	a[left] = key;
	return left;
	
}

 

 

 

 

 

把a【keyi】的位置先挖走,记录这个key值。

1.从右边往左找小,把这个值填入坑中,同时这个位置形成一个新的坑

2.从左边往右找大 把这个值填入坑中,同时这个位置形成一个新的坑

3.重复以上操作,直到left==right,然后把key值填入这个坑中,此时这个位置一定是坑,因为left和right永远有一个是坑

3.前后指针法

int partsort(int* a, int left, int right)
{
	int prev = left;
	int cur = left + 1;
	int keyi = left;
	while (cur <= right)
	{
		if (a[cur] < a[keyi] && ++prev != cur)//这里直接判断一下,相等就不交换,并且在判断条件 
                                              //的地方就更新prev
		{
			Swap(&a[prev], &a[cur]);
		}
		++cur;//cur就是一直往前走,直到结束,遇到相应位置才有操作,因此直接放到循环中
	}
	Swap(&a[keyi], &a[prev]);
	keyi = prev;
	return keyi;

}

cur一直向后找小于key的位置

如果a【cur】< key

++prev,然后交换a【prev】和a【cur】

如果cur所在位置的值都比key小,那么cur和prev拉不开差距.++prev后和cur交换就是自身交换

        如果遇到比key大的值,就会拉开差距,此时如果cur遇到比key小的值,这个值就会和一个比key大的值交换,因为prev和cur原本中间隔着的都是大于key的值,++prev后再交换就会是这样的结果

 

这样相当于把大的往右推,小的往左推

 

cur走出数组结束,key与a【prev】交换即可 

注意点

        以上三种方法只是实现形式不同,时间复杂度是完全相同的,并且主逻辑的代码不需要更改,就是一个递归,只需要把部分排序修改即可

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

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

相关文章

【Python基础】Python lambda(简洁与高效的匿名函数)

本文收录于 《Python编程入门》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程基础知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、lambda函数的基本概念三、lambda函数的应用实例3.1 在列表排序中使用lambda函数3.2 在map()函数中…

(批处理)设置延时+设置关机倒计时

使用方式&#xff1a;建立一个文本文件夹&#xff0c;将文件扩展名改为.bat&#xff0c;右键单击后编辑&#xff0c;将代码复制进去。 将文件保存 echo off echo 三秒后会出现一个提示自动关机ping -n 3 127.0.0.1 >nul rem 实现的功能是在这里停3秒再继续往下执行 rem 以…

OpenCore Legacy Patcher 2.0.0 发布,83 款不受支持的 Mac 机型将能运行最新的 macOS Sequoia

在不受支持的 Mac 上安装 macOS Sequoia (OpenCore Legacy Patcher v2.0.0) Install macOS on unsupported Macs 请访问原文链接&#xff1a;https://sysin.org/blog/install-macos-on-unsupported-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主…

【Linux】多路转接epoll

一、I/O多路转接 poll 1.1 poll函数接口 函数原型 函数参数 fds&#xff1a;是一个poll函数监听的结构列表&#xff0c;每一个元素中包含了三部分内容&#xff1a;文件描述符&#xff0c;监听的事件集合&#xff0c;返回的事件集合。nfds&#xff1a;表示的是fds数组的长度tim…

VUE + NODE 历史版本安装

以node 12.20.0为例子&#xff0c;想下载哪个版本&#xff0c;后面写哪个版本 https://registry.npmmirror.com/binary.html?pathnode/v12.20.0/ 安装国内镜像7.1.0 cnpm npm install -g cnpm7.1.0 -g --registryhttps://registry.npmmirror.com 安装vue脚手架4.5.15 cnpm …

【有啥问啥】深入浅出马尔可夫链蒙特卡罗(Markov Chain Monte Carlo, MCMC)算法

深入浅出马尔可夫链蒙特卡罗&#xff08;Markov Chain Monte Carlo, MCMC&#xff09;算法 0. 引言 Markov Chain Monte Carlo&#xff08;MCMC&#xff09;是一类用于从复杂分布中采样的强大算法&#xff0c;特别是在难以直接计算分布的情况下。它广泛应用于统计学、机器学习…

【linux基础】linux中的开发工具(4)--调试器gdb的使用

目录 前言一&#xff0c;背景二&#xff0c;gdb的使用1. 启动 gdb 调试器&#xff1a;2. 罗列代码信息3. 运行程序4. 有关断点的操作(1) 打断点(2) 查看断点(3) 删除断点(4) 在一次调试中&#xff0c;断点是递增的(5) 关闭断点(6) 开启断点(7) 逐过程调试&#xff0c;相当于 F1…

我与Linux的爱恋:进程|进程的查看与管理|创建进程

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;Linux的学习 ​ 文章目录 一、进程的概念1.什么是进程2.在这里插入代码片多进程管理3.描述进程-PCB 2.查看进程与管理进程1.使用指令查看进程2.通过系统调用函数查看pid3.杀进程4.ppid&…

如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?

优质博文&#xff1a;IT-BLOG-CN 问题 我在 macOS 中使用 vscode 版本 1.92.2&#xff0c;并安装了Java 扩展包v0.29.0。当我打开command click或right click->Go to definition一个没有源代码的类时&#xff0c;vscode 会使用 FernFlower 反编译器打开 .class 文件。但…

一步一步自制py脚本并且并且修改为exe可执行文件教学外附带SHA-1解密exe文件资源

第一步&#xff1a;安装 Python 下载 Python&#xff1a;访问 Python 官网 下载并安装最新版本的 Python。安装时选择添加到环境变量 PATH&#xff1a;在安装过程中&#xff0c;确保勾选“Add Python to PATH”选项。 第二步&#xff1a;编写 Python 脚本 创建一个新的 Pyth…

HTB-Base(strcmp函数绕过、sudo -l提权)

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天给大家讲解Base靶场&#xff0c;起点内容到此完结 渗透过程 信息搜集 服务器开放了22SSH服务 和 80HTTP服务 目录爆破 通过目录扫描出/login 和/asserts文件夹 发现/login 拥有目录遍历漏洞login.php.swp 是使用…

Mysql_使用简介

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

循环练习 案例

swich新特性 jdk12 穿透 逢七过 //含有七和被七整除舍去 public class test1 {public static void main(String[] args){for (int i 1; i <100 ; i) {if(i%70||i%107||i/107){continue;}System.out.println(i);}} } 求平方根 //输入大于2的整数&#xff0c;求平方根&…

AI基础 L22 Uncertainty over Time I 时间的不确定性

Time and Uncertainty 1 Time and Uncertainty States and Observations • discrete-time models: we view the world as a series of snapshots or time slices • the time interval ∆ between slices, we assume to be the same for every interval • Xt: denotes the se…

C++编译环境(IDE)推荐及安装

IDE是什么 嗨嗨嗨&#xff0c;我又来水博文了 今天来给大家推荐几款好用的IDE IDE是集成开发环境&#xff08;Integrated Development Environment&#xff09;的缩写&#xff0c;是一种软件应用程序&#xff0c;提供了用于软件开发的各种工具和功能&#xff0c;包括代码编辑…

windows C++ 并行编程-PPL 中的取消操作(一)

并行模式库 (PPL) 中取消操作的角色、如何取消并行工作以及如何确定取消并行工作的时间。 运行时使用异常处理实现取消操作。 请勿在代码中捕捉或处理这些异常。 此外&#xff0c;还建议你在任务的函数体中编写异常安全的代码。 例如&#xff0c;可以使用获取资源即初始化 (RA…

LidarView之定制版本号

介绍 LidarView软件需要关注2个版本号&#xff1a;1.Application版本号&#xff1b;2.安装包版本号 Application版本号 改变LV_VERSION_FULL可达到改变软件版本号的目的 SET(LV_VERSION_FULL "V1.3.0")标题栏版本号 关于对话框 安装包版本号 在Inno Setup Compi…

【退役之再次线上部署】Spring Boot + VUE + Nginx + MySQL

这篇博客写在凌晨 4 点 20 分&#xff0c;这个时候我刚线上部署完成 web 项目&#xff0c;自己写的全栈项目 这个点儿&#xff0c;也睡不着了&#xff0c;索性就写篇博客记录一下 一、踩坑实录 这个是 最重要的&#xff0c;所以写在前面 Nginx 配置文件 location location /a…

如何做系统架构?从动态系统思考的角度

在动态系统思考的背景下&#xff0c;系统架构不再只是一个静态的、结构化的设计&#xff0c;而是一个随着时间推移、基于不同要素互动产生涌现行为的动态过程。系统架构师的任务不仅仅是定义系统的形态和结构&#xff0c;更是通过剖析系统的互动网络、功能涌现和使用场景&#…

文章解读与仿真程序复现思路——电力系统自动化EI\CSCD\北大核心《计及抢修人员调度的配电网信息-物理协同恢复策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…