冒泡排序
最坏和平均情况时间复杂度O(n^2),最好情况只扫描一次发现以是顺序排列,时间复杂度为O(n) 空间复杂度O(1) 两个元素比较后决定是否换位置,不会改变原来排序的顺序因此为稳定排序 适用于数据量少和已经部分数据排过序
public static void bubble ( int [ ] arr) {
int len = arr. length;
int temp;
int flag;
for ( int i = len - 1 ; i > 0 ; -- i) {
flag = 0 ;
for ( int j = 0 ; j < i; ++ j) {
if ( arr[ j] > arr[ j + 1 ] ) {
temp = arr[ j] ;
arr[ j] = arr[ j + 1 ] ;
arr[ j + 1 ] = temp;
++ flag;
}
}
if ( flag == 0 ) {
break ;
}
}
}
选择排序
最坏、最好和平均情况都需要找到最大值或最小值,时间复杂度O(n^2), 空间复杂度O(1) 最大或最小值直接与前方未排序的值交换,排序顺序可能被改变,因此不是稳定排序 适用于数据量少和已经部分数据排过序
public static void selectSort ( int [ ] arr) {
int smallIndex, small, temp;
for ( int i = 0 ; i < arr. length - 1 ; i++ ) {
small = arr[ i] ;
smallIndex = i;
for ( int j = i + 1 ; j < arr. length; j++ ) {
if ( small > arr[ j] ) {
small = arr[ j] ;
smallIndex = j;
}
}
if ( smallIndex != i) {
temp = arr[ i] ;
arr[ i] = arr[ smallIndex] ;
arr[ smallIndex] = temp;
}
}
}
插入排序
最坏和平均情况时间复杂度O(n^2),最好情况时间复杂度为O(n) 空间复杂度O(1) 两个元素比较后决定是否换位置,不会改变原来排序的顺序因此为稳定排序 适用于大部分数据已经排过序的情况 插入排序会造成数据的大量搬移,建议在链表上使用
public static void insert ( int [ ] arr) {
int len = arr. length;
int temp, index;
for ( int i = 1 ; i < len; ++ i) {
temp = arr[ i] ;
index = i - 1 ;
while ( index >= 0 && temp < arr[ index] ) {
arr[ index + 1 ] = arr[ index] ;
-- index;
}
arr[ index + 1 ] = temp;
}
}
希尔排序
在插入排序的基础上进行,将数据区分成特定间隔的几个小区块,以选择排序排完区块内的数据后再渐渐减少间隔的距离 任何情况下时间复杂度为O(n^(3/2)) 空间复杂度O(1) 跟插入排序一样为稳定排序 适用于大部分数据都已排序的情况
public static void shell ( int [ ] arr) {
int len = arr. length;
int temp, index;
int jump = len/ 2 ;
while ( jump != 0 ) {
for ( int i = jump; i < len; ++ i) {
temp = arr[ i] ;
index = i - jump;
while ( index >= 0 && temp < arr[ index] ) {
arr[ index + jump] = arr[ index] ;
index -= jump;
}
arr[ index + jump] = temp;
}
jump /= 2 ;
}
}
快速排序
最好和平均情况下,时间复杂度为O(nlog2n),最快情况下为O(n^2) 最好情况下,空间复杂度为O(log2n),最坏情况为O(n) 不是稳定排序 平均运行速度最快
public static void quick ( int [ ] arr, int begin, int end) {
if ( begin > end)
return ;
int tmp = arr[ begin] ;
int i = begin;
int j = end;
while ( i != j) {
while ( arr[ j] >= tmp && j > i)
j-- ;
while ( arr[ i] <= tmp && j > i)
i++ ;
if ( j > i) {
int t = arr[ i] ;
arr[ i] = arr[ j] ;
arr[ j] = t;
}
}
arr[ begin] = arr[ i] ;
arr[ i] = tmp;
quick ( arr, begin, i- 1 ) ;
quick ( arr, i+ 1 , end) ;
}
合并排序
n个数据需要log2n次处理,每次处理的时间复杂度为O(n),所以最好、最坏以及平均情况的时间复杂度均为O(nlog2n) 需要n个额外空间暂存数据,空间复杂度为O(n) 稳定排序算法
public static void merge ( int [ ] arr, int [ ] temp, int start, int end) {
if ( start >= end) {
return ;
}
int middle = start + ( end - start) / 2 ;
int start1 = start, end1 = middle;
int start2 = middle + 1 , end2 = end;
int index = start;
merge ( arr, temp, start1, end1) ;
merge ( arr, temp, start2, end2) ;
while ( start1 <= end1 && start2 <= end2) {
temp[ index++ ] = arr[ start1] > arr[ start2] ? arr[ start2++ ] : arr[ start1++ ] ;
}
while ( start1 <= end1) {
temp[ index++ ] = arr[ start1++ ] ;
}
while ( start2 <= end2) {
temp[ index++ ] = arr[ start2++ ] ;
}
for ( int i = start; i <= end; i++ ) {
arr[ i] = temp[ i] ;
}
}
基数排序法
所有情况下,时间复杂度为O(nlogp k),k是原始数据的最大值 空间复杂度为O(np),p指字符数,最大值的位数 稳定排序算法
public static void radix ( int [ ] arr) {
int len = arr. length;
int bit = maxBit ( arr) ;
int [ ] count = new int [ 10 ] ;
int [ ] temp = new int [ len] ;
int k;
int m_radix = 1 ;
for ( int i = 1 ; i <= bit; i++ ) {
for ( int u = 0 ; u < 10 ; u++ ) {
count[ u] = 0 ;
}
for ( int j = 0 ; j < len; j++ ) {
k = arr[ j] / m_radix % 10 ;
++ count[ k] ;
}
for ( int s = 1 ; s < 10 ; s++ ) {
count[ s] += count[ s - 1 ] ;
}
for ( int n = len - 1 ; n >= 0 ; n-- ) {
k = arr[ n] / m_radix % 10 ;
temp[ count[ k] - 1 ] = arr[ n] ;
-- count[ k] ;
}
for ( int m = 0 ; m < len; m++ ) {
arr[ m] = temp[ m] ;
}
m_radix *= 10 ;
}
}
public static int maxBit ( int [ ] arr) {
int max = arr[ 0 ] ;
int bit = 1 ;
for ( int i = 1 ; i < arr. length; i++ ) {
max = max < arr[ i] ? arr[ i] : max;
}
while ( max >= 10 ) {
max /= 10 ;
++ bit;
}
return bit;
}