JAVA快排数组被卡常?试试优先队列(堆排)

快排的最坏时间复杂度可以达到O(n^2)。有人说这种概率极小,但如果测试数据被精心安排过呢?尤其是对于轻易就被卡常的JAVA来说。快排不小心就T掉。另外,空间复杂度上,快排主递归时需要使用栈空间,最坏O(n),最好O(logn)。
堆排序是一个宝藏,它的平均、最坏、最好时间复杂度都是O(nlogn)级别的,有时更少。并且空间复杂度为常数级别。然而为什么大家更推崇快排?

一句话就是:因为堆排序下,数据读取的开销变大。在计算机进行运算的时候,数据不一定会从内存读取出来,而是从一种叫cache的存储单位读取。原因是cache相比内存,读取速度非常快,所以cache会把一部分我们经常读取的数据暂时储存起来,以便下一次读取的时候,可以不必跑到内存去读,而是直接在cache里面找。一般认为读取数据遵从两个原则:temporal locality,也就是不久前读取过的一个数据,在之后很可能还会被读取一遍;另一个叫spatial locality,也就是说读取一个数据,在它周围内存地址存储的数据也很有可能被读取到。因此,在读取一个单位的数据(比如1个word)之后,不光单个word会被存入cache,与之内存地址相邻的几个word,都会以一个block为单位存入cache中。另外,cache相比内存小得多,当cache满了之后,会将旧的数据剔除,将新的数据覆盖上去。在进行堆排序的过程中,由于我们要比较一个数组前一半和后一半的数字的大小,而当数组比较长的时候,这前一半和后一半的数据相隔比较远,这就导致了经常在cache里面找不到要读取的数据,需要从内存中读出来,而当cache满了之后,以前读取的数据又要被剔除。简而言之快排和堆排读取arr[i]这个元素的平均时间是不一样的。
作者:qinzp
链接:https://www.zhihu.com/question/23873747/answer/327295185
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

不要因此忽视堆排序。在ACM中,堆排序可以比快速排序快很多。写法:

			PriorityQueue<Integer> q = new PriorityQueue<>();
			for(int i=0;i<n;i++) {
				q.add(sc.nextInt());
			}
			for(int i=0;i<n;i++) {
				a[i]=q.poll();
				sum+=a[i];
			}
			//Arrays.sort(a);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值