简单排序:插入排序、选择排序、
冒泡排序 分治排序:快速排序、归并排序
分配排序:桶排序、基数排序
树状排序:堆排序
其他:计数排序、希尔排序
稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。
非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。
原地排序:原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
非原地排序:需要利用额外的数组来辅助排序。
时间复杂度:一个算法执行所消耗的时间。
空间复杂度:运行完一个算法所需的内存大小。
/** insertSort * 插入排序法 * @param arr * @return */
func insertSort(arr []int) {
// //判断数组是否为空或者长度是否大于2
if len(arr) < 2 {
return
}
//循环遍历数组
for i := 1; i < len(arr); i++ {
//定义变量保存要插入的值
tem := arr[i]
k := i - 1
for k >= 0 && arr[k] > tem {
arr[k+1] = arr[k]
k--
}
//元素插入
arr[k+1] = tem
}
return
}
// selectSort 选择排序 时间复杂度可能很高
func selectSort(arr []int) {
n := len(arr)
for i := 0; i < n-1; i++ {
m := i
for j := i + 1; j < n; j++ {
if arr[m] > arr[j] {
m = j
}
}
//交换
temp := arr[i]
arr[i] = arr[m]
arr[m] = temp
}
}
// bubbleSort 冒泡排序算法
func bubbleSort(arr []int) {
if len(arr) < 2 {
return
}
flag := true
//加一个标志位,记录上一次是否发生了交换,如果是,我们则进行下一轮,如果没有,说明已经冒泡好了
for i := 1; i < len(arr) && flag; i++ {
//控制次数,第几趟排序,只需要n-1趟,有交换时进行,只有flag=false就说明上一次一个元素都没有进行交换
flag = false
//假定未交换
for j := 0; j < len(arr)-i; j++ {
if arr[j] > arr[j+1] {
temp := arr[j]
arr[j] = arr[j+1]
arr[j+1] = temp
flag = true
}
}
}
}
// quickSort 快速排序算法
func quickSort(arr []int, left, right int) []int {
if left < right {
//获取基点元素所处的位置
mid := partition(arr, left, right)
//进行分割
arr = quickSort(arr, left, mid-1)
arr = quickSort(arr, mid+1, right)
}
return arr
}
func partition(arr []int, left, right int) int {
//选取基点元素
pivot := arr[left]
i := left + 1
j := right
for {
// 向右找到第一个小于等于 pivot 的元素位置
for i <= j && arr[i] <= pivot {
i++
}
// 向左找到第一个大于等于 pivot 的元素位置
for i <= j && arr[j] >= pivot {
j--
}
if i >= j {
break
}
//交换两个元素的位置,使得左边的元素不大于pivot,右边的不小于pivot
temp := arr[i]
arr[i] = arr[j]
arr[j] = temp
}
arr[left] = arr[j]
// 使中轴元素处于有序的位置
arr[j] = pivot
return j
}
// 堆排序
func heapSort(arr []int) {
//1.构建大顶堆
for i := len(arr)/2 - 1; i >= 0; i-- {
//从第一个非叶子结点从下至上,从右至左调整结构
sift(arr, i, len(arr))
}
//2.调整堆结构+交换堆顶元素与末尾元素
for i := len(arr) - 1; i > 0; i-- {
//现在的数组第一个就是根结点,最小值所在,进行交换,把它放到最右边
temp := arr[i]
arr[i] = arr[0]
arr[0] = temp
//重新建立堆
sift(arr, 0, i)
//重新对堆进行调整
}
}
/**
建立堆的方法
私有方法,只允许被堆排序调用
@param arr 要排序数组
@param parent 当前的双亲节点
@param len 数组长度
*/
func sift(arr []int, parent, len int) {
value := arr[parent]
//先取出当前元素i
for child := 2*parent + 1; child < len; child = child*2 + 1 {
//从parent结点的左子结点开始,也就是2*parent+1处开始
if child+1 < len && (arr[child] < arr[child+1]) {
//如果左子结点小于右子结点,child指向右子结点
child++
//右孩子如果比左孩子大,我们就将现在的孩子换到右孩子
}
//判断是否符合大顶堆的特性, 如果右孩子大于双亲,自然左孩子也大于双亲,符合
//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
if value < arr[child] {
arr[parent] = arr[child]
parent = child
} else {
//如果不是,说明已经符合我们的要求了。
break
}
}
arr[parent] = value
//将value值放到最终的位置
}