常用排序算法面试准备
1.冒泡排序
算法思想:顾名思义,升序排序,冒泡排序每一趟会把最小的值排到最前面,像泡泡一样浮上来,代码如下(golang),算法复杂度为o(n2)
func bubbleSort(l []int) { for i := 0; i < len(l); i++ { for j := len(l) - 1; j > i; j-- { if l[j] < l[j-1] { tmp := l[j] l[j] = l[j-1] l[j-1] = tmp } } } }
2.快速排序
算法思想:快排是运用了分治的思想,选择一个基准值(通常为数组的第一个值),将数组分成两部分,左边部分是由值比基准值小的数组成,右边部分是由值比基准值大得数组成,这样大的颗粒度上数组是有序的,然后最左右部分再使用之间的分组方法,直到最终分组的长度为1,层层返回组成有序的。代码如下(golang),算法复杂度平均为O(nlog2n)
func quickSort(l []int, low, high int) { if low >= high { return } start := low end := high ref := l[low] for low < high { for low < high && l[high] > ref { high-- } if low < high { l[low] = l[high] } for low < high && l[low] <= ref { low++ } if low < high { l[high] = l[low] } } l[low] = ref quickSort(l, start, low-1) quickSort(l, low + 1, end) }
3.插入排序
算法思想:插入排序通常设想将一个数插入到一个已经排好序的数组中,只需要把这个数与排好序的元素相比,如果小于数组元素就交换,代码如下(golang),插入排序通常适合数组有序,数据量不大的场景
func insertSort(l []int) { for i := 1; i< len(l); i++ { for j := i; j > 0; j-- { if l[j] < l[j-1] { tmp := l[j] l[j] = l[j-1] l[j-1] = tmp } } } }
4.希尔排序
算法思想:希尔排序是插入排序的升级,希尔排序是将数组按照一定增量进行分组,每个分组使用插入排序,知道分组增量为1结束
func shellSort(l []int) { for gap := len(l)/2; gap > 0; gap /= 2 { for i := gap; i < len(l); i++ { for j := i; j >= gap; j -= gap { if l[j] < l[j-gap] { tmp := l[j] l[j] = l[j-gap] l[j-gap] = tmp } } } } }
5.选择排序
算法思想:选择排序是每次遍历找到最i小的数放在当前第i的位置
func selectSort(l []int) { for i := 0; i < len(l); i++ { min := i for j := i; j < len(l); j++ { if l[j] < l[min] { min = j } } tmp := l[i] l[i] = l[min] l[min] = tmp } }
6.堆排序
算法思想:堆排序是利用了堆的结构特点,堆是一个完全二叉树,有大顶堆和小顶堆两种堆,大顶堆是指所有父节点都不小于其左右子节点,小顶堆是指父节点不大于其左右子节点。以大顶堆为例,根据堆的这种特性可以知道,大顶堆的根节点是这些节点当中数值最大的。堆可以使用一维数组标识,数组下标为i的左右子节点下标left=2i+1,right=2i+2。有了这些基础知识,使用堆排序,首先先把数组组建成一个二叉树,让二叉树满足堆的特性,从下至上不断调整节点位置,形成堆,组成的堆的顶点是这些节点中最大的,把该值与最后的元素交换,将剩下的节点重复组成堆,重复之前的步骤,知道节点个数为1。
func heapSort(l []int) { n := len(l) for i := n; i > 0; i-- { for j := i/2; j > 0; j-- { top := j - 1 left := 2*j - 1 right := 2*j if left < i && l[top] < l[left] { top = left } if right < i && l[top] < l[right] { top = right } fmt.Println(top, left, right, j-1) if top != j - 1 { tmp := l[j-1] l[j-1] = l[top] l[top] = tmp } fmt.Println(l) } tmp := l[i-1] l[i-1] = l[0] l[0] = tmp } }
7.归并排序
算法思想:归并排序采用了分治的算法,将数组二分,对每个分组再次使用归并排序,然后每层将排好序的两组合并为一个有序数组返回,这种是递归实现;迭代实现思路:先将数组按最小粒度分组,即一个元素一组,相邻组来两两合并,所以初始跨度应该为2,往后依次乘2,需要额外处理剩下跨度不足的部分,代码如下
func mergeSort(l []int) { for gap := 2; gap < len(l); gap *= 2 { i := 0; for ; i + gap -1 < len(l); i++ { merge(l, i, i+gap/2-1, i + gap -1) } if i + gap/2 -1 < len(l) { merge(l, i, i+gap/2-1, len(l)-1) } } } func merge(l []int, low, mid, high int) { sortL := make([]int, high - low + 1) len1 := mid - low + 1 len2 := high - mid var i, j int for i < len1 && j < len2 { if l[low + i] < l[mid + j + 1] { sortL[i + j] = l[low + i] i++ } else { sortL[i + j] = l[mid + j + 1] j++ } } if i < len1 { for i < len1 { sortL[i+j] = l[low + i] i++ } } if j < len2 { for j < len2 { sortL[i+j] = l[mid+j + 1] j++ } } for k, v := range sortL { l[low + k] = v } } 212,1 98%
8.计数排序
算法思想:对于数值正在一定范围内的数列,可以将数值映射到一个新的数组上,这个新的数组下标与数组值一一mapping,新的数组的值代表的是这个该位置出现在原数组的次数,这样的话,只需要遍历新的数组按照顺序输出的就是有序的数组,次数代表重复填充的个数;可以在前面的基础上再进行优化,新数组的值不是简单的统计次数,而是累计他前面所有的次数,这样的话,按照原数组的顺序遍历,找的该位置的值就是排序的次序,每次找到一次需要次值减去一,表示拿出一个数,代码如下
func countSort(l []int) []int { var min int = l[0] var max int = l[0] for _, v := range l { if min > v { min = v } if max < v { max = v } } rangeL := make([]int, max-min+1) for _, v := range l { rangeL[v-min]++ } var sum int for k, v := range rangeL { sum += v rangeL[k] = sum } l2 := make([]int, len(l)) for _, v := range l { l2[rangeL[v-min]-1] = v rangeL[v-min]-- } return l2 }
9.桶排序
算法思想:桶排序是计数排序的升级,计数排序将需要排序的数列值一一映射到一个数组空间上,而桶排序是将需要排序的数列指的某一范围映射到一个桶,即一个桶对应的可能是多个待排序数,这样在大的力度上是有序的,对每个桶可以采用排序算法进行排序,这个算法可以是其他排序
10.基数排序
算法思想:基数排序也有痛的概念,基数排序分LSD(低位优先算法)和MSD(高位优先算法);举例:LSD是从低的位数开始比较,10进制,会划分10个桶,范围0-9,先按个位数进行分组,继续在按十位数进行分组,直到所有高位都是0,集合都在桶为0的组,代码如下
func radixSort(l []int) { mod := 10 level := 1 bucketList := make([][]int, mod) for len(bucketList[0]) < len(l) { bucketList = make([][]int, mod) for _, v := range l { index := (v/level)%mod bucketList[index] = append(bucketList[index], v) } level *= 10 //mod *= 10 var i int for _, bucket := range bucketList { for _, v := range bucket { l[i] = v i++ } } } }

浙公网安备 33010602011771号