时间:2023-10-25 13:26:01 浏览:69
之前我们在交换类排序中引入了冒泡排序,这次引入了另一种交换类排序,叫做快速排序。快速排序的优点是原地排序,不占用额外空间,时间复杂度为o(nlogn)。
当然对于快速排序也有缺点。对于包含大量重复元素的数组排序效率非常低,时间复杂度会降低到o(n ^ 2)。此时,我们需要使用改进的快速排序-双向快速排序。在双向快速排序的基础上,进一步优化了三向快速排序。
快速排序
快速排序的基本思想是通过一遍排序将待排序的数据分成两个独立的部分,其中一部分的所有数据都小于另一部分的所有数据,然后按照这种方法分别对这两部分数据进行快速排序,整个排序过程可以递归进行,使整个数据成为有序序列。
快速排序步骤如下:
1.以第一个元素为分界点,用l指向它。
2.遍历右边的元素。在遍历的过程中,我们排列数组,有的小于v,有的大于v,用j指向小于v和大于v的分界点,用i指向当前访问的元素e,此时数组arr[l 1…j]v,arr [j 1 … i-1] v。
3.如果ev,直接在大于v的部分后面合并e,然后我继续比较下面的元素。
4.如果ev,把e移到j指向的元素的后面元素,然后j,然后我继续比较后面的元素。
5.这样遍历整个数组一次。遍历后,数组分为三部分,左边部分为v,中间部分为v,右边部分为v。
6.最后我们把l指向的元素和j指向的元素进行交换,这样元素v就很快排序了。v的左边元素小于v,右边元素大于v。
现在我们用上面的方法快速排序数组[2,1,4,3,7,8,5,6]。下图显示了快速排序的整个过程:
快速排序代码:
公共静态无效排序(可比[] arr) {
int n=arr.length
sort(arr,0,n1);
}
//递归使用快速排序对arr的范围进行排序[l…r]
私有静态空排序(可比[] arr,int l,int r) {
if (l=r) {
返回;
}
//分区arr[l…r]并返回p,这样arr[l…p-1]arr[p];arr[p 1…r] arr[p]
int p=partition(arr,l,r);
排序(arr,l,p1);
sort(arr,p 1,r);
}
私有静态int分区(可比[] arr,int l,int r) {
//最左边的元素用作校准点
可比v=arr[l];
int j=l;
for(int i=l 1;i=r;i ) {
if (arr[i]。compareto(v) 0)
swap(arr,j 1,i);
j .
}
}
swap(arr,l,j);
返回j;
}
优化快速排序
经过上面的介绍,我们可以发现快速排序并不能保证每个分割都有相同大小的子阵,所以可能一边小一边大。对于有序数组,快速排序的时间复杂度变成o(n ^ 2),相当于树退化成链表。下图显示了这一变化:
上面,我们使用左边的第一个元素作为校准元素。现在我们随机选择一个元素作为校准元素。此时第一次选择第一个元素的概率为1/n,第二个元素为1/n-1。以此类推,在出现之前退化成链表的概率是1/n(n-1)(n-2)…。当n较大时,这个概率几乎为零。
另一个优化是对小规模数组使用插入排序,因为递归会使小规模问题中的方法调用过于频繁,并且插入排序对于小规模数组非常快。
优化的快速排序代码:
公共静态无效排序(可比[] arr) {
int n=arr.length
sort(arr,0,n1);
}
//贺盛文贺盛文,-什么停止[l.r]阿云阿云阿云阿云阿云阿云阿云
私有静态void排序(相当于[] arr,int l,int r)}
//云娥与云娥,云娥与云娥
如果(rl=15)}
insertonstart。sort(arr、l、r);
返回;
}
//-什么停止[l.r]阿悦分割区诶诶哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟,阿忠p,你知道吗?僧儿页:1:停止[p1.r]停止[p]
int p=分区(arr、l、r);
输出(arr,l,p-1);
(经常预算):
}
专用静态(同internationalorganizations)国际组织部件
(可比[] arr,int l,int r) {
//在arr[l…r]范围内随机选择一个值作为校准点轴心
swap(arr,l,(int)(math . random()*(rl ^ 1))l);
可比v=arr[l];
int j=l;
for(int i=l 1;i=r;i ) {
if (arr[i]。compareto(v) 0)
swap(arr,j 1,i);
j .
}
}
swap(arr,l,j);
返回j;
}
双向快速排序
对于包含大量重复元素的数组,上面的快速排序效率很低,因为在我们上面的判断中,如果元素小于v,那么元素就放在v部分,如果元素大于等于v,那么就放在v部分。这时如果数组中有大量重复的元素,v部分会变得很长,导致左右两边不平衡,性能降低。
双向快速排序的步骤如下:
1.把v和v放在数组的两端,用i指向v的下一个元素,用j指向v的前一个元素。
2.从i向后遍历,如果遍历的元素ev继续向后遍历,直到遍历的元素e=v,那么停止遍历。从j开始向前遍历,如果遍历的元素为ev,继续向前遍历,直到遍历的元素e=v,然后停止遍历。
3.交换一下我指向的元素和j指向的元素,然后我,j继续比较下一个。
双向快速排序代码:
公共静态无效排序(可比[] arr) {
int n=arr.length
sort(arr,0,n1);
}
私有静态空排序(可比[] arr,int l,int r) {
//对于小规模数组,使用插入排序
if(rl=15){
insertionsort.sort(arr,l,r);
返回;
}
int p=partition(arr,l,r);
排序(arr,l,p1);
sort(arr,p 1,r);
}
私有静态int分区(可比[] arr,int l,int r) {
//在arr[l…r]范围内随机选择一个值作为校准点轴心
swap(arr,l,(int)(math . random()*(rl ^ 1))l);
可比v=arr[l];
int i=l 1,j=r;
while (true) {
//注意这里的边界,arr[i]。compareto(v) 0,不能是arr[i]。compareto(v)=0
//如果不加等号,此时会退出while循环,也就是交换i和j的值,这样对于一个包含大量相同元素的数组,交换两边相等的数据,可以在一定程度上保证两路的数据平衡。
//从i向后遍历,如果遍历的元素ev,继续向后遍历,直到遍历的元素e=v,然后停止遍历
while (i=r arr[i]。compareto(v) 0)
i;
}
//从j开始向前遍历,如果遍历的元素为ev,继续向前遍历,直到遍历的元素e=v,然后停止遍历
while(j=l ^ 1 arr[j]。compareto(v) 0)
j ;
}
if (i=j) {
打破;
}
swap(arr,i,j);
i;
j ;
}
//此时j指向的元素是数组中小于v的最后一个元素,i指向的元素是数组中大于v的第一个元素。
swap(arr,l,j);
返回j;
}
三向快速排序
三向快速排序的步骤如下:
1.在双向快速排序的基础上,我们将等于v的元素作为单一部分。lt指向小于v部分的最后一个元素,gt指向大于v部分的第一个元素。
2.从i向后遍历,如果遍历的元素e=v,e直接合并到=v部分,然后i继续遍历。如果你遍历元素ev,交换e部分的第一个元素和=v(lt 1指向的元素),然后lt,我继续遍历。如果遍历的元素ev,则交换e和v的前一个元素(gt-1指向的元素),然后gt ,但此时不需要改变i,因为i位置的元素与gt位置之前的空白元素交换。
3.遍历之后,i=gt,然后用lt-pointing元素交换l-pointing元素。
4.在v形零件和v形零件上执行上述操作。
三向快速排序相对于双向快速排序的优势在于,减少了重复元素的比较操作,因为重复元素在一次排序中已经被排列为单一部分,然后只需要对不等于重复元素的其他元素进行排序。
三向快速排序代码:
公共静态无效排序(可比[] arr) {
int n=arr.length
sort(arr,0,n1);
}
私有静态空排序(可比[] arr,int l,int r) {
//对于小规模数组,使用插入排序
if(rl=15){
insertionsort.sort(arr,l,r);
返回;
}
//在arr[l…r]范围内随机选择一个值作为校准点轴心
swap(arr,l,(int)(math . random()*(rl ^ 1))l);
可比v=arr[l];
int lt=l;//arr[l 1…lt] v
int gt=r 1;//arr[gt…r] v
int i=l 1;//arr[lt 1…i)=v
while (i gt) {
if (arr[i]。compareto(v) 0)
swap(arr,i,lt 1);
i;
lt。
} else if (arr[i]。compareto(v) 0)
互换(arr,i,gt1);
gt ;
} else { //arr[i]==v
i;
}
}
互换(arr,l,lt);
排序(arr,l,lt1);
sort(arr,gt,r);
}
摘要
本文介绍了快速排序、快速排序的优化、双向快速排序和三向快速排序。
为了快速排序,我们需要选择合适的校准点,使校准点的两侧平衡;当在快速排序中递归到小数组时,我们可以用插入排序来代替递归,以减少不必要的开销。
对于双向快速排序和三向快速排序,我们在数组中使用了大量重复的元素。
最后,建议jdk底部的排序使用插入排序 双路快速排序
合并和排序的组合。
微信群太多了怎么归类(微信群太多如何排序)
现在几乎每个人都有三五个微信群,有的甚至有几十个微信群。当然,拥有大量微信群的人应该花更多的时间来管理微信群,否则微信群的作用无法得到充分发挥。不过你不用担心,如果选择专业的微信多群管理软件,可以帮助你轻松管理微信群。但是市面上有很多这样的软件,选择的时候要多比较。那么,如何选择微信多群管理软件呢?性价比怎么样?我们来看看。
选择微信多群管理软件时,要根据几个标准来选择。这样可以选择适合自己的软件,操作起来非常方便。大家在选择微信多群管理软件时,要从以下几个方面进行选择:
1.了解软件的性能:为什么要看软件的性能?这是因为有些软件开发的时候,技术方面不够,人在体验它的功能的时候,可能会卡。性能不稳定会影响大家的操作。所以我们在选择微信多群管理软件的时候,要了解它的性能。只有性能稳定的软件,才能让大家更好的运营,更好的管理社区。
2.熟悉软件的功能:不同的微信多群管理软件有不同的功能。选择适合自己的软件,在功能上能满足大家的需求。如果选择单功能软件,在管理社区时可能会出现操作问题。彩色企业服务是一款多功能社区管理软件,是专业的微信群运营工具、管理工具、专业的客服聊天系统。借助这个软件,每个人都可以高效地管理社区,即使你有数百个社区。
3.了解软件的性价比:每个软件都是用技术开发的,所以价格不便宜。当然,你也可以选择自由软件。但是这些软件在性能和功能上并不能保证每个人的使用。所以要选择有技术支持的软件。彩画使用方便,性价比高,给你带来更好的体验。
微信多群管理软件如何选择?性价比怎么样?看了上面的介绍,大家对这个问题有所了解。微信多群管理软件有很多。选择的时候可以多方面比较选择。
社区管理需要从多方面进行。选择社区管理软件进行管理也是一种很好的方法。建议你选择合适的工具,管理效率才能大大提高!
相关文章
怀孕周期
备孕分娩婴儿早教
猜你喜欢