1、排序算法
1.1 快速排序
快排的时间复杂度是O(nlogn)
其实现思想就是随机找到一个中间值 小于这个值得放左边 大于这个值得放右边
然后大于这个值得半部分和小于这个值得半部分分别递归
直到全部排完
jdk1.8中的Arrays.sort()的排序方法就是使用的快排 当数据量大于47的时候采用快排
小于47的时候使用插排
实现代码:
public class QuickSort {
public static void quickSort ( int [ ] arr , int left, int right) {
if ( left < right) {
swap ( arr, left + ( ( right - left ) >> 1 ) , right) ;
int [ ] p = partition ( arr, left, right) ;
quickSort ( arr, left, p[ 0 ] - 1 ) ;
quickSort ( arr, p[ 1 ] + 1 , right) ;
}
}
private static int [ ] partition ( int [ ] arr, int left, int right) {
int less = left - 1 ;
int more = right;
while ( left < more) {
if ( arr[ left] < arr[ right] ) {
swap ( arr, ++ less, left++ ) ;
} else if ( arr[ left] > arr[ right] ) {
swap ( arr, -- more, left) ;
} else {
left++ ;
}
}
swap ( arr, more, right) ;
return new int [ ] { less + 1 , more} ;
}
private static void swap ( int [ ] arr, int j, int i) {
int temp = arr[ j] ;
arr[ j] = arr[ i] ;
arr[ i] = temp;
}
public static void main ( String[ ] args) {
int [ ] arr = ArrayUtils. getArray ( 10 , 20 ) ;
ArrayUtils. printArray ( arr) ;
quickSort ( arr, 0 , arr. length - 1 ) ;
System. out. println ( ) ;
ArrayUtils. printArray ( arr) ;
}
}
1.2 堆排
堆排就是建立一个抽象意义上的堆、算法上的堆是一个完全二叉树结构。
其底层是一个数组,一个节点的左孩子是 index * 2 + 1
右孩子是 index * 2 + 2
父亲节点是 (index - 1)/ 2
大根堆就是在以当前节点作为一个树的时候、此节点是整棵树中的最大值(小根堆反之)。
堆排序主要分为两步:
1、建立一个堆,然后每次将堆顶的元素和最后一层的最后一个元素交换。
2、然后将堆顶的元素进行下沉,直到以他为树的所有节点中只有他最大(小)。
堆排时间复杂度是严格意义上的O(nlogn) 空间复杂度是O(1)
堆排的应用如优先级队列等。
public class HeapSort {
public static void heapSort ( int [ ] arr) {
if ( arr == null || arr. length < 2 ) {
return ;
}
for ( int i = 0 ; i < arr. length ; i++ ) {
heapInsert ( arr, i) ;
}
int size = arr. length;
swap ( arr, 0 , -- size) ;
while ( size > 0 ) {
heapify ( arr, 0 , size) ;
swap ( arr, 0 , -- size) ;
}
}
private static void heapify ( int [ ] arr, int index, int size) {
int left = index * 2 + 1 ;
while ( left < size) {
int largest = left + 1 < size && arr[ left + 1 ] > arr[ left] ? left + 1 : left;
largest = arr[ largest] > arr[ index] ? largest : index;
if ( largest == index) {
break ;
}
swap ( arr, largest, index) ;
index = largest;
left = index * 2 + 1 ;
}
}
private static void heapInsert ( int [ ] arr, int index) {
while ( arr[ index] > arr[ ( index - 1 ) / 2 ] ) {
swap ( arr, index, ( index - 1 ) / 2 ) ;
index = ( index - 1 ) / 2 ;
}
}
private static void swap ( int [ ] arr, int j, int i) {
int temp = arr[ j] ;
arr[ j] = arr[ i] ;
arr[ i] = temp;
}
public static void main ( String[ ] args) {
int [ ] arr = ArrayUtils. getArray ( 10 , 20 ) ;
ArrayUtils. printArray ( arr) ;
heapSort ( arr) ;
System. out. println ( ) ;
ArrayUtils. printArray ( arr) ;
}
}
1.3 归并排序
归并排序就是将数组递归的两两划分、然后再合并的过程 在合并的过程中排好序
递的过程就是将数组从中间分成两半、直到数组大小为1,
归的过程就是讲两部分合成成一个部分,合成的过程中排好序
时间复杂度O(nlogn)
public class MergeSort {
public static void mergeSort ( int [ ] arr) {
if ( arr. length < 2 || arr == null) {
return ;
}
mergeSort ( arr, 0 , arr. length - 1 ) ;
}
private static void mergeSort ( int [ ] arr, int left, int right) {
if ( left == right) {
return ;
}
int mid = left + ( ( right - left) >>> 1 ) ;
mergeSort ( arr, left, mid) ;
mergeSort ( arr, mid + 1 , right) ;
merge ( arr, left, mid, right) ;
}
private static void merge ( int [ ] arr, int left, int mid, int right) {
int [ ] help = new int [ right - left + 1 ] ;
int i = 0 ;
int leftPoint = left;
int rightPoint = mid + 1 ;
while ( leftPoint <= mid && rightPoint <= right) {
help[ i++ ] = arr[ leftPoint] < arr[ rightPoint] ? arr[ leftPoint++ ] : arr[ rightPoint++ ] ;
}
while ( leftPoint <= mid) {
help[ i++ ] = arr[ leftPoint++ ] ;
}
while ( rightPoint <= right) {
help[ i++ ] = arr[ rightPoint++ ] ;
}
for ( i = 0 ; i < help. length; i++ ) {
arr[ left + i] = help[ i] ;
}
}
public static void main ( String[ ] args) {
int [ ] arr = ArrayUtils. getArray ( 10 , 20 ) ;
ArrayUtils. printArray ( arr) ;
mergeSort ( arr, 0 , arr. length - 1 ) ;
System. out. println ( ) ;
ArrayUtils. printArray ( arr) ;
}
}