面试必问的排序算法

复制代码
欢迎大家到我的博客浏览。排序算法 | YinKai's Blog

介绍

在面试中被问到排序算法,发现不能很好的描述出来,于是写一篇文章总结一下。常见的排序算法有 冒泡排序插入排序快速排序归并排序堆排序等。下面一一介绍。

1、冒泡排序 O(n^2)
算法思想:

共 n 个元素需要排序,通过比较相邻的两个元素,并将较大的元素放到后面,以此每一轮比较将乱序的元素中的最大的元素放到最后一个有序区间中。每一次遍历都能确定一个数在有序数组中的位置,且数组最后的一个区间中的数是有序的,直到所有数的位置都确定了,排序完成。

核心代码:
Go 复制代码
for i := 0; i < n-1; i++ {
    for j := 0; j < n-i-1; j++ {
        if arr[j] > arr[j+1] {
            // 交换 arr[j] 和 arr[j+1]
            arr[j], arr[j+1] = arr[j+1], arr[j]
        }
    }
}
2、插入排序 O(n^2)
算法思想:

遍历一遍整个数组,每次遍历将当前元素放到数组首部的有序序列中的合适位置,每次保证数组首部增加一个数,遍历 n - 1 次后,就可以保证整个数组的有序性。【合适的位置:往前找第一个小于当前数的位置,将其放在该数的后面,就说明当前数前面小于当前数,当前数后面大于当前数】

核心代码:
Go 复制代码
for i := 1; i < n; i++ {
    key := q[i] // 注意:在Go中切片的使用
    j := i - 1

    // 往前找第一个小于当前数的位置
    // 将其放在该数的后面,说明当前数前面小于当前数,当前数后面大于当前数
    for j >= 0 && q[j] > key {
        q[j+1] = q[j]
        j--
    }

    q[j+1] = key
}
3、快速排序 O(nlogn)
算法思想:

分而治之的一个思想,每次将整个数组分为两部分,然后保证左边是小于某个值的,右边是大于某个值的,这样在对两个部分采用同样的思想去划分,最后划分到区间中只有一个数了,就可以保证整个数组是有序的了。

核心代码:
Go 复制代码
func quickSort(q []int, l, r int) {
    if l >= r {
        return 
    }
​
    mid := (l + r) >> 1
    x := q[mid]
    i, j := l - 1, r + 1
    for i < j {
        for i ++; q[i] < x; i ++{}
        for j --; q[j] > x; j --{}
        if i < j {
            q[i], q[j] = q[j], q[i]
        }
    }
    quickSort(q, l, j)
    quickSort(q, j + 1, r)
}
4、归并排序 O(nlogn)
算法思想:

利用递归将整个区间分为足够小的区间,保证小区间中的数是有序的,然后再逐渐回溯,使大区间也变得有序。最终达到整个区间有序的一个状态。

核心代码:
Go 复制代码
func mergeSort(a []int, l, r int) {
    if l >= r {
        return
    }
​
    mid := (l + r) >> 1
    mergeSort(a, l, mid)
    mergeSort(a, mid+1, r)
    i, j, k := l, mid+1, 0
    for i <= mid && j <= r {
        if a[i] <= a[j] {
            t[k] = a[i]
            k++
            i++
        } else {
            t[k] = a[j]
            k++
            j++
        }
    }
​
    for i <= mid {
        t[k] = a[i]
        k++
        i++
    }
    for j <= r {
        t[k] = a[j]
        k++
        j++
    }
    for i, j := l, 0; i <= r; i++ {
        a[i] = t[j]
        j++
    }
}
5、堆排序
算法思想

堆:即一棵完全二叉树,且每一个点小于等于其左右儿子节点【小根堆】。

建堆:从总数的 n/2 开始往上建,因为必须保证其有左右儿子节点。建堆的过程,就是把父节点、左右儿子节点中较小的元素放到父节点的位置,逐步将大的节点往下移的操作。

核心代码
Go 复制代码
package main
​
​
import "fmt"
​
var n, m, cnt int
var h []int
​
func down (u int) {
    t := u
    if u * 2 <= cnt && h[u * 2] < h[t] {
        t = u * 2
    }
    if u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t] {
        t = u * 2 + 1
    }
    if t != u {
        h[t], h[u] = h[u], h[t]
        down(t)
    }
}
​
func main() {
    fmt.Scan(&n, &m)
    h = make([]int, n + 1)
    
    for i := 1; i <= n; i ++ {
        fmt.Scan(&h[i])
    }
    cnt = n
    
    for i := n / 2; i > 0; i -- {
        down(i)
    }
    for n > 0 {
        n --
        fmt.Printf("%d ", h[1])
        h[1] = h[cnt]
        cnt --
        down(1)
    }
}

未完待续。。。。

相关推荐
Lee川3 小时前
面试通关:JWT 认证与双 Token 机制深度解析
后端·面试
平凡但不平庸的码农4 小时前
Go Slice 详解
算法·golang
kyriewen5 小时前
你还在手动敲命令部署?GitHub Actions 让你 push 即上线,摸鱼时间翻倍
前端·面试·github
怕浪猫5 小时前
荒岛原始无工业、无电力、无设备,从零搭建最基础计算机体系
人工智能·设计模式·面试
炸膛坦客7 小时前
嵌入式 - 数据结构与算法:(1-7)数据结构 - 顺序表和链表的对比
数据结构·链表
Jasmine_llq8 小时前
《B3867 [GESP202309 三级] 小杨的储蓄》
算法·循环遍历·数组累加(模拟)·索引定位·顺序输出
啦啦啦_99998 小时前
案例之 逻辑回归_电信用户流失预测
算法·机器学习·逻辑回归
风筝在晴天搁浅8 小时前
快手/字节 CodeTop LeetCode 415.字符串相加
算法·leetcode
hoiii1878 小时前
基于栅格法的机器人工作空间划分系统
数据结构·机器人
DragonnAi8 小时前
猫咪如厕检测与分类识别系统系列【十四】 项目结构重新整理-即将开源完整算法
算法·开源