跟着AI学算法快速排序,剖析排序过程
快速排序是一种基于比较的排序算法,是排序算法中平均性能最优的一种算法之一。其基本思想是通过不断地选取一个基准值(pivot),将待排序序列划分为两个子序列,其中一个子序列中的所有元素都小于等于基准值,另一个子序列中的所有元素都大于基准值,然后对这两个子序列分别递归地进行排序,最终得到一个有序序列。
快速排序算法的关键在于如何选取基准值。一般来说,可以选择待排序序列的第一个元素、最后一个元素、中间元素或随机元素作为基准值。选定基准值之后,可以使用两个指针(i,j)分别从序列的左右两端向中间扫描,当i指向一个大于等于基准值的元素时,停止扫描;当j指向一个小于等于基准值的元素时,停止扫描。然后交换i和j指向的元素,继续扫描直到ij为止。最后将基准值与i指向的元素交换位置,即可完成一次划分。
执行过程请移步文章末尾:排序执行过程。
快速排序算法的时间复杂度为O(nlogn)(最坏情况下为O(n2)),空间复杂度为O(logn)。
AI编码实现:
在该代码中,我们使用了两个函数,分别是quickSort和partition。其中,quickSort函数是递归调用的,它用来对整个数组进行排序。partition函数则用来将待排序数组划分为两部分,并返回枢轴的索引位置。在partition函数中,我们首先选取数组的第一个元素作为枢轴,并使用两个指针i和j分别从待排序序列的左右两端开始扫描。当i指向一个大于等于枢轴值的元素时,停止扫描;当j指向一个小于等于枢轴值的元素时,停止扫描。然后交换i和j指向的元素,继续扫描直到ij为止。最后将枢轴值与j指向的元素交换位置,即可完成一次划分。
本地测试:
为了能够打印排序过程,代码稍作修改。packagecom。algorithm。sort;importjava。util。Arrays;publicclassQuickSort{publicstaticvoidquickSort(int〔〕arr,intleft,intright,intdeep){deep;System。out。println();System。out。println(递归深度:deep;开始);System。out。println(比较left:left,right:right;);if(leftright){System。out。println(排序数组:Arrays。toString(Arrays。copyOfRange(arr,left,right1)));System。out。println(递归深度:deep;开始排序,获取枢轴);intpivotIndexpartition(arr,left,right);将待排序数组划分为两部分,并返回枢轴的索引位置System。out。println(递归深度:deep;排序结束。枢轴:〔arr〔pivotIndex〕〕;新数组:Arrays。toString(arr));System。out。println(开始枢轴:〔arr〔pivotIndex〕〕左侧部分快速排序);quickSort(arr,left,pivotIndex1,deep);对左半部分进行快速排序System。out。println(开始枢轴:〔arr〔pivotIndex〕〕右侧部分快速排序);quickSort(arr,pivotIndex1,right,deep);对右半部分进行快速排序}else{System。out。println(leftright,递归返回);}System。out。println(递归深度:deep结束);System。out。println();}publicstaticintpartition(int〔〕arr,intleft,intright){intpivotarr〔left〕;选取数组的第一个元素作为枢轴intileft1;i指针从左端点开始intjright;j指针从右端点开始System。out。println(枢纽元素:pivot;比枢纽元素小放左边,比枢纽元素大放右边);while(ij){while(ij){从左端点开始找到第一个大于等于枢轴的元素System。out。println(左侧开始,下标i:i,比较:〔arr〔i〕,pivot〕);if(arr〔i〕pivot){System。out。println(比枢纽元素大,停止比较,该元素待交换);break;}System。out。println(比枢纽元素小,不动,下标加1);i;}while(ij){从右端点开始找到第一个小于等于枢轴的元素System。out。println(右侧开始,下标j:j,比较:〔arr〔j〕,pivot〕);if(arr〔j〕pivot){System。out。println(比枢纽元素小,停止比较,该元素待交换);break;}System。out。println(比枢纽元素小,不动,下标减1);j;}if(ij){交换i和j指向的元素System。out。println(交换〔arr〔i〕,arr〔j〕〕;);swap(arr,i,j);System。out。println(左侧下标加1;右侧下标减1);i;j;}else{System。out。println(同一元素,不交换);}System。out。println(新数组:Arrays。toString(Arrays。copyOfRange(arr,left,right1)));}将枢轴值放到正确的位置上System。out。println(枢纽元素与小于枢纽元素的最后一个元素交换:〔pivot,arr〔j〕〕);swap(arr,left,j);returnj;}publicstaticvoidswap(int〔〕arr,inti,intj){inttemparr〔i〕;arr〔i〕arr〔j〕;arr〔j〕temp;}publicstaticvoidmain(String〔〕args){int〔〕arr{5,2,8,3,9,1};System。out。println(选择排序);System。out。println(初始数组:Arrays。toString(arr));System。out。println();quickSort(arr,0,arr。length1,0);System。out。println();System。out。print(最终数组:Arrays。toString(arr));}}
排序执行过程:快速排序初始数组:〔5,2,8,3,9,1〕递归深度:1;开始比较left:0,right:5;排序数组:〔5,2,8,3,9,1〕递归深度:1;开始排序,获取枢轴枢纽元素:5;比枢纽元素小放左边,比枢纽元素大放右边左侧开始,下标i:1,比较:〔2,5〕比枢纽元素小,不动,下标加1左侧开始,下标i:2,比较:〔8,5〕比枢纽元素大,停止比较,该元素待交换右侧开始,下标j:5,比较:〔1,5〕比枢纽元素小,停止比较,该元素待交换交换〔8,1〕;左侧下标加1;右侧下标减1新数组:〔5,2,1,3,9,8〕左侧开始,下标i:3,比较:〔3,5〕比枢纽元素小,不动,下标加1左侧开始,下标i:4,比较:〔9,5〕比枢纽元素大,停止比较,该元素待交换右侧开始,下标j:4,比较:〔9,5〕比枢纽元素小,不动,下标减1同一元素,不交换新数组:〔5,2,1,3,9,8〕枢纽元素与小于枢纽元素的最后一个元素交换:〔5,3〕递归深度:1;排序结束。枢轴:〔5〕;新数组:〔3,2,1,5,9,8〕开始枢轴:〔5〕左侧部分快速排序递归深度:2;开始比较left:0,right:2;排序数组:〔3,2,1〕递归深度:2;开始排序,获取枢轴枢纽元素:3;比枢纽元素小放左边,比枢纽元素大放右边左侧开始,下标i:1,比较:〔2,3〕比枢纽元素小,不动,下标加1左侧开始,下标i:2,比较:〔1,3〕比枢纽元素小,不动,下标加1同一元素,不交换新数组:〔3,2,1〕枢纽元素与小于枢纽元素的最后一个元素交换:〔3,1〕递归深度:2;排序结束。枢轴:〔3〕;新数组:〔1,2,3,5,9,8〕开始枢轴:〔3〕左侧部分快速排序递归深度:3;开始比较left:0,right:1;排序数组:〔1,2〕递归深度:3;开始排序,获取枢轴枢纽元素:1;比枢纽元素小放左边,比枢纽元素大放右边左侧开始,下标i:1,比较:〔2,1〕比枢纽元素大,停止比较,该元素待交换右侧开始,下标j:1,比较:〔2,1〕比枢纽元素小,不动,下标减1同一元素,不交换新数组:〔1,2〕枢纽元素与小于枢纽元素的最后一个元素交换:〔1,1〕递归深度:3;排序结束。枢轴:〔1〕;新数组:〔1,2,3,5,9,8〕开始枢轴:〔1〕左侧部分快速排序递归深度:4;开始比较left:0,right:1;leftright,递归返回递归深度:4结束开始枢轴:〔1〕右侧部分快速排序递归深度:4;开始比较left:1,right:1;leftright,递归返回递归深度:4结束递归深度:3结束开始枢轴:〔3〕右侧部分快速排序递归深度:3;开始比较left:3,right:2;leftright,递归返回递归深度:3结束递归深度:2结束开始枢轴:〔5〕右侧部分快速排序递归深度:2;开始比较left:4,right:5;排序数组:〔9,8〕递归深度:2;开始排序,获取枢轴枢纽元素:9;比枢纽元素小放左边,比枢纽元素大放右边左侧开始,下标i:5,比较:〔8,9〕比枢纽元素小,不动,下标加1同一元素,不交换新数组:〔9,8〕枢纽元素与小于枢纽元素的最后一个元素交换:〔9,8〕递归深度:2;排序结束。枢轴:〔9〕;新数组:〔1,2,3,5,8,9〕开始枢轴:〔9〕左侧部分快速排序递归深度:3;开始比较left:4,right:4;leftright,递归返回递归深度:3结束开始枢轴:〔9〕右侧部分快速排序递归深度:3;开始比较left:6,right:5;leftright,递归返回递归深度:3结束递归深度:2结束递归深度:1结束最终数组:〔1,2,3,5,8,9〕
洛阳过年游记(4)洛阳与开封旅游之对比1开封我们住了三天,去了中国翰园碑林大宋武侠城清明上河园大相国寺开封府大梁门城墙。预估的时间不足,遗憾没有去开封博物馆包公祠天波杨府等景点。洛阳我住了三天,去了龙门石窟白马寺洛邑古
读书笔记活着2023年的第二本书,很早以前就很想看的一本书,但是因为个人矫情又玻璃心,觉得这么悲伤的故事,还是不看为妙,却又好奇,如此难过的故事,为什么让那么多迷茫自卑的人,对未来充满的很大的
大明第一太监多恐怖?为前途亲手割命根子回一次家断送50万大军公元1449年,意气风发的明英宗朱祁镇御驾亲征,讨伐瓦剌,结果没有重创敌军,自己的军队反而在土木堡被饱了饺子,五十万大军叫天天不应,叫地地不灵,全军覆没,明英宗也做了俘虏,那叫一个
剖析北宋三冗得失鉴识,在蓬勃生长的背后,政策又是如何拔地而起在阅读此文前,诚邀您点击一下关注,既方便您进行讨论与分享,又给您带来不一样的参与感,感谢您的支持。引言公元960年,赵匡胤于陈桥兵变之时被拥为新帝,改元建隆,称宋太祖皇帝。赵匡胤观
这位皇帝名声不响,功绩却彪炳史册,远胜号称宋祖的赵匡胤!这位皇帝功绩远胜宋太祖赵匡胤,但名声却不响亮,他是谁呢?他就是唯一一个从牢狱里走出来的西汉传奇皇帝汉宣帝刘询。刘询本名刘病已,曾祖父是威名赫赫的汉武帝刘彻,曾祖母则是一代贤后卫子夫
低离子强度硝酸根还原,面向真正的水处理研究背景NO3是地表水和地下水中分布最广泛的污染物之一。通过间歇性可再生电力驱动的电化学NO3还原是一种很有前途的水处理策略。然而,在低离子强度溶液中,由于带负电荷的阴极与NO3之
塔里木油田今年1月油气双增实现开门红夕阳西下,塔里木油田南疆利民中心的工人仔细检查输气设备的运行状态,保障南疆供气平稳塔里木油田提供中新网乌鲁木齐2月3日电(陶拴科庞浩)3日,记者从中国石油塔里木油田公司获悉,塔里木
坐着火车飞上天!在西安,这条神奇老铁路你总该体验一次做自媒体这两三年,最喜欢的事情是去秦岭里逛。去的地方不算少了,出行方式也很多样,有时自驾,有时坐班车,有时徒步,有时坐火车。秦岭是一条很特别的山脉,从甘肃向东,一直绵延至陕西四川重
启程赴欧,威海市海外招商抢抓开门红来源威海新闻网2月3日,威海市境外招商团队将再度启程,赶赴比利时法国和德国的6座城市,开展招商和经贸促进活动,拜访10余家欧洲重点企业机构。这是春节后威海市境外招商团队首次外出招商
文景之治汉文帝刘恒汉文帝刘恒是刘邦的第四个儿子,西汉的第三个皇帝。他开创了我国封建王朝的第一个太平盛世文景之治,对后世产生了深远的影响。汉文帝的幸运刘恒8岁时,他的父亲刘邦驾崩,朝廷风云突变,太后吕
汉文帝的义母许负,凭借高超的相术被封侯,看看她都预言了啥?说到民间的相术,很多人或许认为那些都是封建迷信,不值得相信。然而,我国历史上的相术,历经几千年的流传,最终演变成为了一种学说。同时,在我国古代,还涌现出许多这方面的奇才。远在我国历