java八大常见排序

冒泡排序

相邻两个元素两两进行比较然后交换位置
for(int i = 1; i < arr.length; i++){ // 控制轮数
for(int j = 1; j <= arr.length - i; j++){ // 控制每一轮的次数
if(arr[j - 1] > arr[j]){
int temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temmp;
}
}
}

在这里插入图片描述

选择排序

拿第一位和后面每一位比较,后一个比前一个大则交换顺序
for(int i = 1; i < arr.length ; i++){ // 控制轮数
for(int j = i; j < arr.length; j++){ // 控制的要比较的下标
if(arr[i - 1] > arr[j]){
int temp = arr[i - 1];
arr[i - 1] = arr[j];
arr[j] = temp;
}
}
}
在这里插入图片描述

插入排序

第一个和第二个比较,第一个大于第二个就换位置,第一个小于第二个就不换位置,然后其他数字从后往前找合适的位置插入
int size=numbers.lenth
int temp=0;
int j=0;
for(int i=0;i<size;i++){
temp=numbers[i];
for(j=i;j>0&&temp<numbers[j-1];j++){
numbers[j]=numbers[j-1];
}
numbers[j]=temp;
}
在这里插入图片描述
快速排序:选择第一个数字作为中轴,和最后一个数字比,后一个比前一个小,则交换,后一个比前一个大则不交换,第一次划分之后左边的数字均是小于中轴的,右边的数字均是大于中轴的。
arr[]={10,5,3,1,7,2,8};
_left=0;
_right=arr.lenth-1
public void quickSort(int arr[],int _left,int _right){
int left=_left;
int right=_right;
int temp=0;
if(left<=right){//待排序的元素至少有两个的情况
temp=arr[left];//待排序的第一个元素作为基准元素
while(left!=right){//从左右两边交替扫描,直到left=right
while(right>left&&arr[right]>=temp){
right–;//从右往左扫描,找到第一个比基准元素小的元素
}
arr[left]=arr[right];//找到这个元素arr[right]后与arr[left]交换
while(left<right&&arr[left]<=temp){
left++;//从左往右扫描,找到第一个比基准元素大的元素
}
arr[right]=arr[left];//找到这个元素arr[left]后与arr[right]交换
arr[right]=temp;//基准元素归为
quickSort(arr,_left,left-1);//对基准元素左边的元素进行递归排序
quickSort(arr,right+1,_right);//对基准元素右边的元素进行递归排序
}
}
}
在这里插入图片描述

希尔排序

先看有多少个数,再根据数字确定增量间隔h=3h+1,根据增量间隔,分割,进行比较,小在前,大在后,当增量间隔为1时采用插入排序
int j = 0;
int temp = 0;
for (int increment = data.length / 2; increment > 0; increment /= 2)
{
for (int i = increment; i < data.length; i++)
{
temp = data[i];
for (j = i; j >= increment; j -= increment)
{
if(temp > data[j - increment])//如想从小到大排只需修改这里
{
data[j] = data[j - increment];
}
else
{
break;
}
}
data[j] = temp;
}
}

increment/3 + 1

在这里插入图片描述

归并排序

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列
在这里插入图片描述

堆排序

初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个 堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对 它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。
在这里插入图片描述
在这里插入图片描述

总结一下:


快速排序(QuickSort)

快速排序是一个就地排序,分而治之,大规模递归的算法。从本质上来说,它是归并排序的就地版本。快速排序可以由下面四步组成。

如果不多于1个数据,直接返回。

一般选择序列最左边的值作为支点数据。

将序列分成2部分,一部分都大于支点数据,另外一部分都小于支点数据。

对两边利用递归排序数列。

快速排序比大部分排序算法都要快。尽管我们可以在某些特殊的情况下写出比快速排序快的算法,但是就通常情况而言,没有比它更快的了。快速排序是递归的,对于内存非常有限的机器来说,它不是一个好的选择。

归并排序(MergeSort)

归并排序先分解要排序的序列,从1分成2,2分成4,依次分解,当分解到只有1个一组的时候,就可以排序这些分组,然后依次合并回原来的序列中,这样就可以排序所有数据。合并排序比堆排序稍微快一点,但是需要比堆排序多一倍的内存空间,因为它需要一个额外的数组。

堆排序(HeapSort)

堆排序适合于数据量非常大的场合(百万数据)。

堆排序不需要大量的递归或者多维的暂存数组。这对于数据量非常巨大的序列是合适的。比如超过数百万条记录,因为快速排序,归并排序都使用递归来设计算法,在数据量非常大的时候,可能会发生堆栈溢出错误。

堆排序会将所有的数据建成一个堆,最大的数据在堆顶,然后将堆顶数据和序列的最后一个数据交换。接下来再次重建堆,交换数据,依次下去,就可以排序所有的数据。

插入排序(InsertSort)

插入排序通过把序列中的值插入一个已经排序好的序列中,直到该序列的结束。插入排序是对冒泡排序的改进。它比冒泡排序快2倍。一般不用在数据大于1000的场合下使用插入排序, 或者重复排序超过200数据项的序列。

冒泡排序(BubbleSort)

冒泡排序是最慢的排序算法。在实际运用中它是效率最低的算法。它通过一趟又一趟地比较数组中的每一个元素,使较大的数据下沉,较小的数据上升。它是O(n^2)的算法。

交换排序(ExchangeSort)和选择排序(SelectSort)

这两种排序方法都是交换方法的排序算法,效率都是 O(n2)。在实际应用中处于和冒泡排序基本相同的地位。它们只是排序算法发展的初级阶段,在实际中使用较少。

基数排序(RadixSort)

基数排序和通常的排序算法并不走同样的路线。它是一种比较新颖的算法,但是它只能用于整数的排序,如果我们要把同样的办法运用到浮点数上,我们必须了解浮点数的存储格式, 并通过特殊的方式将浮点数映射到整数上,然后再映射回去,这是非常麻烦的事情,因此, 它的使用同样也不多。而且,最重要的是,这样算法也需要较多的存储空间。

总结

下面是一个总的表格,大致总结了我们常见的所有的排序算法的特点。

排序法 平均时间 最差情形 稳定度 额外空间 备注
冒泡 O(n2) O(n2) 稳定 O(1) n小时较好
交换 O(n2) O(n2) 不稳定 O(1) n小时较好
选择 O(n2) O(n2) 不稳定 O(1) n小时较好
插入 O(n2) O(n2) 稳定 O(1) 大部分已排序时较好
基数 O(logRB) O(logRB) 稳定 O(n) B是真数(0-9),R是基数(个十百)
Shell O(nlogn) O(ns) 1<s<2 不稳定 O(1) s是所选分组
快速 O(nlogn) O(n2) 不稳定 O(nlogn) n大时较好
归并 O(nlogn) O(nlogn) 稳定 O(1) n大时较好
O(nlogn) O(nlogn) 不稳定 O(1) n大时较好

猜你喜欢

转载自blog.csdn.net/qq_42306104/article/details/85762126