package com.daojia.dop.broker.repository.entity;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.SecureRandom;
/**
* 十大经典排序
* 参考:https://www.runoob.com/w3cnote/radix-sort.html
*/
public class SortDemo {
private static final Logger logger = LoggerFactory.getLogger(SortDemo.class);
public static void main(String[] args) {
logger.info("=================start main=====================");
int n = 10;
int[] array = new int[n];
SecureRandom secureRandom = new SecureRandom();
for (int i = 0; i < array.length; i++) {
array[i] = secureRandom.nextInt(2*n);
}
logger.info("=================start sort=======================");
logger.info(JSONObject.toJSONString(array));
//排序
int[] array1 = array.clone();
bubbleSort(array1);
int[] array2 = array.clone();
quickSort(array2);
int[] array3 = array.clone();
heapSort(array3);
int[] array4 = array.clone();
returnSort(array4);
int[] array5 = array.clone();
insertSort(array5);
int[] array6 = array.clone();
choiceSort(array6);
int[] array8 = array.clone();
hillSort(array8);
int[] array9 = array.clone();
bucketSort(array9);
int[] array7 = array.clone();
countSort(array7);
logger.info(JSONObject.toJSONString(array));
logger.info(JSONObject.toJSONString(array1));
logger.info(JSONObject.toJSONString(array2));
logger.info(JSONObject.toJSONString(array3));
logger.info(JSONObject.toJSONString(array4));
logger.info(JSONObject.toJSONString(array5));
logger.info(JSONObject.toJSONString(array5));
logger.info(JSONObject.toJSONString(array7));
logger.info(JSONObject.toJSONString(array8));
logger.info(JSONObject.toJSONString(array9));
}
/**
* @param n 冒泡
* 如果某一次冒泡没有发生交换则跳出循环
* 时间复杂度O(n^2) 空间复杂度O(1)
*/
public static void bubbleSort(int[] n) {
Long start = System.currentTimeMillis();
for (int i = 0; i < n.length - 1; i++) {
boolean flag = true;
for (int j = 0; j < n.length - i - 1; j++) {
if (n[j] > n[j + 1]) {
swap(n, j, j + 1);
flag = false;
}
}
if (flag) {
break;
}
}
logger.info("runTime for bubbleSort ={}", System.currentTimeMillis() - start);
}
public static void swap(int[] n, int i, int j) {
int tem = n[i];
n[i] = n[j];
n[j] = tem;
}
/**
* @param n 快排
*
* 左右两个指针,取排序开始位为基准值,右指针遍历比基准值小的位置跟左指针交换数据,
* 左指针遍历比基准值大的值跟右指针交换位置,最后左右指针重合将基准值放到重合位置
* 时间复杂度O(nlogn)
*/
public static void quickSort(int[] n) {
Long start = System.currentTimeMillis();
quick(n, 0, n.length - 1);
logger.info("runTime for quickSort ={}", System.currentTimeMillis() - start);
}
public static void quick(int[] n, int start, int end) {
int left = start;
int key = n[start];
int right = end;
while (left < right) {
//必须要又=号否则两数相等死循环
while (left < right && n[right] >= key) {
right--;
}
swap(n, right, left);
while (left < right && n[left] <= key) {
left++;
}
swap(n, left, right);
}
n[left] = key;
if (left + 1 < end) {
quick(n, left + 1, end);
}
if (left - 1 > start) {
quick(n, start, left - 1);
}
}
/**
* @param n 堆排
* 堆的结构是完全二叉树,可以用数组存
* 构建最大堆->堆排序
* 时间复杂度O(nlogn)
*/
public static void heapSort(int[] n) {
Long start = System.currentTimeMillis();
//最后一个非叶子节点 ,满二叉树最后一层节点数=前面所有层总和+1 n/2会向下取整 数组下标从0开始编号
int index = n.length / 2 - 1;
//最大堆
for (int i = index; i >= 0; i--) {
adjustHead(n, i, n.length - 1);
}
for (int i = n.length - 1; i > 0; i--) {
swap(n, i, 0);
adjustHead(n, 0, i - 1);
}
logger.info("runTime for headSort ={}", System.currentTimeMillis() - start);
}
public static void adjustHead(int[] n, int index, int end) {
//index的左节点(index+1)*2-1=2*index+1 (数组索引从0开始)
int left = 2 * index + 1;
if (left > end) {
return;
}
int right = left + 1;
int maxIndex = left;
//=号
if (right <= end && n[right] > n[left]) {
maxIndex = right;
}
if (n[index] < n[maxIndex]) {
swap(n, index, maxIndex);
adjustHead(n, maxIndex, end);
}
}
/**
* @param n 并归
* 数组分割成多断,断内有序,相邻两段合并
* 时间复杂度O(nlogn)
*/
public static void returnSort(int[] n) {
Long start = System.currentTimeMillis();
returnArray(n, 0, n.length - 1);
logger.info("runTime for returnSort ={}", System.currentTimeMillis() - start);
}
public static void returnArray(int[] n, int start, int end) {
if (start == end) {
return;
}
//向下取整
int mid = start + (end - start) / 2;
returnArray(n, start, mid);
//因为向下取整所以mid+1
returnArray(n, mid + 1, end);
merge(n, start, mid + 1, end);
}
public static void merge(int[] n, int start1, int start2, int end2) {
int start = start1;
int end = end2;
int end1 = start2 - 1;
//缓存
int[] tem = new int[end2 - start1 + 1];
int i;
for (i = 0; i < tem.length - 1 && start1 <= end1 && start2 <= end2; i++) {
tem[i] = n[start1] < n[start2] ? n[start1++] : n[start2++];
}
while (start1 <= end1) {
tem[i++] = n[start1++];
}
while (start2 <= end2) {
tem[i++] = n[start2++];
}
//缓存写入数组位置
i--;
while (start <= end) {
n[end--] = tem[i--];
}
}
/**
* @param n 插入
* 前面数组看成有序的,i跟前边的序列倒序对比,如果有比i位置大的数则向后移动
* 直到找到i的位置,将数据插入
* O(n^2)
*/
public static void insertSort(int[] n) {
Long start = System.currentTimeMillis();
for (int i = 1; i < n.length; i++) {
int tem = n[i];
int j = i;
while (j > 0 && n[j - 1] > tem) {
n[j] = n[j - 1];
j--;
}
n[j] = tem;
}
logger.info("runtime for insertSort ={}", System.currentTimeMillis() - start);
}
/**
* @param n 希尔
* 数组分组,组内插入,扩大分组
*/
public static void hillSort(int[] n) {
Long start = System.currentTimeMillis();
//gap--组数,每次组数减半,组内元素个数加倍
for (int gap = n.length / 2; gap > 0; gap /= 2) {
for (int i = gap; i < n.length; i++) {
int tem = n[i];
int j = i;
//每个数跟tem比较,比tem小的向后移动
while (j >= gap && n[j - gap] > tem) {
n[j] = n[j - gap];
j = j - gap;
}
n[j] = tem;
}
}
logger.info("runtime for hillSort ={}", System.currentTimeMillis() - start);
}
/**
* @param n 选择
* 每次从剩余的序列中选出最小值放在剩余序列开头
*/
public static void choiceSort(int[] n) {
Long start = System.currentTimeMillis();
for (int i = 0; i < n.length; i++) {
//记录最小值下标
int minIndex = i;
for (int j = i + 1; j < n.length; j++) {
if (n[j] < n[minIndex]) {
//更新最小值下标
minIndex = j;
}
}
//将最小值放到合适位置
swap(n, i, minIndex);
}
logger.info("runtime for choiceSort ={}", System.currentTimeMillis() - start);
}
/**
* @param n 计数
* 辅助数组k长度为max-min+1,记录每个值出现的次数,eg:k[0]记录min出现的次数
*/
public static void countSort(int[] n) {
Long start = System.currentTimeMillis();
int max = n[0];
int min = n[0];
for (int i = 1; i < n.length; i++) {
max = max > n[i] ? max : n[i];
min = min < n[i] ? min : n[i];
}
int[] k = new int[max - min + 1];
for (int i = 0; i < n.length; i++) {
k[n[i] - min]++;
}
int j = 0;
int i = 0;
while (j < k.length) {
while (k[j] > 0) {
n[i++] = j + min;
k[j]--;
}
j++;
}
logger.info("runtime for countSort={}", System.currentTimeMillis() - start);
}
/**
* @param arr 桶
* 计数的优化?为啥时间比计数更长?
*/
public static void bucketSort(int[] arr) {
Long start = System.currentTimeMillis();
int bucketSize = 5;
int minValue = arr[0];
int maxValue = arr[0];
for (int value : arr) {
if (value < minValue) {
minValue = value;
} else if (value > maxValue) {
maxValue = value;
}
}
int bucketCount = (maxValue - minValue) / bucketSize + 1;
int[][] buckets = new int[bucketCount][bucketSize];
// 利用映射函数将数据分配到各个桶中
for (int i = 0; i < arr.length; i++) {
int index = (arr[i] - minValue) / bucketSize;
int indexBucket = (arr[i] - minValue) % bucketSize;
buckets[index][indexBucket]++;
}
int arrIndex = 0;
for (int i = 0; i < bucketCount; i++) {
int j = 0;
while (j < bucketSize) {
while (buckets[i][j] > 0) {
arr[arrIndex++] = i * bucketSize + j +minValue;
buckets[i][j]--;
}
j++;
}
}
logger.info("runtime for bucketSort ={}", System.currentTimeMillis() - start);
}
/**
*
* 基数
*http://bubkoo.com/2014/01/15/sort-algorithm/radix-sort/
*思想是个位桶排序,然后十位桶排序。。。。。。最后排序完成
*如何解决桶排序扩容浪费时间问题?如果初始化数组长度的桶,浪费空间还不如计数法
*/
}