所有的排序实现均由小到大,均使用int[]数组来排序。
1、冒泡排序
/**
* 冒泡排序,从小到大
* 解析:外层for循环表示冒几次泡,内层for循环表示每次冒泡过程中相邻两个数比较的次数
* 可见越到后面的冒泡,相邻两个数比较的次数越少
*
* @param datas
* @return
*/
public int[] bubbleSort(int[] datas) {
for (int i = 0; i < datas.length - 1; i++) {
for (int j = 0; j < datas.length - 1 - i; j++) {
if (datas[j] > datas[j + 1]) {
int temp = datas[j];
datas[j] = datas[j + 1];
datas[j + 1] = temp;
}
}
}
return datas;
}
2、快速排序
/**
* 快速排序,从小到大
* 误区一记:参数第一次传入的start、end为定值,表示最初确定的排序区间
* 所以要将start、end赋值给low和high,至始至终变化的是low和high
*
* @param datas
* @return
*/
public void quickSort(int[] datas, int start, int end) {
if (start < end) {
int low = start;
int high = end;
int target = datas[low];
int pos = end;
while (low < high) {
if (target > datas[pos]) {
datas[low] = datas[pos];
low++;
pos = low;
} else {
datas[high] = datas[pos];
high--;
pos = high;
}
}
datas[pos] = target;
quickSort(datas, start, pos);
quickSort(datas, pos + 1, end);
}
}
3、直接插入排序
/**
* 直接插入排序
*
* @param datas
*/
public void insertSrot(int[] datas) {
//从第二个数开始遍历比较大小
for (int i = 1; i < datas.length; i++) {
int temp = datas[i];
int j = i - 1;
for (; j >= 0; j--) {
if (datas[j] > temp) {
datas[j + 1] = datas[j];
} else {
break;
}
}
datas[j + 1] = temp;
}
}
4、希尔排序
/**
* 希尔排序
*
* @param datas
*/
public void shellSort(int[] datas) {
//遍历所有步长
for (int i = datas.length / 2; i > 0; i /= 2) {
//遍历所有元素
for (int j = i; j < datas.length; j++) {
//对本组的数据排序
for (int k = j - i; k >= 0; k -= i) {
if (datas[k] > datas[k + i]) {
int temp = datas[k];
datas[k] = datas[k + i];
datas[k + i] = temp;
}
}
}
}
}
5、选择排序
/**
* 选择排序
* 每次选出最小的并排在前面
*
* @param datas
*/
public void selectSort(int[] datas) {
for (int i = 0; i < datas.length; i++) {
for (int j = i + 1; j < datas.length; j++) {
if (datas[i] > datas[j]) {
int temp = datas[j];
datas[j] = datas[i];
datas[i] = temp;
}
}
}
}
6、归并排序
/**
* 归并排序
*
* @param datas 原数据
* @param start 需要排序的开始位
* @param end 需要排序的结束位
*/
public void mergerSort(int[] datas, int start, int end) {
int medium = (end - start) / 2 + start;
if (start < end) {
//递归思想,先排序前半段
mergerSort(datas, start, medium);
//递归思想,先排序后半段
mergerSort(datas, medium + 1, end);
//归并
merger(datas, start, medium, end);
}
}
/**
* 两个有序数组的归并
*
* @param data 原数据
* @param low 需要排序的低位
* @param medium 需要排序的中间位置
* @param high 需要排序的高位
*/
public void merger(int[] data, int low, int medium, int high) {
//创建存放归并后的临时数组
int[] temp = new int[high - low + 1];
//记录第一个数组中需要遍历的下标
int i = low;
//记录第二个数组需要遍历的下标
int j = medium + 1;
//记录临时数组中存放的下标
int index = 0;
//将小的数据放入临时数组中
while (i <= medium && j <= high) {
if (data[i] < data[j]) {
temp[index] = data[i];
i++;
} else {
temp[index] = data[j];
j++;
}
index++;
}
//将第一个数组剩下的数据放入临时数组中
while (i <= medium) {
temp[index] = data[i];
i++;
index++;
}
//将第二个数组剩下的数据放入临时数组中
while (j <= high) {
temp[index] = data[j];
j++;
index++;
}
//将排好序的临时数组里的数据复制到原数组对应位置里面
for (int k = 0; k < temp.length; k++) {
data[low + k] = temp[k];
}
}
7、基数排序
/**
* 基数排序
* 在此基础上可使用队列来优化
*
* @param datas
*/
public void radixSort(int[] datas) {
//取出最大的数
int max = Integer.MIN_VALUE;
for (int i = 0; i < datas.length; i++) {
if (datas[i] < max) {
max = datas[i];
}
}
//用于临时存放数据的二维数组
int[][] temp = new int[10][datas.length];
//用于记录每个数组的数字个数的数组
int[] countArray = new int[10];
int len = ("" + max).length();
//根据最大数的长度决定比较的次数
for (int j = 0, n = 1; j < len; j++, n *= 10) {
//遍历数组将每个数字放到temp中对应的数组中
for (int k = 0; k < datas.length; k++) {
//取每个数不同位数上的数字
int ys = datas[k] / n % 10;
//将数放在相应的数组中
temp[ys][countArray[ys]] = datas[k];
//此余数的数据数量+1
countArray[ys]++;
}
//记录放回原数组中的对应位置
int index = 0;
//取出temp中已分类的数据放回原数组中,countArray.length === 10
for (int l = 0; l < countArray.length; l++) {
if (countArray[l] > 0) {
for (int m = 0; m < countArray[l]; m++) {
datas[index] = temp[l][m];
index++;
}
//把countArray中记录的当前个数信息清空
countArray[l] = 0;
}
}
}
}