「java性能排序」java性能权威指南 豆瓣
本篇文章给大家谈谈java性能排序,以及java性能权威指南 豆瓣对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、java几种排序方式速度的简单测试
- 2、java自动排序函数.......
- 3、数据结构 java开发中常用的排序算法有哪些
- 4、java里,几种排序方法各有什么优缺点?
- 5、java排序,效率高的是哪种排序方法
- 6、Java中冒泡排序和选择排序哪一个性能更高一点呢?
java几种排序方式速度的简单测试
冒泡排序,选择排序,插入排序,快速排序
1、冒泡排序是排序里面最简单的了,但性能也最差,数量小的时候还可以,数量一多,是非常慢的。
public static void bubbleSort(int[] arr){
for(int i=0;iarr.length;i++){
for(int j=0;jarr.length-1-i;j++){
if(arr[j]arr[j+1]){
int temp =arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
2 选择排序(最慢)
选择排序的时间复杂度还有空间复杂度跟冒泡是一样的。
public static void chooseSort(int[] arr){
for(int i=0;iarr.length;i++){
for(int j=i+1;jarr.length;j++){
if(arr[i]arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
3、插入排序
插入排序的时间复杂度也是O(n*n),空间复杂度也是O(1)。
public static void insertSort(int[] arr){
for(int i=1;iarr.length;i++){
for(int j=0;ji;j++){
if(arr[i]arr[j]){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
4、快速排序(最快)
public static void quickSort(int[] arr,int head,int tail){
int i=head,j=tail;
if(ij){
return;
}
int key=arr[i];
while (ij) {
while(ij key=arr[j]){
j--;
}
if(ij){
arr[i++]=arr[j];
}
while(ij key=arr[i]){
i++;
}
if(ij){
arr[j--]=arr[i];
}
}
arr[j]=key;
quickSort(arr, head, j-1);
quickSort(arr, j+1, tail);
}
测试:
public static int[] getArr(){
int arr[]=new int[100000];
for(int i=0;iarr.length;i++){
arr[i]=new Random().nextInt(arr.length)+1;
}
return arr;
}
public static void main(String[] args) {
int arr1[]=getArr();
int arr2[]=getArr();
int arr3[]=getArr();
int arr4[]=getArr();
long s1=System.currentTimeMillis();
bubbleSort(arr1);
long e1=System.currentTimeMillis();
System.out.println("bubbleSort:"+(e1-s1)+"毫秒");
long s2=System.currentTimeMillis();
chooseSort(arr2);
long e2=System.currentTimeMillis();
System.out.println("chooseSort:"+(e2-s1)+"毫秒");
long s3=System.currentTimeMillis();
insertSort(arr3);
long e3=System.currentTimeMillis();
System.out.println("insertSort:"+(e3-s3)+"毫秒");
long s4=System.currentTimeMillis();
quickSort(arr4, 0, arr4.length-1);
long e4=System.currentTimeMillis();
System.out.println("quickSort:"+(e4-s4)+"毫秒");
}
java自动排序函数.......
要实现排序功能,一般有两种途径,这里对基本类型不适用,基本类型一般有Arrays中的静态方法.
1.对象本身实现Comparable接口,那么该类的实例就是可以排序的.
有关Comparable:
只要实现了Comparable接口,就可以调用Collections的sort方法对集合中的元素排序.
2.指定一个Comparator,也就是实现了Comparator的类的一个实例.
但是Java本身只提供了一个Comparator的实现,就是Collections.reverseOrder().
该方法返回的是一个已经实现了Comparable接口的反序.
看一下Comparator的全部内容:
public interface Comparator {
int compare(Object o1, Object o2);
boolean equals(Object obj);
}
定义了两个方法,其实我们一般都只需要实现compare方法就行了,因为类都是默认从Object继承
所以会使用Object的equals方法.
Comparator一般都作为一个匿名类出现,对于没有实现Comparable的对象的集合,排序的时候
需要指定一个Comparator.
这里举例说明
对于实现了Comparable的类我们就用最简单的Integer
List list=new ArrayList();
list.add(new Integer(3));
list.add(new Integer(53));
list.add(new Integer(34));
Collections.sort(list);
对于没有实现Comparable的,我们就用Object,按照hashCode大小来排序.
List list= new ArrayList();
list.add(new Object());
list.add(new Object());
list.add(new Object());
Collections.sort(list,new Comparator(){ public int compare(Object o1, Object o2){
return (o1.hashCode()-o2.hashCode());
})
数据结构 java开发中常用的排序算法有哪些
排序算法有很多,所以在特定情景中使用哪一种算法很重要。为了选择合适的算法,可以按照建议的顺序考虑以下标准:
(1)执行时间
(2)存储空间
(3)编程工作
对于数据量较小的情形,(1)(2)差别不大,主要考虑(3);而对于数据量大的,(1)为首要。
主要排序法有:
一、冒泡(Bubble)排序——相邻交换
二、选择排序——每次最小/大排在相应的位置
三、插入排序——将下一个插入已排好的序列中
四、壳(Shell)排序——缩小增量
五、归并排序
六、快速排序
七、堆排序
八、拓扑排序
一、冒泡(Bubble)排序
----------------------------------Code 从小到大排序n个数------------------------------------
void BubbleSortArray()
{
for(int i=1;in;i++)
{
for(int j=0;in-i;j++)
{
if(a[j]a[j+1])//比较交换相邻元素
{
int temp;
temp=a[j]; a[j]=a[j+1]; a[j+1]=temp;
}
}
}
}
-------------------------------------------------Code------------------------------------------------
效率 O(n²),适用于排序小列表。
二、选择排序
----------------------------------Code 从小到大排序n个数--------------------------------
void SelectSortArray()
{
int min_index;
for(int i=0;in-1;i++)
{
min_index=i;
for(int j=i+1;jn;j++)//每次扫描选择最小项
if(arr[j]arr[min_index]) min_index=j;
if(min_index!=i)//找到最小项交换,即将这一项移到列表中的正确位置
{
int temp;
temp=arr[i]; arr[i]=arr[min_index]; arr[min_index]=temp;
}
}
}
-------------------------------------------------Code-----------------------------------------
效率O(n²),适用于排序小的列表。
三、插入排序
--------------------------------------------Code 从小到大排序n个数-------------------------------------
void InsertSortArray()
{
for(int i=1;in;i++)//循环从第二个数组元素开始,因为arr[0]作为最初已排序部分
{
int temp=arr[i];//temp标记为未排序第一个元素
int j=i-1;
while (j=0 arr[j]temp)/*将temp与已排序元素从小到大比较,寻找temp应插入的位置*/
{
arr[j+1]=arr[j];
j--;
}
arr[j+1]=temp;
}
}
------------------------------Code--------------------------------------------------------------
最佳效率O(n);最糟效率O(n²)与冒泡、选择相同,适用于排序小列表
若列表基本有序,则插入排序比冒泡、选择更有效率。
四、壳(Shell)排序——缩小增量排序
-------------------------------------Code 从小到大排序n个数-------------------------------------
void ShellSortArray()
{
for(int incr=3;incr0;incr--)//增量递减,以增量3,2,1为例
{
for(int L=0;L(n-1)/incr;L++)//重复分成的每个子列表
{
for(int i=L+incr;in;i+=incr)//对每个子列表应用插入排序
{
int temp=arr[i];
int j=i-incr;
while(j=0arr[j]temp)
{
arr[j+incr]=arr[j];
j-=incr;
}
arr[j+incr]=temp;
}
}
}
}
--------------------------------------Code-------------------------------------------
适用于排序小列表。
效率估计O(nlog2^n)~O(n^1.5),取决于增量值的最初大小。建议使用质数作为增量值,因为如果增量值是2的幂,则在下一个通道中会再次比较相同的元素。
壳(Shell)排序改进了插入排序,减少了比较的次数。是不稳定的排序,因为排序过程中元素可能会前后跳跃。
五、归并排序
----------------------------------------------Code 从小到大排序---------------------------------------
void MergeSort(int low,int high)
{
if(low=high) return;//每个子列表中剩下一个元素时停止
else int mid=(low+high)/2;/*将列表划分成相等的两个子列表,若有奇数个元素,则在左边子列表大于右侧子列表*/
MergeSort(low,mid);//子列表进一步划分
MergeSort(mid+1,high);
int [] B=new int [high-low+1];//新建一个数组,用于存放归并的元素
for(int i=low,j=mid+1,k=low;i=mid j=high;k++)/*两个子列表进行排序归并,直到两个子列表中的一个结束*/
{
if (arr[i]=arr[j];)
{
B[k]=arr[i];
I++;
}
else
{ B[k]=arr[j]; j++; }
}
for( ;j=high;j++,k++)//如果第二个子列表中仍然有元素,则追加到新列表
B[k]=arr[j];
for( ;i=mid;i++,k++)//如果在第一个子列表中仍然有元素,则追加到新列表中
B[k]=arr[i];
for(int z=0;zhigh-low+1;z++)//将排序的数组B的 所有元素复制到原始数组arr中
arr[z]=B[z];
}
-----------------------------------------------------Code---------------------------------------------------
效率O(nlogn),归并的最佳、平均和最糟用例效率之间没有差异。
适用于排序大列表,基于分治法。
六、快速排序
------------------------------------Code--------------------------------------------
/*快速排序的算法思想:选定一个枢纽元素,对待排序序列进行分割,分割之后的序列一个部分小于枢纽元素,一个部分大于枢纽元素,再对这两个分割好的子序列进行上述的过程。*/ void swap(int a,int b){int t;t =a ;a =b ;b =t ;}
int Partition(int [] arr,int low,int high)
{
int pivot=arr[low];//采用子序列的第一个元素作为枢纽元素
while (low high)
{
//从后往前栽后半部分中寻找第一个小于枢纽元素的元素
while (low high arr[high] = pivot)
{
--high;
}
//将这个比枢纽元素小的元素交换到前半部分
swap(arr[low], arr[high]);
//从前往后在前半部分中寻找第一个大于枢纽元素的元素
while (low high arr [low ]=pivot )
{
++low ;
}
swap (arr [low ],arr [high ]);//将这个枢纽元素大的元素交换到后半部分
}
return low ;//返回枢纽元素所在的位置
}
void QuickSort(int [] a,int low,int high)
{
if (low high )
{
int n=Partition (a ,low ,high );
QuickSort (a ,low ,n );
QuickSort (a ,n +1,high );
}
}
----------------------------------------Code-------------------------------------
平均效率O(nlogn),适用于排序大列表。
此算法的总时间取决于枢纽值的位置;选择第一个元素作为枢纽,可能导致O(n²)的最糟用例效率。若数基本有序,效率反而最差。选项中间值作为枢纽,效率是O(nlogn)。
基于分治法。
七、堆排序
最大堆:后者任一非终端节点的关键字均大于或等于它的左、右孩子的关键字,此时位于堆顶的节点的关键字是整个序列中最大的。
思想:
(1)令i=l,并令temp= kl ;
(2)计算i的左孩子j=2i+1;
(3)若j=n-1,则转(4),否则转(6);
(4)比较kj和kj+1,若kj+1kj,则令j=j+1,否则j不变;
(5)比较temp和kj,若kjtemp,则令ki等于kj,并令i=j,j=2i+1,并转(3),否则转(6)
(6)令ki等于temp,结束。
-----------------------------------------Code---------------------------
void HeapSort(SeqIAst R)
{ //对R[1..n]进行堆排序,不妨用R[0]做暂存单元 int I; BuildHeap(R); //将R[1-n]建成初始堆for(i=n;i1;i--) //对当前无序区R[1..i]进行堆排序,共做n-1趟。{ R[0]=R[1]; R[1]=R[i]; R[i]=R[0]; //将堆顶和堆中最后一个记录交换 Heapify(R,1,i-1); //将R[1..i-1]重新调整为堆,仅有R[1]可能违反堆性质 } } ---------------------------------------Code--------------------------------------
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。
堆排序的最坏时间复杂度为O(nlgn)。堆排序的平均性能较接近于最坏性能。 由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。 堆排序是就地排序,辅助空间为O(1), 它是不稳定的排序方法。
堆排序与直接插入排序的区别:
直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
堆排序可通过树形结构保存部分比较结果,可减少比较次数。
八、拓扑排序
例 :学生选修课排课先后顺序
拓扑排序:把有向图中各顶点按照它们相互之间的优先关系排列成一个线性序列的过程。
方法:
在有向图中选一个没有前驱的顶点且输出
从图中删除该顶点和所有以它为尾的弧
重复上述两步,直至全部顶点均已输出(拓扑排序成功),或者当图中不存在无前驱的顶点(图中有回路)为止。
---------------------------------------Code--------------------------------------
void TopologicalSort()/*输出拓扑排序函数。若G无回路,则输出G的顶点的一个拓扑序列并返回OK,否则返回ERROR*/
{
int indegree[M];
int i,k,j;
char n;
int count=0;
Stack thestack;
FindInDegree(G,indegree);//对各顶点求入度indegree[0....num]
InitStack(thestack);//初始化栈
for(i=0;iG.num;i++)
Console.WriteLine("结点"+G.vertices[i].data+"的入度为"+indegree[i]);
for(i=0;iG.num;i++)
{
if(indegree[i]==0)
Push(thestack.vertices[i]);
}
Console.Write("拓扑排序输出顺序为:");
while(thestack.Peek()!=null)
{
Pop(thestack.Peek());
j=locatevex(G,n);
if (j==-2)
{
Console.WriteLine("发生错误,程序结束。");
exit();
}
Console.Write(G.vertices[j].data);
count++;
for(p=G.vertices[j].firstarc;p!=NULL;p=p.nextarc)
{
k=p.adjvex;
if (!(--indegree[k]))
Push(G.vertices[k]);
}
}
if (countG.num)
Cosole.WriteLine("该图有环,出现错误,无法排序。");
else
Console.WriteLine("排序成功。");
}
----------------------------------------Code--------------------------------------
算法的时间复杂度O(n+e)。
java里,几种排序方法各有什么优缺点?
一、冒泡排序
已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较 a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比较a[3]与a[4],以此类推,最后比较a[n-1]与a[n]的值。这样处理一轮后,a[n]的值一定是这组数据中最大的。再对 a[1]~a[n-1]以相同方法处理一轮,则a[n-1]的值一定是a[1]~a[n-1]中最大的。再对a[1]~a[n-2]以相同方法处理一轮,以此类推。共处理n-1轮后a[1]、a[2]、……a[n]就以升序排列了。
优点:稳定;
缺点:慢,每次只能移动相邻两个数据。
二、选择排序
冒泡排序的改进版。
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
选择排序是不稳定的排序方法。
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果:
①初始状态:无序区为R[1..n],有序区为空。
②第1趟排序
在无序区R[1..n]中选出关键字最小的记录R[k],将它与无序区的第1个记录R[1]交换,使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
③第i趟排序
第i趟排序开始时,当前有序区和无序区分别为R[1..i-1]和R(1≤i≤n- 1)。该趟排序从当前无序区中选出关键字最小的记录 R[k],将它与无序区的第1个记录R交换,使R[1..i]和R分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
这样,n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。
优点:移动数据的次数已知(n-1次);
缺点:比较次数多。
三、插入排序
已知一组升序排列数据a[1]、a[2]、……a[n],一组无序数据b[1]、 b[2]、……b[m],需将二者合并成一个升序数列。首先比较b[1]与a[1]的值,若b[1]大于a[1],则跳过,比较b[1]与a[2]的值,若b[1]仍然大于a[2],则继续跳过,直到b[1]小于a数组中某一数据a[x],则将a[x]~a[n]分别向后移动一位,将b[1]插入到原来 a[x]的位置这就完成了b[1]的插入。b[2]~b[m]用相同方法插入。(若无数组a,可将b[1]当作n=1的数组a)
优点:稳定,快;
缺点:比较次数不一定,比较次数越少,插入点后的数据移动越多,特别是当数据总量庞大的时候,但用链表可以解决这个问题。
三、缩小增量排序
由希尔在1959年提出,又称希尔排序(shell排序)。
已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。发现当n不大时,插入排序的效果很好。首先取一增量d(dn),将a[1]、a[1+d]、a[1+2d]……列为第一组,a[2]、a[2+d]、 a[2+2d]……列为第二组……,a[d]、a[2d]、a[3d]……列为最后一组以次类推,在各组内用插入排序,然后取d'd,重复上述操作,直到d=1。
优点:快,数据移动少;
缺点:不稳定,d的取值是多少,应取多少个不同的值,都无法确切知道,只能凭经验来取。
四、快速排序
快速排序是目前已知的最快的排序方法。
已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先任取数据 a[x]作为基准。比较a[x]与其它数据并排序,使a[x]排在数据的第k位,并且使a[1]~a[k-1]中的每一个数据a[x],a[k+1]~a[n]中的每一个数据a[x],然后采用分治的策略分别对a[1]~a[k-1]和a[k+1]~a[n] 两组数据进行快速排序。
优点:极快,数据移动少;
缺点:不稳定。
五、箱排序
已知一组无序正整数数据a[1]、a[2]、……a[n],需将其按升序排列。首先定义一个数组x[m],且m=a[1]、a[2]、……a[n],接着循环n次,每次x[a]++.
优点:快,效率达到O(1)
缺点:数据范围必须为正整数并且比较小
六、归并排序
归并排序是多次将两个或两个以上的有序表合并成一个新的有序表。最简单的归并是直接将两个有序的子表合并成一个有序的表。
归并排序是稳定的排序.即相等的元素的顺序不会改变.如输入记录 1(1) 3(2) 2(3) 2(4) 5(5) (括号中是记录的关键字)时输出的 1(1) 2(3) 2(4) 3(2) 5(5) 中的2 和 2 是按输入的顺序.这对要排序数据包含多个信息而要按其中的某一个信息排序,要求其它信息尽量按输入的顺序排列时很重要.这也是它比快速排序优势的地方.
java排序,效率高的是哪种排序方法
和所有其他语言是一样的。应该还是快速排序效率最高。
public static void bubbleSort(int a[]) {
int len = a.length;
for (int i = 0; i len - 1; i++) {
for (int j = 0; j len - 1 - i; j++) {
if (a[j] a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
public static void selectSort(int a[]) {
int temp = 0;
int len = a.length;
for (int i = 0; i len - 1; i++) {
int min = a[i];
int index = i;
for (int j = i + 1; j len; j++) {
if (min a[j]) {
min = a[j];
index = j;
}
}
temp = a[i];
a[i] = a[index];
a[index] = temp;
}
}
public static void insertSort(int a[]) {
int len = a.length;
for (int i = 1; i len; i++) {
int temp = a[i];// 待插入的值
int index = i;// 待插入的位置
while (index 0 a[index - 1] temp) {
a[index] = a[index - 1];// 待插入的位置重新赋更大的值
index--;// 位置往前移
}
a[index] = temp;
}
}
public static int partition(int a[], int low, int height) {
int key = a[low];
while (low height) {
while (low height a[height] = key)
height--;
a[low] = a[height];
while (low height a[low] = key)
low++;
a[height] = a[low];
}
a[low] = key;
return low;
}
public static void quickSort(int a[], int low, int height) {
if (low height) {
int result = partition(a, low, height);
quickSort(a, low, result - 1);
quickSort(a, result + 1, height);
}
}
测试结果
------------------------------------------
测试数据10000
冒泡排序:120ms
选择排序:32ms
插入排序:20ms
快速排序:7ms
------------------------------------------
测试数据100000
冒泡排序:13098ms
选择排序:2334ms
插入排序:1264ms
快速排序:23ms
效率差距很大啊!!!!
Java中冒泡排序和选择排序哪一个性能更高一点呢?
一般来说选择比冒泡效率高;
冒泡排序在内循环交换,选择排序在外循环交换,效率差也就在这个交换次数上,毕竟O(n)O(n^2)。如果数组完全有序,冒泡内循环的交换一次都不会执行,而选择排序每次还要和本身交换一次,此时冒泡效率高。但这种情况极少,所以从算法的角度看,选择优于冒泡。
java性能排序的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java性能权威指南 豆瓣、java性能排序的信息别忘了在本站进行查找喔。
发布于:2022-12-05,除非注明,否则均为
原创文章,转载请注明出处。