排序就是将数组按照递增或者递减的顺序排列起来
直接插入排序
当插入到第i个元素时,前边i-1个元素已经排好了序,只需要将i元素依次与前i-1个元素进行比较,找到合适位置插入进去,原来位置上的元素后移即可。
public void insertSort(int[] array){
for (int i=1;i<array.length;i++){
int tmp=array[i];
int j=i-1;
for (;j>=0;j--){
if (array[j]>tmp){
array[j+1]=array[j];
}else {
break;
}
}
array[j+1]=tmp;
}
}
时间复杂度 最坏:O(n^2) 逆序 最好:O(n) 有序 场景:当数据基本上是有序的时候,使用直接插入排序
希尔排序
先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
public static void shell(int[] array,int gap){
for (int i=gap;i<array.length;i++){
int tmp=array[i];
int j=i-gap;
for (;j>=0;j-=gap){
if (array[j]>tmp){
array[j+gap]=array[j];
}else {
break;
}
}
array[j+gap]=tmp;
}
}
public static void shellSort(int[] array){
int gap=array.length;
while (gap>1){
shell(array,gap);
gap=gap/2;
}
shell(array,1);
}
选择排序
第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零
public static void selectSort(int[] array){
for (int i = 0; i < array.length-1; i++) {
int minIndex=i;
for (int j = i+1; j < array.length; j++) {
if (array[minIndex]>array[j]){
minIndex=j;
}
}
swap(array,i,minIndex);
}
}
public static void swap(int[] array,int i,int j){
int tmp=array[i];
array[i]=array[j];
array[j]=tmp;
}
public static void selectSort2(int[] array){
int left=0;
int right=array.length-1;
while (left<right){
int minIndex=left;
int maxIndex=left;
for (int i = left+1; i <= right ; i++) {
if (array[i]<array[minIndex]){
minIndex=i;
}
if (array[i]>array[maxIndex]){
maxIndex=i;
}
}
swap(array,left,minIndex);
if (left==maxIndex){
maxIndex=minIndex;
}
swap(array,right,maxIndex);
left++;
right--;
}
}
时间复杂度:O(n^2) 空间复杂度:O(1)
堆排序
以升序排序为例,先建立一个大根堆,每次跟堆顶元素进行交换,直到交换完成。
private static void createBigHeap(int[] array){
for (int parent = (array.length-2)/2; parent >= 0; parent--) {
shiftDown(array,parent,array.length);
}
}
public static void heapSort(int[] array){
createBigHeap(array);
int end=array.length-1;
while (end>=0){
swap(array,0,end);
shiftDown(array,0,end);
end--;
}
}
private static void shiftDown(int[] array,int parent,int len){
int child=2*parent+1;
while (child<len){
if (child+1<len && array[child]<array[child+1]){
child++;
}
if (array[child]>array[parent]){
swap(array,child,parent);
parent=child;
child=2*parent+1;
}else {
break;
}
}
}
时间复杂度:O(n*logn) 空间复杂度:O(1)
冒泡排序
从第一位开始进行相邻的两个数的比较,将较大的数放后面,比较完毕之后向后挪一位继续比较下面两个相邻的两个数大小关系,重复此步骤,直到最后一个还没归位的数。
public static void bubbleSort(int[] array){
for (int i = 0; i < array.length-1; i++) {
boolean flg=false;
for (int j = 0; j < array.length-1-i; j++) {
if (array[j]>array[j+1]){
swap(array,j,j+1);
flg=true;
}
}
if (!flg){
break;
}
}
}
冒泡排序 时间复杂度:O(N^2)* 针对优化后的代码,时间复杂度在有序的情况下: O(n) 空间复杂度:0(1)
快速排序
Hoare法
public static int partition(int[] array,int start,int end){
int i=start;
int key=array[start];
while (start<end){
while (start<end && array[end]>=key){
end--;
}
while (start<end && array[start]<=key){
start++;
}
swap(array,start,end);
}
swap(array,start,i);
return start;
}
public static void quick(int[] array,int left,int right){
if (left>=right){
return;
}
int pivot=partition(array,left,right);
quick(array,left,pivot-1);
quick(array,pivot+1,right);
}
public static void quickSort(int[] array){
quick(array,0,array.length-1);
}
挖坑法
public static int partition(int[] array,int start,int end){
int key=array[start];
while (start<end){
while (start<end && array[end]>=key){
end--;
}
array[start]=array[end];
while (start<end && array[start]<=key){
start++;
}
array[end]=array[start];
}
array[start]=key;
return start;
}
前后指针法
public static int partition(int[] array,int start,int end){
int prev=start;
int cur=start+1;
while (cur<=end){
if (array[cur]<array[start] && array[++prev]!=array[cur]){
swap(array,cur,prev);
}
cur++;
}
swap(array,prev,start);
return prev;
}
时间复杂度:O(n*logn) 【理想情况下】 空间复杂度:O(logn)
归并排序
递归法
public static void mergeFunc(int[] array,int left,int right){
if (left>=right){
return;
}
int mid=(left+right)/2;
mergeFunc(array,left,mid);
mergeFunc(array,mid+1,right);
merge(array,left,right,mid);
}
private static void merge(int[] array,int start,int end,int midIndex){
int[] tmpArr=new int[end-start+1];
int k=0;
int s1=start;
int s2=midIndex+1;
while (s1<=midIndex && s2<=end){
if (array[s1]<=array[s2]){
tmpArr[k++]=array[s1++];
}else {
tmpArr[k++]=array[s2++];
}
}
while (s1<=midIndex){
tmpArr[k++]=array[s1++];
}
while (s2<=end){
tmpArr[k++]=array[s2++];
}
for (int i = 0; i < k; i++) {
array[i+start]=tmpArr[i];
}
}
public static void mergeSort(int[] array){
mergeFunc(array,0,array.length-1);
}
时间复杂度:O(n*logn) 空间复杂度:O(n)
非递归法
public static void mergeSort(int[] array){
int gap=1;
while (gap<array.length){
for (int i = 0; i < array.length; i+=2*gap) {
int s1=i;
int e1=s1+gap-1;
if (e1>=array.length){
e1=array.length-1;
}
int e2=e1+gap;
if (e2>=array.length){
e2=array.length-1;
}
merge(array,s1,e2,e1);
}
gap*=2;
}
}