堆排序、归并排序、快速排序总结

《数据结构初阶》堆排序总结与思考 向上调整、向下调整、堆排序的详细解析 阅读详情

昨天刚把这三个排序算法复习了一遍,其中归并排序和快速排序特别的重要,一定要熟练并理解透彻!

以下排序的结果都默认为非递减

 

1、堆排序(默认大顶堆)

堆排序的思想:首先构建一个完全二叉树,从最大的非叶子结点,如果该结点小于孩子结点,则把该结点与最大的孩子结点交换,使该结点不断的往下沉到合适位置。然后又从第二大的非叶子结点开始,不断循环下去直到根节点,这时候便构造出了大顶堆,最后根结点就是堆中最大的节点。交换根结点(arc[1])与最后一个结点(arc[N--]),再使新的根节点不断往下沉到合适位置,并形成新的大顶堆,又让根结点(arc[1])与最后一个(arc[N--])交换...不断循环至整个数组有序。

 

看看具体的代码:

 

public void heapSort(int arc[]){
		int N =arc.length-1;
		for(int i=N/2;i>=1;i--){	       //从最大的非叶子结点开始,构造一个大顶堆		
			sink(arc,N,i);
		}
		while(N>=1){       
			each(arc,1,N--);              //交换啊arc[1]与arc[N--],注意是N--而不是N
			System.out.println(arc[N+1]); //输出根结点,即堆中最大的结点
			sink(arc,N,1);               //使新的根结点往下沉到合适的位置
		}
	}

	private void sink(int[] arc,int N,int i) {   //使结点沉到合适的位置
		
		int j;
		while(2*i<=N){
			j = 2*i;
			if(j<N&&arc[j]<arc[j+1]){         //j<N防止数据越界,选出两个子结点中的最小值
				j++;
			}
			if(arc[i]>arc[j]){           //如果父结点比两个子结点都大,则跳出循环
				break;
			}
			each(arc,i,j);               //交换父子结点
			i=j;
		}
		
		
	}

	private void each(int[] arc, int i, int j) {    //两个结点交换
		int t;

		t = arc[i];
		arc[i] = arc[j];
		arc[j] = t;		
	}


堆排序算法的几个特点:

 

1.时间复杂度为O(nlogn);

2.不稳定

3.适用于大量数据选出小于k(k>0)的元素

 

 

2、归并排序

归并排序思想:应用了分治思想,即不断的将大问题变小问题,通过解决小问题来解决整个大问题。

2.1自上而下的归并排序

自上而下归并排序思想:不断地将无序数组用递归方法划分为两个数组,直到数组变的很小时(如划分到每个数组只有1个元素时)再进行两两归并,最后使得整个数组有序。

 

看看具体的代码

 

       public void mergeSort(int arc[],int low,int hight){
		int mid=low+(hight-low)/2;
		if(low>=hight){            //递归的结束条件
			return;
		}
		mergeSort(arc,low,mid);    //将数组划分为两个数组
		mergeSort(arc,mid+1,hight);
		merge(arc,low,mid,hight);   //将两个数组归并
	}

	private void merge(int[] arc, int low, int mid,int hight) {
		
		int a;
		int i=low,j=mid+1;          //注意i=low,而不是i=0
		for(int k=low;k<=hight;k++){//k=low,而不是k=0,k<=hight,而不是k<=arc.lenght-1
			aux[k] = arc[k];        
		}
		for(a=low;a<=hight;a++)    //a=low,而不是a=0,a<=hight,而不是a<=arc.lenght-1
		if(i>mid){                 //如第一个数组元素全部已经归并,则将第二个数组元素直接归并到arc[]
			arc[a] = aux[j++];  
		}else if(j>hight){         //如第二个数组元素全部已经归并,则将第一个数组元素直接归并到arc[]
			arc[a] = aux[i++];
		}else if(aux[i]<aux[j]){
			arc[a] = aux[i++];
		}else{
			arc[a] = aux[j++];
		}		
	}


注:数组aux[]声明为全局变量,如果作为局部变量的话,在递归过程中会不断实例化新的数组,这样子会增加算法的空间复杂度

 

 

 

2.2自下而上的归并排序

自下而上归并排序思想:直接将数组进行两两(每个数组为1个元素)归并,然后四四(每个数组为2个元素)归并,八八(每个数组为4个元素)归并,一直循环下去,直到将整个数组归并。

 

看看具体的代码

 

public void mergeSort2(int arc[]){
		int N = arc.length;
		int low;
		for(int sz=1;sz<N;sz*=2){
			for(int i=0;i<N;i+=2*sz){
				low = i;
				merge(arc,low,low+sz-1,Math.min(low+2*sz-1, N-1));
			}
		}				
	}


注:之前一直对merge(arc,low,low+sz-1,Math.min(low+2*sz-1, N-1));中的low+sz-1和low+2*sz-1的“-1”难以理解,网上又找不到对它的解释,现在就将我的理解分享出来吧

 

(sz即为两两、四四、八八归并时的变量,这里不多解释)。假设a指向的元素和a左边的所有元素称为a拥有的元素,因此low+sz-1和low+2*sz-1中的 “-1”是因为low和sz或者low和2*sz拥有的元素中,low指向的那个元素重复了,既然重复那么就要-1。

 

归并排序算法的几个特点:

1.时间复杂度为O(nlogn);

2.稳定

3.自上而下的归并排序需要创建辅助数组

 

3、快速排序

快速排序的思想:找一个切点,将数组切分为两部分,小于切点的元素交换到切点的左边,大于切点的元素交换到切点的右边,并返回切点下标,再把切点左边和切点右边分别作为一个数组,递归下去,直到low>=high。

看看具体的代码

 

public void qSort(int arc[],int low,int high){
		
		if(low>=high){       //递归的结束条件
			return;
		}
		int pivot = partiton(arc,low,high);  //返回切点
		qSort(arc,low,pivot);           //将切点左边的数组作为整体递归
		qSort(arc,pivot+1,high);        //将切点右边的数组作为整体递归
		
	}

	private int partiton(int[] arc, int low, int high) {   //将数组切分为两部分,小于切点的元素交换到切点的左边,
		                                                //  大于切点的元素交换到切点的右边,并返回切点下标
		int pivotkey = arc[low];		    //默认数组的第一个元素为切点
		while(low<high){			
			while(low<high&&arc[high]>=pivotkey){
				high--;
			}
			ench(arc,low,high);    //元素的交换
			while(low<high&&arc[low]<=pivotkey){
				low++;
			}
			ench(arc,low,high);
		}		 
		return low;  //注意返回的是下标而不是pivotkey
		
	}

	private void ench(int[] arc, int low, int high) {   //元素的交换
		
		int t;
		t = arc[low];
		arc[low] = arc[high];
		arc[high] = t;
		
	}

 

 

 

 

 

快速排序算法的几个特点:

1.时间复杂度为O(nlogn);

2.不稳定

 

 

 

总结

1.堆排序适用于大量数组选出小于k(k>0)的元素的应用,过程是不断向堆尾添加数据,使新添加的不断往上浮到合适位置,并把根结点(值最大)去掉,重新调整为大顶堆,不断循环,就可以找到小于k的元素。这样大量数据就需要一次性调入内存进行排序,而是调用一部分作为堆,并不断向堆添加数据和删除不符合条件的数据。

2.归并排序分为自上而下和自下而上两种,即递归和非递归。

3.虽然快速排序和归并排序的时间复杂度都一样(nlogn),但是由于硬件原因,快速排序的平均速度要快于归并排序

 

经典排序算法——快速排序、归并排序、堆排序 之前两篇关于排序算法的综述以及平方阶复杂度的3种具体类型的排序算法,这一篇将具体介绍其中平均时间复杂度在平方阶O(nlog2n)O(nlog_2n)O(nlog2​n)的三个排序算法,以及各种算法的代码实现(亲测正确)。 快速排序 快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 O(nlogn)O(nlogn)O(nlogn)次比较。在最坏状况下则需要O(n2)O(n... 阅读详情

相关推荐

快速排序、堆排序、归并排序简单比较

快速排序、堆排序和归并排序都是平均时间复杂度为O(nlog(n))的算法。有关其原理介绍已经有很多。今天写了个简单的实现,用JFreeChart做了个简单的性能比较。懒得保存在本地,上传一下,以供日后回看。 import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartFrame; import org.jfree.ch

ohohoohoho的专栏 1753

堆排序学习总结

堆排序可以在前k趟就能确认数组的第K大或第k小元素。 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序。 首先我们来了解下什么是堆。 堆排序基本原理 堆分为两种:大顶堆和小顶堆,两者的差别主要在于排序方式。 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图: 堆排序的基本思...

is Mr.Chen的博客 529

冒泡排序,快速排序,堆排序,归并排序

1.冒泡排序(1)基本思想:从无序序列头部开始,进行两两比较,根据大小交换位置,直到最后将最大(最小)的数据元素交换到了无序序列的队尾,从而成为有序序列的一部分;下一次继续这个过程,直到所有数据元素都排好序。算法的核心在于:每次通过两两比较交换位置。选出剩余无序序列里最大(最小)的数据元素放到队尾。(2)C++实现代码:#include&lt;stdio.h&gt; void bubble_sor...

qq_35710556的博客 2476

【排序算法】——— 堆排序总结

文章目录

Lebron 1089

插入排序、归并排序、堆排序和快速排序的稳定性分析

在计算机科学中,排序是将一组数据按照特定顺序进行排列的过程。排序算法的效率和稳定性是评价其优劣的两个重要指标。稳定性指的是在排序过程中,相等的元素在排序后保持原有的相对顺序。本文将详细分析插入排序、归并排序、堆排序和快速排序这四种常见排序算法的稳定性,并通过浅显易懂的语言进行解释。

笔者从事电信媒体开发多年,愿意将多年的开发经验分享给同行 2865

堆排序总结 堆排序总结

堆排序总结.doc 堆排序总结.doc 堆排序总结.doc 堆排序总结.doc

堆排序小结

堆排序 堆 定义:堆是一种数据结构,可以按层次从左到右,构造成一颗完全二叉树。除却最后一层,其它层一定是排满的。 性质:         (1)父子结点的位置关系:                  设定:根节点的位置为1,heap[1],那么对于完全二叉树中一个拥有父子节点的节点来说,他们的位置必定存在以下关系                   parent[i] = ⌊

盛夏和也的博客 305

数据结构课程设计 实验报告——堆排序

堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。

堆排序算法 总结

最近面试,老是被问到堆排序算法。 回答时老是感觉思路不清楚,现在总结一下,把思路弄清楚的。 1.堆排序是利用堆的特性对记录序列进行排序的一种排序方法。 好的那么堆得特性是什么呢? 堆得定义: 堆是满足下列性质的数列{r1, r2, …,rn}:   如下

clam_clam的专栏 5万+

Windows 游戏 EXCEPTION_ACCESS_VIOLATION 修复:3类硬件问题与5步软件排查法

本文提供Windows游戏EXCEPTION_ACCESS_VIOLATION错误的终极修复指南,涵盖3类硬件问题(内存故障、显卡问题、超频不稳定)和5步软件排查法(文件验证、驱动更新、DEP调整等),帮助玩家彻底解决0xFFFFFFFFFFFFFFFF内存访问冲突问题。

weixin_31856057的博客 2406

手把手教你理解MIS结构C-V特性曲线:从理论到测试实操

本文深入解析了金属-绝缘体-半导体(MIS)结构的电容-电压(C-V)特性曲线,从积累、耗尽到反型等物理状态出发,详细阐述了其测试原理与实操要点。文章重点介绍了如何通过C-V曲线提取氧化层厚度、掺杂浓度、界面态密度等关键参数,并探讨了偏压-温度(B-T)应力实验在揪出可动离子电荷等可靠性问题中的应用,为半导体器件物理研究与工艺评估提供了实用指南。

weixin_29304021的博客 440

堆排序、快速排序和归并排序

快排的思想、Hoare版分割法、挖坑法分割法、如何优化快速排序。

2301_77053417的博客 2991

MaxEnt物种分布预测中的常见误区与优化技巧:如何提高模型准确率

本文深入探讨了MaxEnt物种分布预测模型从基础应用到精准预测的进阶实践。针对模型准确率提升,文章系统分析了环境变量筛选、模型参数调优、结果批判性解读等核心环节的常见误区,并提供了基于生态位模型原理的深度优化技巧,帮助研究者产出更可靠、可解释的预测结果。

weixin_29219539的博客 594

堆排序,归并排序和快速排序

一,堆排序,可以用来解决优先队列,topk等问题 class Solution: def sortArray(self, nums: List[int]) -> List[int]: def heapsort(nums): len_nums = len(nums) # 建堆过程,也可以理解为向上调整的过程 for i in range(len_nums//2-1, -1, -1):

qq1344574215的博客 455

【Linux】U盘配置Ubuntu系统 ——(Win10+Ubuntu20.04)双系统安装教程

Ubuntu系统安装

WS_Change的博客 4327

菱Q系列串行通信模块QJ71C24N:概述与特点

该模块支持多种串行通信协议,包括RS-232、RS-422和RS-485等,并提供了可靠的数据传输和高效的通信性能。菱Q系列串行通信模块QJ71C24N是一款功能强大的模块,具有多种通信协议支持、高速数据传输、多点通信能力和简化配置与使用等特点。简化配置和使用:QJ71C24N模块具有简单易用的配置工具和用户界面,使得用户能够快速进行模块的设置和调整。高速数据传输:QJ71C24N模块提供了高速的数据传输能力,可实现快速的数据交换和通信。本文将介绍QJ71C24N模块的概述和特点,并提供相应的源代码示例。

IunScala的博客 1931

堆排序、归并排序、快速排序

堆排序 堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。 堆排序是基于堆这种数据结构实现的,什么是堆呢?首先,堆是一棵完全二叉树,其次根据性质不同可以分为以下两种: 大根(顶)堆:每个结点的值均大于等于它的两个孩子结点的值 小根(顶)堆:每个结点的值均小于等于它的两个孩子结点的值 显然,大根堆的堆顶具有整个堆中最大的结点值,小根堆的堆顶具有整个堆中最小的结点值。下面我

闻风听雨的博客 1098

由异常的测试眼图引发的深入思考

信号测试中出现“双眼皮”的眼图测试效果,可能的导致因素总结如下:PCB通道阻抗设计不匹配,负载端出现严重反射;发射端采用了不当的信号预处理;接收器均衡处理不当;通道串扰严重... 基于以上的假设,本文就逐一分析下这些因素到底是如何对正常的信号眼图造成影响的。

一只豌豆象的博客 3060

快速排序 堆排序 归并排序

堆排序的思想就是先将待排序的序列建成大根堆,使得每个父节点的元素大于等于它的子节点。如果nums[i]>pivot,交换nums[i],nums[great],i++,great--;如果nums[i]

2301_76352996的博客 765

小程序数据采集(3):PC端微信小程序降维调试与流量数据获取详解

本文提出了一种针对PC端微信小程序的逆向分析方法,通过利用PC端基于Chromium架构的天然优势,实现无需Root的降维打击。文章详细介绍了如何开启CEF远程调试协议、基于DevTools Protocol实现流量劫持、对抗PC端安全防线以及获取小程序本地存储数据的技术方案。相比移动端严苛的环境,PC端小程序在调试接口、网络拦截和数据存储等方面存在显著漏洞,为爬虫开发提供了更便捷的突破口。

数据知道的博客 825

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

排序算法:归并排序、快速排序、堆排序

这两种方法,个人认为只是前者用了递归的方法,后者使用两个 for 循环模拟了递归压栈出栈的算法,本质上还是相同的(如果理解错误,还望大佬指出)。而这两个有序的序列,又是根据“分治”思想将一个学列分割成的两部分(将一个序列不断的分隔,到最后就剩一个的时候他自然就是有序的)。两个指针,left从左到右,找比 piovt “大”的数;堆排序是“选择排序”的一种变体,算法中比较难的地方是用数组构建“大顶堆”或“小顶堆”的过程。2、此时数组的 0 位置(也就是堆顶),就是数组的最大值了,将其与数组的最后一个数交换。

softshow1026的博客 1293

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Python算法与数据结构——快速排序、堆排序、归并排序

快速排序、堆排序、归并排序

weixin_74165584的博客 3164

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

堆排序、快速排序、归并排序算法详解

手把手带你拿捏终极排序算法。

LibraRhy的博客 1877
上一篇: 选择排序、插入排序、希尔排序总结
下一篇: 红黑树-插入篇
ZengBlog
博客等级 码龄10年 29粉丝 22原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值