package com.algorithm.exersice;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 查找和排序:
* 查找:顺序查找O(n)、二分查找O(lgn)、哈希表查找O(1)、二叉排序树查找O(lgn)
* 排序:插入排序、冒泡排序、归并排序、快速排序
*/
public class SearchAndSort {
public static void main(String[] args) {
int a[] = {39,5,3,16,27,2,19,38,50,4,47,15,48};
//int a[] = {1,2,3,4,5};
//bubbleSort(a); // 冒泡排序
//selectionSort(a); // 选择排序
//insertionSort(a); //插入排序
//shellSort(a); // 希尔排序
//mergeSort(a); // 归并排序
print(a);
}
/**
* 归并排序
* T(n) = 2T(n/2)+n
* 时间复杂度:平均O(nlgn),最坏O(nlgn),最好O(nlgn)
* 空间复杂度O(n)
* 稳定排序
* 时间复杂度固定,不受输入数据影响,表现优于选择排序
* 缺点:需要额外空间
* @param a
*/
private static void mergeSort(int[] a) {
if (a == null || a.length == 0 || a.length == 1) {
return;
}
int temp[] = Arrays.copyOf(a,a.length);
//mergeSortRecursively(a, 0, a.length-1, temp); //递归算法
mergeSortNonRecursively(a, temp); //非递归算法
}
/**
* 归并排序非递归算法
*/
private static void mergeSortNonRecursively(int[] a, int[] temp) {
int gap=0, start=0, current=0, i=0, j=0;
for (gap=1; gap<a.length; gap*=2) {
for (start=0; start<a.length; start=start+gap*2) {
i=start;
j=start+gap;
current=start;
while (i<start+gap && i<a.length && j<start+gap*2 && j<a.length) {
if (a[i]<=a[j]) {
temp[current++] = a[i++];
} else {
temp[current++] = a[j++];
}
}
while (i<start+gap && i<a.length) {
temp[current++] = a[i++];
}
while (j<start+gap*2 && j<a.length) {
temp[current++] = a[j++];
}
}
for (i=0; i<a.length; i++) {
a[i] = temp[i];
}
}
}
/**
* 归并排序递归算法
*/
private static void mergeSortRecursively(int[] a, int start, int end, int temp[]) {
if (start >= end) {
return;
}
int rightStart = start+(end-start)/2+1;
mergeSortRecursively(a,start, rightStart-1, temp);
mergeSortRecursively(a,rightStart, end, temp);
int i=start, j=rightStart;
int currentIndex = start;
while (i<=rightStart-1 && j<=end) {
if (a[i]<=a[j]) {
temp[currentIndex++] = a[i++];
} else {
temp[currentIndex++] = a[j++];
}
}
while (i<=rightStart-1) {
temp[currentIndex++] = a[i++];
}
while (j<=end) {
temp[currentIndex++] = a[j++];
}
for (currentIndex=start;currentIndex<=end;currentIndex++) {
a[currentIndex] = temp[currentIndex];
}
System.out.println("每步打印:start="+start+", end="+end);
print(a);
System.out.println();
}
/**
* 希尔排序
* 时间复杂度:平均O(n^1.3),最坏O(n^2),最好O(n)(*时间复杂度与步长的选择有关)
* 空间复杂度O(1)
* 不稳定排序
* @param a
*/
private static void shellSort(int[] a) {
if (a == null || a.length == 0 || a.length == 1) {
return;
}
int gap = a.length/2; //步长
int m=0, n=0;
int temp = 0;
while (gap>0) {
// 以下是分组执行,但实际过程中是多个分组交叉执行
/*for (int i = 0; i < gap; i++) {
for (m = gap + i; m < a.length; m += gap) {
temp = a[m];
for (n = m-gap; n >=0; n -= gap) {
if (a[n] > temp) {
a[n + gap] = a[n];
} else {
break;
}
}
a[n + gap] = temp;
}
}*/
for (m=gap; m<a.length;m++) {
temp = a[m];
for (n=m-gap; n>=0; n-=gap) {
if (a[n]>temp) {
a[n+gap] = a[n];
} else {
break;
}
}
a[n+gap] = temp;
}
//每步说明:
//System.out.println("步长为"+gap+":");
//print(a);
//System.out.println();
//每步说明end
gap = gap/2;
}
}
/**
* 插入排序
* 时间复杂度:平均O(n^2),最坏O(n^2),最好O(n)
* 空间复杂度O(1)
* 稳定排序
* 适用原始数据基本有序的
* @param a
*/
private static void insertionSort(int[] a) {
if (a == null || a.length == 0 || a.length == 1) {
return;
}
int temp=0, i=0, j=0;
for (i=1; i<a.length; i++) {
temp = a[i];
j=i-1;
for (j=i-1;j>=0;j--) {
if (a[j]>temp) {
a[j+1] = a[j];
} else {
break;
}
}
a[j+1] = temp;
}
}
/**
* 选择排序
* 时间复杂度:平均O(n^2),最坏O(n^2),最好O(n^2)
* 空间复杂度O(1)
* 不稳定排序
* 适用数据规模小的
* @param a
*/
private static void selectionSort(int[] a) {
if (a == null || a.length == 0 || a.length == 1) {
return;
}
int minIndex = 0;
for (int i=0;i<a.length-1;i++) {
minIndex = i;
for (int j=i+1; j<a.length; j++) {
if (a[minIndex] > a[j]) {
minIndex = j;
}
}
if (i != minIndex) {
swap(a, i, minIndex);
}
}
}
/**
* 冒泡排序
* 时间复杂度:平均O(n^2),最坏O(n^2),最好O(n)
* 空间复杂度O(1)
* 稳定排序
* 适用原始数据基本有序的
* @param a
*/
private static void bubbleSort(int[] a) {
if (a == null || a.length == 0 || a.length == 1) {
return;
}
for (int i=0 ;i<a.length-1;i++) {
boolean flag = false; //在此次遍历中是否有元素交换
for (int j=0; j<a.length-1-i; j++) {
if (a[j]>a[j+1]) {
swap(a, j, j+1);
flag = true;
}
}
if (!flag) {
//没有元素交换,说明已经排序完成
break;
}
}
}
// 交换数组a中位置i和位置j的元素
private static void swap(int[] a, int j, int i) {
if (a == null || j>=a.length || j<0 || i>=a.length || i<0) {
System.err.println("swap下标越界 j="+j+", i="+i);
return;
}
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
//打印数组
private static void print(int[] a) {
if (a==null || a.length ==0) {
System.out.println("empty array");
return;
}
for (int i=0;i<a.length;i++) {
System.out.printf("%d ",a[i]);
}
}
}