时间复杂度为O(n^2)的:
插入、选择(不稳定)、冒泡
时间复杂度为O(nlogn)的:
堆(不稳定),快速(不稳定),归并
一、插入排序
将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换,直到全部元素都比较过为止。
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
public static void 插入排序(int[] arr)
{
for(int i=0;i<arr.length-1;i++)
{
for(int j=i+1;j>0;j--)
{
if(arr[j-1]>arr[j])
{
swap(arr,j-1,j);
}
}
}
System.out.println(Arrays.toString(arr));
} O(n^2) 稳定
二、选择排序
每次都在剩余的数组中找到最小值,把找到的最小值和头节点值交换,重复arr.length轮
最坏情况每次都必须换一下,都坏O(n^2)
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
public static void 选择排序(int[] arr)
{
for(int i=0;i<arr.length-1;i++)
{
int minIndex=i;
for(int j=i+1;j<arr.length;j++)
{
if(arr[j]<arr[minIndex])
{
minIndex=j;
}
}
if(minIndex != i)
{
swap(arr,minIndex,i);
}
}
System.out.println(Arrays.toString(arr));
} O(n^2), 不稳定
序列5 8 5 2 9, 这个在执行选择排序的时候,第一遍,肯定会将array[0]=5,交换到2所在的位置,也就是 2 8 5 5 9,那么很显然,之后的排序我们就会发现,array[2]中的5会出现在原先的array[0]之前,所以选择排序不是一个稳定的排序
三、冒泡排序
不解释,你学的第一个算法
public static void 冒泡排序(int[] arr)
{
for(int i=arr.length-1;i>0;i--) //每次需要排序的长度
{
for(int j=0;j<i;j++)
{
if(arr[j]>arr[j+1])
swap(arr,j,j+1);
}
}
System.out.println(Arrays.toString(arr));
} O(n^2) , 稳定
四、快速排序
递归的思想,每次选择一个元素,左边的数组都小于选定元素,右边的数组都大于选定元素;
public static void 快速排序(int[] arr,int low,int high)
{
if(arr.length<=0) return;
if(low>=high) return;
int left = low;
int right = high;
int temp = arr[low];
while(left<right)
{
while(left<right && arr[right]>temp)
right--;
while(left<right && arr[left]<=temp)
left++;
swap(arr,left,right);
}
swap(arr,left,low);
System.out.println("Sorting:" + Arrays.toString(arr));
快速排序(arr,low,left-1);
快速排序(arr,left+1,high);
}
https://www.youtube.com/watch?v=T258-Umoz9A
O(nlogn) 不稳定
五、归并排序
递归版本:
public static void mergeSort1(int[] arr,int l, int r)
{
if(l<r)
{
int m=l+(r-l)/2;
mergeSort1(arr,l,m);
mergeSort1(arr,m+1,r);
merge(arr,l,m,r);
}
}
public static void merge(int[] arr,int l,int m,int r)
{
int n1 = m-l+1; //左子数组的长度
int n2=r-m; //右子数组的长度
int[] L=new int[n1];
int[] R=new int[n2];
for(int i=0;i<n1;i++)
L[i] = arr[l+i];
for(int j=0;j<n2;j++)
R[j] = arr[m+1+j];
int i=0,j=0,k=l;
while(i<n1 && j<n2)
{
if(L[i]<=R[j])
{
arr[k] = L[i];
i++;
}else{
arr[k]=R[j];
j++;
}
k++;
}
while(i<n1)
{
arr[k] = L[i]; k++; i++;
}
while(j<n2)
{
arr[k] = R[j];k++; j++;
}
} O(nlogn) 稳定
六、堆排序
堆排序的思想跟选择排序类似,但是如何快速找到最小(最大)元素?——》最大最小堆
public static void heapify(int[] arr,int n,int i)
{
int largest = i;
int l=2*i+1;//左子树的位置
int r=2*i+2;//右子树的位置
if(l<n && arr[l]>arr[largest])
largest=l;
if(r<n && arr[r]>arr[largest])
largest=r;
if(largest != i)
{
swap(arr,i,largest);
heapify(arr,n,largest);
}
}
public static void 堆排序(int[] arr)
{
int n=arr.length;
for(int i=n/2-1;i>=0;i--)
heapify(arr,n,i);
for(int i=n-1;i>=0;i--)
{
swap(arr,0,i);
heapify(arr,i,0);
}
} O(nlogn) 不稳定
堆分为大顶堆和小顶堆;大顶堆:父节点的值一定大于它的左右节点的值。
堆排序的过程:
1.构造一个大顶堆,取堆顶数字;
2. 再将剩下的数字构造一个大顶堆,取堆顶的数字
3.重复上面的操作,直到取完堆中的数字,最终得到一个从大到小排序的序列

京公网安备 11010502036488号