之前总结过常见排序算法的时间复杂度、空间复杂度、是否稳定等特性,现将代码补上。
代码:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication20;
import java.util.Arrays;
/**
*
* @author cdxxs
*/
public class JavaApplication20 {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int[] arr ={30, 2, 10, -10, 23, 15};
JavaApplication20 demo = new JavaApplication20();
System.out.println(Arrays.toString(arr));
//demo.bubblesort(arr);
//demo.bubblesort1(arr);
//demo.selectsort(arr);
//demo.insertsort1(arr);
//demo.insertsort2(arr);
//demo.mergesort(arr, 0, arr.length-1);
//demo.quicksort(arr, 0, arr.length-1);
//demo.shellsort1(arr);
//demo.shellsort2(arr);
System.out.println(Arrays.toString(arr));
}
//交换
public void swap(int[] arr, int i, int j){
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
//冒泡排序O(n^2) 最好O(n) 空间复杂度O(n) 稳定
public void bubblesort(int[] arr){
for(int i = 0; i < arr.length-1; i++)
for(int j = 0; j < arr.length-1-i; j++)
if(arr[j] > arr[j+1])
swap(arr, j, j+1);
}
//冒泡排序优化,设置标志位,如果经过一次冒泡排序没有交换元素,那么直接返回,如果交换了,那么继续冒泡排序
public void bubblesort1(int[] arr){
int flag = 0;
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr.length-1; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
flag = 1;//表示已经交换了
}
}
//如果flag==0,说明已经排好序了,那么直接返回
if(flag == 0)
return ;
flag = 0;
}
}
//选择排序O(n^2) O(1) 不稳定:2 2 2 1
public void selectsort(int[] arr){
for(int i = 0; i < arr.length-1; i++)
for(int j = i+1; j < arr.length; j++)
if(arr[i] > arr[j])
swap(arr, i, j);
}
//插入排序O(n^2) 最好O(n)排好序 空间O(1) 稳定
public void insertsort1(int [] arr){
//第一个元素是有序序列,从第二个数字开始,对每个数字进行插排,从后向前遍历排序序列,插入合适的位置
for(int i = 1; i < arr.length; i++){
int tmp = arr[i];
int j = i-1;
while(j >= 0 && arr[j] > tmp){
arr[j+1] = arr[j];
j--;
}
arr[j+1] = tmp;
}
}
//插入排序优化
public void insertsort2(int[] arr){
for(int i = 1; i < arr.length; i++){
for(int j = i-1; j >= 0; j--){
if(arr[j] > arr[j+1])
swap(arr, j, j+1);
else
break;
}
}
}
//希尔排序 O(nlogn) O(1) 不稳定:5 1 1 2,tag = 2
public void shellsort1(int[] arr){
int gap = arr.length;
while(gap > 1){
gap = gap/3+1;
for(int i = gap; i < arr.length; i++){
int tmp = arr[i];
int j = i-gap;
while(j >= 0 && arr[j] > tmp){
arr[j+gap] = arr[j];
j -= gap;
}
arr[j+gap] = tmp;
}
}
}
//希尔排序优化
public void shellsort2(int[] arr){
int gap = arr.length;
while(gap > 1){
gap = gap/3+1;
for(int i = gap; i < arr.length; i++){
for(int j = i-gap; j >= 0; j -= gap){
if(arr[j] > arr[j+gap])
swap(arr, i, j+gap);
else
break;
}
}
}
}
//快速排序 O(nlogn)最好,每次划分都能均匀地划分成两份 O(n^2)最差,对应已经排好序的序列 空间复杂度是O(logn)~O(n),和具体的划分方式有关 不稳定:4 3 3 3 1
public void quicksort(int[] arr, int start, int end){
if(arr == null || start < 0 || end >= arr.length || start > end)
throw new IllegalArgumentException("illegal parameters");
int key = arr[start];
int i = start;
int j = end;
while(i < j){
//j从后向前遍历,找比其小的数字
while(i < j && arr[j] >= key)
j--;
//i从前向后遍历,找比其大的数字
while(i < j && arr[i] <= key)
i++;
if(i == j)
{
swap(arr, i, start);//找到了key的位置
break;
}
swap(arr, i, j);
}
//如果左边还有待排序数字,递归进行快速排序
if(start < i)
quicksort(arr, start, i-1);
//如果右边还有待排序数字,递归进行快速排序
if(i < end)
quicksort(arr, i+1, end);
}
//归并排序 O(nlogn) O(n)空间复杂度 稳定
public void mergesort(int[] arr, int start, int end){
if(arr == null || start < 0 || end >= arr.length || start > end)
throw new IllegalArgumentException("illegal parameters");
if(start < end){
int mid = (start+end)/2;
mergesort(arr, start, mid);
mergesort(arr, mid+1, end);
merge(arr, start, mid, end);//将数组合并
}
}
//合并两个数组
public void merge(int[] arr, int start, int mid, int end){
int[] tmp = new int[end-start+1];//定义临时数组,存储排好序的数组
int i = start, j = mid+1, k = 0;//定义三个变量,分别用于遍历前半个数组,后半个数组,以及临时数组
while(i <= mid && j <= end){
if(arr[i] < arr[j])
tmp[k++] = arr[i++];
else
tmp[k++] = arr[j++];
}
//如果i还没遍历结束
while(i <= mid)
tmp[k++] = arr[i++];
while(j <= end)
tmp[k++] = arr[j++];
//重构数组
for(i = 0; i < tmp.length; i++)
arr[i+start] = tmp[i];
}
}