排序分类概览
时间空间复杂度概览
以下排序方式均采用从小到大排序。
1.1.直接插入排序
算法思想
1.从位置1的数值n开始,将前面已经遍历过的数值集合看成数组m,则将n往m中插入
2.n插入到集合m中时从后往前比较,如果比n大则往后移一位,如果比较到比n小,则当前位置就是插入n的位置
3.通过1、2的操作则可以保证每次插入n后m的集合都是排好的序列
4.循环1、2、3操作将集合中所有数值均插入一遍即排序完成
代码实现
private int[] array = {
23, 11, 7, 29, 33, 59, 8, 20, 9, 3, 2, 6, 10, 44, 83, 28, 5, 1, 0, 36};
/**
* 直接插入排序:从1开始遍历数组,每个数字都在前面已经遍历的数字中插入
* 从小到大排序的话碰到比它大的则往后移,直到比它小为止
*/
private void insertSort() {
for (int i = 1; i < array.length; i++) {
int temp = array[i];
int j;
// 在前面已经遍历过的数字中比较若小于则往后移
for (j = i - 1; j >= 0; j--) {
if (temp < array[j]) {
array[j + 1] = array[j];
} else {
break;
}
}
array[j + 1] = temp;
}
}
kotlin语言实现
class Solution {
fun sortArray(nums: IntArray): IntArray {
if (null == nums || nums.size == 0) {
return nums
}
for (i in 1 until nums.size) {
val temp = nums[i]
for (j: Int in i - 1 downTo 0) {
if (temp < nums[j]) {
nums[j + 1] = nums[j]
nums[j] = temp
} else {
break
}
}
}
return nums
}
}
1.2.二分法排序
算法思想
1.从位置1的数值为n,将前面已经遍历过的数值集合看成数组m,则将n往m中插入。
2.n插入到集合m中时采用二分法,先比较m中中间的数值,如果比n大则继续比较后面一半集合的中间的数值,直至比较到拆分的集合中左边一半或者右边一半没有值为止,则当前中间值的位置即为n插入到m中的位置。
3.通过1、2的操作则可以保证每次插入n后m的集合都是排好的序列。
4.循环1、2、3操作将集合中所有数值均插入一遍即排序完成。
代码实现
private int[] array = {
23, 11, 7, 29, 33, 59, 8, 20, 9, 3, 2, 6, 10, 44, 83, 28, 5, 1, 0, 36};
/**
* 二分插入排序:从1开始遍历,已经遍历的数组中头是left,尾是right,遍历到的数字与中间的数字对比
* 若小于中间的数字则right变更成中间数字前面的一个数字,反之则变更left
* 直至最后left>right则插入
*/
private void binaryInsertSort() {
for (int i = 1; i < array.length; i++) {
int temp = array[i];
int left = 0, right = i - 1;
int mid;
while (left <= right) {
mid = (left + right) / 2;
if (temp < array[mid]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
// 将遍历到比他大的数字全部往后移一位
for (int j = i - 1; j >= left; j--) {
array[j + 1] = array[j];
}
array[left] = temp;
}
}
2.希尔排序
引用成贴:https://www.jianshu.com/p/d730ae586cf3
3.简单选择排序
算法思想
采用从小到大排序:
1.找到所有数中最大值下标
2.找到最大值的下标与最后一个位置的数值交换位置,这样每次找到的最大值则固定到最后
3.循环1、2操作直至遍历找到所有
代码实现
private int[] array = {
23, 11, 7, 29, 33, 59, 8, 20, 9, 3, 2, 6, 10, 44, 83, 28, 5, 1, 0, 36};
/**
* 选择排序:找到当前数中最大的数字,找到后与最后一个位置的数字交换位置,直至循环遍历完所有的数为止
*/
private void selectSort() {
for (int i = 0; i < array.length; i++) {
// 定义最大数字的下标,默认为0
int max = 0;
for (int j = 0; j < array.length - i; j++) {
// 找到比自己大的数就更新下标
if (array[max] < array[j]) {
max = j;
}
}
// 将找到最大的数与最后一个数字交换位置
int temp = array[array.length - i - 1];
array[array.length - i - 1] = array[max];
array[max] = temp;
}
}
kotlin语言实现
class Solution {
fun sortArray(nums: IntArray): IntArray {
if (null == nums || nums.size == 0) {
return nums
}
var length = nums.size
while (length > 0) {
var maxIndex: Int = 0
for (i: Int in 0 until length) {
//此处为升序排序
//若对数据进行降序排序,改为小于号即可,即 if (nums[i] < nums[maxIndex])
if (nums[i] > nums[maxIndex]) {
maxIndex = i
}
}
var temp = nums[length - 1]
nums[length - 1] = nums[maxIndex]
nums[maxIndex] = temp
length--
}
return nums
}
}
4.堆排序
引用成贴:https://blog.csdn.net/l577217/article/details/80516654
5.冒泡排序
算法思想
1.两两比较,如果后者比前者大则交换位置
2.每遍历一圈最大的数就会冒到最后,则确定了本轮比较中的最大值放到最后不动
3.循环1、2直至遍历完所有
代码实现
private int[] array = {
23, 11, 7, 29, 33, 59, 8, 20, 9, 3, 2, 6, 10, 44, 83, 28, 5, 1, 0, 36};
/**
* 冒泡排序:两两比较,大者交换位置,则每一圈比较最大的数就会冒到最后,循环直至遍历完所有
*/
private void bubbleSort() {
for (int i = 0; i < array.length - 1; i++) {
for (int j = 0; j < array.length - i - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
6.快速排序
算法思想
1.快速排序的思想主要是先设置一个基准点m,这里我们假设每次设置的基准点都是每一组的第一个数值。
2.拿着基准点m在集合中进行比较,找到它应该放置的位置。
3.比较方式主要是定义集合中最左边的下标left,最右边的下标right,从左边开始比较,比m小则left++,找到比m大的则停住,将left下标的值赋值成right下标的值,然后同理比较right,比m大的则right–,找到比m小的就赋值成left下标的值。当left==right之后则比较完成。
4.经过步骤3的比较之后则可以找到m点排序所在的位置,然后集合被分成前后两半,各自按照1、2、3的方式排序,递归至全部拆分比较完成后即排序完成。
步骤3引用《啊哈!算法》一书中的插图。图中以第一个点6为基准点,找到6排序后应该所在的位置。
代码实现
private int[] array = {
23, 11, 7, 29, 33, 59, 8, 20, 9, 3, 2, 6, 10, 44, 83, 28, 5, 1, 0, 36};
/**
* 快速排序:找到某个点排序之后它应该所在的位置
*/
private void quickSort() {
quickSort(0, array.length - 1);
}
/**
* 找到开始和结束位置之间以第一个数为基数,这个基数应该所在的位置
* 找到之后以基数为中心点拆分成前后两段,依次递归进行本操作,直至最后遍历完所有基数为止
*
* @param low 开始的点下标
* @param high 结束的点下标
*/
private void quickSort(int low, int high) {
if (low >= high) {
return;
}
int mid = getMiddle(low, high);
quickSort(low, mid - 1);
quickSort(mid + 1, high);
}
/**
* 通过比较获取最开始基数最后所在的位置
*
* @param low 最开始的位置
* @param high 结束的位置
* @return 最后基数所在的位置
*/
private int getMiddle(int low, int high) {
int temp = array[low];
while (low < high) {
while (low < high && array[high] >= temp) {
high--;
}
array[low] = array[high];
while (low < high && array[low] <= temp) {
low++;
}
array[high] = array[low];
}
array[low] = temp;
return low;
}
7.归并排序
算法思想
1.将数据集合两分拆开。
2.循环拆分至每组只剩一个为止。
3.将拆分的数组进行排序组合。
4.两两合并,直至合并成一个数组即排序完成。
代码实现
private int[] array = {
23, 11, 7, 29, 33, 59, 8, 20, 9, 3, 2, 6, 10, 44, 83, 28, 5, 1, 0, 36};
/**
* 归并排序:将数据集合两分拆开,直至最小之后两两排序合并
*/
private void mergeSort() {
int[] temp = new int[array.length];
mergeSort(temp, 0, array.length - 1);
}
/**
* 查分数组,如果数组不能拆分了,则直接返回,拆分之后合并
*/
private void mergeSort(int[] temp, int start, int end) {
if (start >= end) {
return;
}
int mid = (start + end) / 2;
mergeSort(temp, start, mid);
mergeSort(temp, mid + 1, end);
mergeArray(temp, start, mid + 1, end);
}
/**
* 将数组array,以mid为中心,前后两个数组进行合并
*/
private void mergeArray(int[] temp, int start, int mid, int end) {
// 定义指针下标,记录前后段是够可以继续移动
int minA = start, minB = mid;
for (int i = start; i <= end; i++) {
if (minA >= mid || minB > end) {
// 如果a或者b用完了,则直接用对方的
if (minA >= mid) {
temp[i] = array[minB];
minB++;
} else {
temp[i] = array[minA];
minA++;
}
} else {
// 都没用完则比较大小
if (array[minA] < array[minB]) {
temp[i] = array[minA];
minA++;
} else {
temp[i] = array[minB];
minB++;
}
}
}
System.arraycopy(temp, start, array, start, end - start + 1);
}
8.基数排序
引用成贴:https://blog.csdn.net/lrxb_123/article/details/115013190