面试必问的排序算法

复制代码
欢迎大家到我的博客浏览。排序算法 | 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)
    }
}

未完待续。。。。

相关推荐
J***793942 分钟前
后端在分布式系统中的数据分片
算法·哈希算法
Dream it possible!2 小时前
LeetCode 面试经典 150_二叉搜索树_二叉搜索树中第 K 小的元素(86_230_C++_中等)
c++·leetcode·面试
sin_hielo2 小时前
leetcode 2872
数据结构·算法·leetcode
dragoooon343 小时前
[优选算法专题八.分治-归并 ——NO.49 翻转对]
算法
AI科技星3 小时前
为什么宇宙无限大?
开发语言·数据结构·经验分享·线性代数·算法
Zero-Talent3 小时前
位运算算法
算法
不穿格子的程序员3 小时前
从零开始刷算法——双指针-三数之和&接雨水
算法·双指针
合方圆~小文4 小时前
AI摄像头精准识别技术依赖于深度算法
数据结构·数据库·数码相机·模块测试
无限进步_4 小时前
C语言数组元素删除算法详解:从基础实现到性能优化
c语言·开发语言·windows·git·算法·github·visual studio
松涛和鸣4 小时前
16、C 语言高级指针与结构体
linux·c语言·开发语言·数据结构·git·算法