排序算法 | 平均时间复杂度 | 平均空间复杂度 |
---|---|---|
冒泡 | O(n2) | O(1) |
选择 | O(n2) | O(1) |
插入 | O(n2) | O(1) |
希尔 | O(N*logN) | O(1) |
快速 | O(N*logN) | O(logN) ~O(N) |
归并排序 | O(N*logN) | O(m) |
堆 | O(N*logN) | O(1) |
计数排序 | O(m)桶的数量 | |
基数排序 | O(d(n+r)) |
冒泡排序
循环比较相邻元素,经由交换慢慢“浮”到数列的顶端
/**
* 冒泡排序
* 比较相邻的两个数据,如果第二个数小,就交换位置
* 从后向前两两比较,一直到比较最前两个数据
* 设置标志位flag,如果发生了交换flag设置为true,这一轮没有发生交换,说明数据的顺序已经排好
* 平均时间复杂度:O(n2)
* @param arr
*/
public static void BubbleSort(int[] arr){
int temp;
boolean flag;//是否交换的标志
for(int i=0; i<arr.length-1; i++){ //表示趟数,一共arr.length-1次。
flag = false;
for(int j=arr.length-1; j>i; j--){ //一趟冒泡过程
if(arr[j] < arr[j-1]){
temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
flag = true;
}
if(!flag)
{ break;
}
}
}}
选择排序
遍历找到第n个元素最小的值,交换位置
/**
* 遍历找到第n个元素最小的值
* 平均时间复杂度:O(n2)
* @param arr
*/
public static void select_sort(int[] arr){
for (int i =0;i<arr.length -1;i++){ //找到第n个元素最小的值。
int minIndex = i;
for (int j=i;j<arr.length-1;j++){
if(arr[j] < arr[minIndex]){
minIndex = j;
}
}
if(minIndex != i){
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
插入排序
遍历将第n个数插入到前n-1个已排好序的数组的合适位置
/**
* 在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序
* @param arr
*/
public static void insert_sort(int[] arr){
int temp;
for (int i = 0;i<arr.length - 1;i++){ //前i个有序
for (int j = i+1;j > 0;j-- ){
if(arr[j] < arr[j-1]){
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}else {
break;
}
}
}
}
希尔算法
基于步长对插入排序的改进
/**
* 在要排序的一组数中,根据某一增量分为若干子序列,并对子序列分别进行插入排序。
* 基于步长对插入排序的改进
* @param arr
*/
public static void shell_sort(int[] arr){
int temp;
int length = arr.length;
int incre = length;
while (true){
incre = incre/2;
for (int k = 0;k<incre;k++){ //根据增量分为若干子序列
for (int i = k+incre;i<length;i+=incre){
for (int j = i;j>k;j-=incre ){
if(arr[j]<arr[j-incre]){
temp = arr[j-incre];
arr[j-incre] = arr[j];
arr[j] = temp;
}else{
break;
}
}
}
}
if(incre == 1){
break;
}
}
}
快速排序
先找左边元素中轴,再用分治法,分别对这两个独立的数组进行排序
/**
* 挖坑填数
* 先从数列中取出一个数作为key值;
* 将比这个数小的数全部放在它的左边,大于或等于它的数全部放在它的右边;
* 对左右两个小数列重复第二步,直至各区间只有1个数。
* @param arr
* @param l
* @param r
*/
public static void quickSort(int[] arr,int l,int r){
if(l >= r){
return;
}
int key = arr[l];
int i = l;
int j = r;
while (i<j){
while (i < j && arr[j] >= key){
j--;
}
if(i<j){
arr[i] = arr[j];
i++;
}
while (i < j && arr[i] <= key){
i++;
}
if(i < j){
arr[j] = arr[i];
}
}
arr[i] = key;
quickSort(arr,l,i-1);
quickSort(arr,i+1,r);
}
归并排序
先分解队列,在将两个(或两个以上)有序表合并成一个新的有序表
/**
* 先递归的分解数列,再合并数列就完成了归并排序。
* @param arr
* @param l
* @param r
* @param temp
*/
public static void merge_sort(int[] arr,int l,int r,int[] temp){
if(l<r){
int mid = (l+r)/2;
merge_sort(arr,l,mid,temp);
merge_sort(arr,mid+1,r,temp);
mergeArr(arr,l,r,mid,temp);
}
}
public static void mergeArr(int[] arr, int l, int r, int mid, int[] temp){
int i = l;
int j = r;
int ml = mid;
int mr = mid+1;
int k = 0;
while (i <= ml && mr <= j){
if (arr[i] < arr[mr]){
temp[k] = arr[i];
i++;
}else {
temp[k] = arr[mr];
mr++;
}
k++;
}
while (i<= ml){
temp[k] = arr[i];
i++;
k++;
}
while (mr <=r){
temp[k] = arr[mr];
mr++;
k++;
}
for(int ii=0;ii<k;ii++){
arr[l + ii] = temp[ii];
}
}
堆排序
一是建立堆,二是堆顶与堆的最后一个元素交换位置
public static void heap_sort(int[] arr){
int lengh = arr.length;
int temp = 0;
//初始化最小堆
initMinHeap(arr,lengh);
for (int i = lengh-1;i>0;i--){
temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
MinHeapFixdown(arr,0,i);
}
}
private static void initMinHeap(int[] arr,int length){
for(int i=(length-1)/2 ; i>=0 ; i--){
MinHeapFixdown(arr,i,length);
}
}
private static void MinHeapFixdown(int[] arr,int i,int lenght){
int j = 2*i +1;
int temp;
while (j<lenght){
if(j+1 < lenght && arr[j] < arr[j+1]){
j++;
}
if(arr[j] > arr[i]){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
i = j;
j = 2*i+1;
}
}