二分查找
时间复杂度:O(log2n)
public class Hello {
public static void main ( String [ ] args) {
int [ ] arr = new int [ ] { 1 , 2 , 3 , 5 , 7 , 12 } ;
int target = 12 ;
int res;
res = findIndex ( arr, target) ;
System . out. println ( res) ;
}
public static int findIndex ( int [ ] arr, int target) {
int left = 0 ;
int right = arr. length- 1 ;
int mid;
while ( left <= right) {
mid = ( left + right) / 2 ;
if ( arr[ mid] == target) {
return mid;
} else if ( arr[ mid] < target) {
left = mid + 1 ;
} else if ( arr[ mid] > target) {
right = mid - 1 ;
}
}
return - 1 ;
}
}
冒泡排序
原理:依次比较相邻的两个数,大泡往后面冒,小泡往前面冒
最差时间复杂度:O(n^2)
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 ] ) {
int change = arr[ j] ;
arr[ j] = arr[ j+ 1 ] ;
arr[ j+ 1 ] = change;
}
}
}
可优化:新增flag变量,当数组本身已经排好序时,第一次循环内容未执行,此时flag=1,直接break
int flag = 1 ;
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 ] ) {
int change = arr[ j] ;
arr[ j] = arr[ j+ 1 ] ;
arr[ j+ 1 ] = change;
flag = 0 ;
}
}
if ( flag) break ;
}
选择排序
原理:从0索引处开始,依次和后面每个元素做比较,小的元素往前放,经过一轮比较后,最小的元素就出现在了最小索引处。
时间复杂度:O(n^2)
for ( int i = 0 ; i < arr. length- 1 ; i++ ) {
for ( int j = i; j < arr. length; j++ ) {
if ( arr[ i] > arr[ j] ) {
int t = arr[ i] ;
arr[ i] = arr[ j] ;
arr[ j] = t;
}
}
}
直接插入排序
原理:将一个个记录依次插入到一个长度为m的有序表中,使之仍保持有序。
(即将数组中较小的数往前搬)
for ( int i = 1 ; i < arr. length; i++ ) {
for ( int j = i; j > 0 ; j-- ) {
if ( arr[ j- 1 ] > arr[ j] ) {
int t = arr[ j] ;
arr[ j] = arr[ j- 1 ] ;
arr[ j- 1 ] = t;
}
}
}
希尔排序
原理:又称缩小增量排序。先将原表按增量ht分组,每个子文件按照直接插入法排序。同样,用下一个增量ht/2将文件再分为子文件,再直接插入法排序。直到ht=1时整个文件排好序。
时间复杂度:O(n^(3/2))
int h = arr. length/ 2 ;
while ( h> 0 ) {
for ( int i = h; i < arr. length; i++ ) {
for ( int j = i; j > h- 1 ; j-- ) {
if ( arr[ j- h] > arr[ j] ) {
int t = arr[ j] ;
arr[ j] = arr[ j- h] ;
arr[ j- h] = t;
}
}
}
h /= 2 ;
}
可采用克努特序列选取第一个增量,之后希尔排序时ht=(ht-1)/3
int ht = 1 ;
while ( ht <= arr. length/ 3 ) {
ht = ht * 3 + 1 ;
}
快速排序
原理:分治法:比大小,再分区。从数组中取出一个数作为基准数,然后分区,将比这个数大或等于的数放右边,小于的这个数的放左边,再对左右区间重复此操作,直到各区间只有一个数。(例如体育课快速排队)
方法:挖坑填数法
时间复杂度:O(nlog2n)
public static void quickSort ( int [ ] arr, int start, int end) {
if ( start < end) {
int index = getIndex ( arr, start, end) ;
quickSort ( arr, start, index- 1 ) ;
quickSort ( arr, index+ 1 , end) ;
}
}
public static int getIndex ( int [ ] arr, int start, int end) {
int i = start;
int j = end;
int x = arr[ i] ;
while ( i < j) {
while ( i < j && arr[ j] >= x) {
j-- ;
}
if ( i < j) {
arr[ i] = arr[ j] ;
i++ ;
}
while ( i < j && arr[ i] < x) {
i++ ;
}
if ( i < j) {
arr[ j] = arr[ i] ;
j-- ;
}
}
arr[ i] = x;
return i;
}
归并排序
原理:先将长度为N的数组看成由N个有序的长度为1的数组组成,然后两两归并,得到N/2个长度为2或1的有序子序列,再两两归并,重复归并直到得到一个长度为N的有序序列为止。(2路归并排序)
时间复杂度:O(nlogn)
public static void Sort ( int [ ] arr, int start, int end) {
int mid = ( start + end) / 2 ;
if ( start < end) {
Sort ( arr, start, mid) ;
Sort ( arr, mid+ 1 , end) ;
guibin ( arr, start, mid, end) ;
}
}
public static void guibin ( int [ ] arr, int start, int mid, int end) {
int i = start;
int j = mid + 1 ;
int [ ] temp = new int [ end- start+ 1 ] ;
int k = 0 ;
while ( i <= mid && j <= end) {
if ( arr[ i] <= arr[ j] ) {
temp[ k++ ] = arr[ i] ;
i++ ;
} else {
temp[ k++ ] = arr[ j] ;
j++ ;
}
}
while ( i <= mid) {
temp[ k++ ] = arr[ i++ ] ;
}
while ( j <= end) {
temp[ k++ ] = arr[ j++ ] ;
}
for ( int h= 0 ; h < temp. length; h++ ) {
arr[ h+ start] = temp[ h] ;
}
}
基数排序
原理:先找出数组中最大元素的位数为h,然后新建10个新数组,将原数组中的数字逐一判断个位数k,然后放进对应的第k个新数组中,直到数组为空时,将新数组中从第一个按顺序将元素放进原数组,接着将原数组中的数字逐一判断十位数k,重复上述操作,循环h次,则原数组排序完成。(牺牲空间换取时间)
时间复杂度:O (nlog®m)
public static void Sort ( int [ ] arr) {
if ( arr. length == 0 ) return ;
int max = getMax ( arr) ;
int len = String . valueOf ( max) . length ( ) ;
int [ ] [ ] temp = new int [ 10 ] [ arr. length] ;
int [ ] count = new int [ 10 ] ;
for ( int i = 0 , n = 1 ; i < len; i++ , n*= 10 ) {
for ( int j = 0 ; j < arr. length; j++ ) {
int ys = arr[ j] / n % 10 ;
temp[ ys] [ count[ ys] ++ ] = arr[ j] ;
}
int index = 0 ;
for ( int k = 0 ; k < count. length; k++ ) {
if ( count[ k] != 0 ) {
for ( int h = 0 ; h < count[ k] ; h++ ) {
arr[ index++ ] = temp[ k] [ h] ;
}
count[ k] = 0 ;
}
}
}
}
public static int getMax ( int [ ] arr) {
int max = arr[ 0 ] ;
for ( int i = 1 ; i < arr. length; i++ ) {
if ( max < arr[ i] ) {
max = arr[ i] ;
}
}
return max;
}
堆排序
原理:将待排序序列构造成一个大顶堆,此时整个序列的最大值就是堆顶的根节点,将其与末尾元素进行交换,此时末尾就为最大值,然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值,如此反复执行,使能得到一个有序序列。
时间复杂度:O(nlogn)
public static void Sort ( int [ ] arr) {
if ( arr. length == 0 ) return ;
int start = ( arr. length- 1 ) / 2 ;
for ( int i = start; i >= 0 ; i-- ) {
bigSort ( arr, arr. length, i) ;
}
for ( int i = arr. length- 1 ; i > 0 ; i-- ) {
int t = arr[ 0 ] ;
arr[ 0 ] = arr[ i] ;
arr[ i] = t;
bigSort ( arr, i, 0 ) ;
}
}
public static void bigSort ( int [ ] arr, int size, int index) {
int left = index * 2 + 1 ;
int right = index * 2 + 2 ;
int maxIndex = index;
if ( left < size && arr[ left] > arr[ maxIndex] ) {
maxIndex = left;
}
if ( right < size && arr[ right] > arr[ maxIndex] ) {
maxIndex = right;
}
if ( maxIndex != index) {
int temp = arr[ index] ;
arr[ index] = arr[ maxIndex] ;
arr[ maxIndex] = temp;
bigSort ( arr, size, maxIndex) ;
}
}