/**
* Title: 插入排序中的直接插入排序,依赖于初始序列
* Description: 在有序序列中不断插入新的记录以达到扩大有序区到整个数组的目的
* 时间复杂度:最好情形O(n),平均情形O(n^2),最差情形O(n^2)
* 空间复杂度:O(1)
* 稳定性: 稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class StraightInsertionSort {
public static int[] insertSort(int[] target) {
if (target != null && target.length != 1) {
for (int i = 1; i < target.length; i++) {
for (int j = i; j > 0; j--) {
if(target[j] < target[j-1]) {
int temp = target[j];
target[j] = target[j-1];
target[j-1] = temp;
}
}
}
}
return target;
}
}
/**
* Title: 选择排序中的直接选择排序
* Description: 每次找到数组中当前排序范围中的最小值并与该范围中的第一个数字交换,同时缩小待排序数组的排序范围
* 时间复杂度:最好情形O(n^2),平均情形O(n^2),最差情形O(n^2)
* 空间复杂度:O(1)
* 稳定性:不稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class StraightSelectSort {
public static int[] selectSort(int[] target) {
if (target != null && target.length != 1) {
for (int i = 0; i < target.length; i++) {
int min_index = i;
for (int j = i + 1; j < target.length; j++) {
if (target[min_index] > target[j]) {
min_index = j;
}
}
if (target[min_index] != target[i]) {
int min = target[min_index];
target[min_index] = target[i];
target[i] = min;
}
}
}
return target;
}
}
/**
* Title: 插入排序中的希尔排序
* Description: 分别对间隔为gap的gap个子序列进行直接插入排序,不断缩小gap,直至为 1
* 刚开始时,gap较大,每个子序列元素较少,排序速度较快;
* 待到排序后期,gap变小,每个子序列元素较多,但大部分元素基本有序,所以排序速度仍较快。
* 时间复杂度:O(n) ~ O(n^2)
* 空间复杂度:O(1)
* 稳 定 性:不稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class ShellSort {
public static int[] shellSort(int[] target) {
if (target != null && target.length != 1) {
int gap = target.length;
do {
gap = gap / 3 + 1;
for (int i = 0 + gap; i < target.length; i++) {
if (target[i] < target[i - gap]) {
int j = i - gap;
int temp = target[i];
do {
target[j + gap] = target[j];
j = j - gap;
} while (j >= 0 && target[j] > temp);
target[j + gap] = temp;
}
}
} while (gap > 1);
}
return target;
}
}
/**
* Title: 分配排序中的基数排序
* Description: 不是在对元素进行比较的基础上进行排序,而是采用 "分配 + 收集" 的办法
* 首先,将目标序列各元素分配到各个桶中;
* 其次,将各个桶中的元素按先进先出的顺序再放回去
* 如此往复...
* 时间复杂度:O(d*(r+n))或者 O(dn),d 的大小一般会受到 n的影响
* 空间复杂度:O(rd + n)或者 O(n)
* 稳 定 性:稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class RadixSort {
/**
* @description 分配 + 收集
* @param target 待排序数组
* @param r 基数
* @param d 元素的位数
* @param n 待排序元素个数
* @return
*/
public static int[] radixSort(int[] target, int r, int d, int n) {
if (target != null && target.length != 1 ) {
int[][] bucket = new int[r][n];
int digit;
int divisor = 1;
int[] count = new int[r];
for (int i = 0; i < d; i++) {
for (int ele : target) {
digit = (ele / divisor) % 10;
bucket[digit][count[digit]++] = ele;
}
int index = 0;
for (int j = 0; j < r; j++) {
int k = 0;
while (k < count[j]) {
target[index++] = bucket[j][k++];
}
count[j] = 0;
}
divisor *= 10;
}
}
return target;
}
public static void main (String[] agr) {
int[] a = {4, 1, 31, 21};
int[] b = RadixSort.radixSort(a, 10, 2, 4);
for (int i = 0; i < b.length; i++) {
System.out.println(b[i]);
}
}
}
/**
* Title: 交换排序中的快速排序,目前应用最为广泛的排序算法,是一个递归算法
* Description:快速排序包括两个过程:划分 和 快排
* "划分"是指将原序列按基准元素划分两个子序列
* "快排"是指分别对子序列进行快排
*
* 就平均计算时间而言,快速排序是所有内部排序方法中最好的一个
*
* 对大规模数据排序时,快排是快的;对小规模数据排序时,快排是慢的,甚至慢于简单选择排序等简单排序方法
*
* 快速排序依赖于原始序列,因此其时间复杂度从O(nlgn)到O(n^2)不等
* 时间复杂度:最好情形O(nlgn),平均情形O(nlgn),最差情形O(n^2)
*
* 递归所消耗的栈空间
* 空间复杂度:O(lgn)
*
* 可选任一元素作为基准元素
* 稳 定 性:不稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class QuickSort {
/**
* @description 快排算法(递归算法):在递去过程中就把问题解决了
* @param target
* @param left
* @param right
* @return
*/
public static int[] quickSort(int[] target, int left, int right) {
if (right > left) {
int base_index = partition(target, left, right);
quickSort(target, left, base_index - 1);
quickSort(target, base_index + 1, right);
return target;
}
return target;
}
/**
* @description 序列划分,以第一个元素为基准元素
* @param target 序列
* @param left 序列左端
* @param right 序列右端
* @return
*/
public static int partition(int[] target, int left, int right) {
int base = target[left];
int base_index = left;
for (int i = left + 1; i <= right; i++) {
if (target[i] < base) {
base_index++;
if (base_index != i) {
int temp = target[base_index];
target[base_index] = target[i];
target[i] = temp;
}
}
}
target[left] = target[base_index];
target[base_index] = base;
System.out.println(Arrays.toString(target));
return base_index;
}
}
import java.util.Arrays;
/**
* Title: 归并排序 ,概念上最为简单的排序算法,是一个递归算法
* Description:归并排序包括两个过程:归 和 并
* "归"是指将原序列分成半子序列,分别对子序列进行递归排序
* "并"是指将排好序的各子序列合并成原序列
*
* 归并排序的主要问题是:需要一个与原待排序数组一样大的辅助数组空间
*
* 归并排序不依赖于原始序列,因此其最好情形、平均情形和最差情形时间复杂度都一样
* 时间复杂度:最好情形O(n),平均情形O(n^2),最差情形O(n^2)
* 空间复杂度:O(n)
* 稳 定 性:稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class MergeSort {
/**
* @created 2017年5月20日 下午4:04:52
* @param target 待排序序列
* @param left 待排序序列起始位置
* @param right 待排序序列终止位置
* @return
*/
public static int[] mergeSort(int[] target, int left, int right) {
if (right > left) {
int mid = (left + right) / 2;
mergeSort(target, left, mid);
mergeSort(target, mid+1, right);
return merge(target, left, mid, right);
}
return target;
}
/**
* @description 两路归并算法
* @param target 用于存储归并结果
* @param left 第一个有序表的第一个元素所在位置
* @param mid 第一个有序表的最后一个元素所在位置
* @param right 第二个有序表的最后一个元素所在位置
* @return
*/
public static int[] merge(int[] target, int left, int mid, int right) {
int[] temp = Arrays.copyOf(target, target.length);
int s1 = left;
int s2 = mid + 1;
int index = left;
while (s1 <= mid && s2 <= right) {
if (temp[s1] <= temp[s2]) {
target[index++] = temp[s1++];
}
else {
target[index++] = temp[s2++];
}
}
while (s1 <= mid) {
target[index++] = temp[s1++];
}
while (s2 <= right) {
target[index++] = temp[s2++];
}
return target;
}
}
/**
* Title: 堆排序(选择排序),升序排序(最大堆)
* Description: 现将给定序列调整为最大堆,然后每次将堆顶元素与堆尾元素交换并缩小堆的范围,直到将堆缩小至1
* 时间复杂度:O(nlgn)
* 空间复杂度:O(1)
* 稳 定 性:不稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class HeapSort {
public static int[] heapSort(int[] target) {
if (target != null && target.length > 1) {
int pos = (target.length - 2) / 2;
while (pos >= 0) {
shiftDown(target, pos, target.length - 1);
pos--;
}
for (int i = target.length-1; i > 0; i--) {
int temp = target[i];
target[i] = target[0];
target[0] = temp;
shiftDown(target, 0, i-1);
}
return target;
}
return target;
}
/**
* @description 自上而下调整为最大堆
* @param target
* @param start
* @param end
*/
private static void shiftDown(int[] target, int start, int end) {
int i = start;
int j = 2 * start + 1;
int temp = target[i];
while (j <= end) {
if (j < end && target[j + 1] > target[j]) {
j = j + 1;
}
if (target[j] <= temp) {
break;
}
else {
target[i] = target[j];
i = j;
j = 2 * j + 1;
}
}
target[i] = temp;
}
}
/**
* Title: 交换排序中的冒泡排序 ,一般情形下指的是优化后的冒泡排序,最多进行n-1次比较
* Description:因为越大的元素会经由交换慢慢"浮"到数列的顶端(最后位置),最大的数最后才确定下来,所以称为冒泡排序
* 时间复杂度:最好情形O(n),平均情形O(n^2),最差情形O(n^2)
* 空间复杂度:O(1)
* 稳 定 性:稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class BubbleSort {
/**
* @description 朴素冒泡排序(共进行n-1次比较)
* @author rico
*/
public static int[] bubbleSort(int[] target) {
int n = target.length;
if (target != null && n != 1) {
for (int i = 0; i < n-1; i++) {
for (int j = n-1; j > i; j--) {
if (target[j] <target[j-1]) {
int temp = target[j];
target[j] = target[j-1];
target[j-1] = temp;
}
}
System.out.println(Arrays.toString(target));
}
}
return target;
}
/**
* @description 优化冒泡排序
*/
public static int[] optimizeBubbleSort(int[] target) {
int n = target.length;
if (target != null && n != 1) {
for (int i = 0; i < n-1; i++) {
boolean exchange = false;
for (int j = n-1; j > i; j--) {
if(target[j] < target[j-1]) {
int temp = target[j];
target[j] = target[j-1];
target[j-1] = temp;
exchange = true;
}
}
System.out.println(Arrays.toString(target));
if (!exchange) {
return target;
}
}
}
return target;
}
}
/**
* Title: 插入排序中的折半插入排序,依赖于初始序列
* Description: 折半搜索出插入位置,并直接插入;与直接插入搜索的区别是,后者的搜索要快于顺序搜索
* 时间复杂度:折半插入排序比直接插入排序明显减少了关键字之间的比较次数,但是移动次数是没有改变。所以,
* 折半插入排序和插入排序的时间复杂度相同都是O(N^2),在减少了比较次数方面它确实相当优秀,所以该算法仍然比直接插入排序好。
* 空间复杂度:O(1)
* 稳 定 性:稳定
* 内部排序(在排序过程中数据元素完全在内存)
*/
public class BinaryInsertSort {
public static int[] binaryInsertSort(int[] target) {
if (target != null && target.length > 1) {
for (int i = 1; i < target.length; i++) {
int left = 0;
int right = i - 1;
int mid;
int temp = target[i];
if (temp < target[right]) {
while (left <= right) {
mid = (left + right) / 2;
if (target[mid] < temp) {
left = mid + 1;
}
else if (target[mid] > temp) {
right = mid - 1;
}
else {
left = left + 1;
}
}
for (int j = i; j > left; j--) {
target[j] = target[j-1];
}
target[left] = temp;
}
}
}
return target;
}
}