作者:看那个码农
公众号:看那个码农
上期内容介绍了Go语言学习之排序算法(选择、插入、冒泡)|Go主题月
- 选择排序
- 插入排序
- 冒泡排序
本篇内容将继续带领大家走进Go语言的世界。
1.本文简介
Go语言学习之排序算法(快速、堆、希尔)
2.快速排序
快速排序是一种高效的排序算法,基本思想把大的数组拆分成小的,小的再拆分成更小的。
其原理如下
对于一组给定的数据,选择数据中的一个值做为支点,通过一轮排序后,将原数组拆分为两个部分,把大于支点的元素放在右边,小于支点的元素放在左边(升序)然后再依次对前后两部分的记录进行快速排序,递归该过程。直到序列中的所有记录均有序为止。
以数组[5,3,7,0,1,4,2]
为例,说明一下快速排序的过程。
-
第一步选择中间的值3做为支点,(基准值可以任意设置,但是选择中间值比较容易理解)此时数组变为5,[3],7,0,1,4,2
-
第二步按照顺序,将每个元素与支点相比较,形成两个部分,一个是小于“3”的[0,1,2]另外一个是大于“3”的[5,7,4]
-
第三步对[0,1,2]与[5,7,4]两个部分不断重复第一步与第二步,直到只剩下一个元素为止
-
此时左边部分已经部分划分后就已经排序好了,所以这部分可以不用管了
-
所以我们来看看支点右边部分的值[5,7,4],设置5为这部分的分支点,对这部分进行划分,左边比支点5小,右边比支点5大
-
最后形成[4],5,[7]的形式
-
支点3的左部分和右部分已经排序好,最后输出出来即可。
具体代码如下:
package main
import (
"fmt"
)
func sort(array []int,low,high int){
if(low>=high){return}
i:=low
j:=high
var index int
index = array[i]
for i<j{
for i<j && array[j]>=index{
j--
}
if i<j {
array[i]=array[j]
i++
}
for i<j&&array[i]<index{
i++
}
if(i<j){
array[j]=array[i]
j--
}
}
array[i]=index
sort(array,low,i-1)
sort(array,i+1,high)
}
func Quick(array []int) {
sort(array,0,len(array)-1)
}
func main(){
array:=[]int{1,5,3,8,0}
Quick(array)
fmt.Printf("{1,5,3,8,0}快速排序的输出为:%v",array)
}
输出为
3.希尔排序
基本原理如下:
- 首先将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少。
- 然后对每个子序列分贝进行直接插入排序,待整个待排序序列“基本有序”后。
- 最后再对所有元素进行一次直接插入排序。
以数组[13,14,94,33,82,25,59,94,65,23,45,27,73,25,39,10]为例,说明一下希尔排序的过程。
如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:
13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10
然后我们对每列进行排序:
10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45
將上述四行数字,依序接在一起时
我们得到:
[10,14,73,25,23,13,27,94,33,39,25,59,94,65,82,45]
这时10已经移至正确位置了,然后再以3为步长进行排序:
10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45
排序之后变为:
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
最后以1步长进行排序(此时就是简单的插入排序了)。
具体代码如下:
package main
import (
"fmt"
)
func shell(array []int){
llen:=len(array)
for h:=llen/2;h>0;h=h/2{
for i:=h;i<llen;i++{
temp:=array[i]
var j int
for j=i-h;j>=0;j-=h{
if(temp<array[j]){
array[j+h]=array[j]
} else{
break
}
}
array[j+h]=temp
}
}
}
func main(){
array:=[]int{10,14,73,25,23,13,27,94,33,39,25,59,94,65,82,45}
shell(array)
fmt.Printf("{10,14,73,25,23,13,27,94,33,39,25,59,94,65,82,45}\n希尔排序的输出为:\n%v",array)
输出为
4.堆排序
堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一种特殊的树形数据结构,其每个结点都有一个值,通常提到的提到的堆都是指一颗完全的二叉树,根节点的值小于(或大于)两个子节点的值,同时,根节点的两个子树也分别是一个堆。
堆排序可以说是一种利用堆的概念来排序的选择排序。
堆排序分为两种方法:
- 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
- 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
堆排序主要有两个过程
- 创建堆
- 不断交换堆顶元素与最后一个元素的位置
5.快速、堆、希尔的算法性能对比
排序方法 | 最好时间 | 平均时间 | 辅助存储 | 稳定性 |
---|---|---|---|---|
快速排序 | O(nlogn) | O(nlogn) | O(logn) | 不稳定 |
堆排序 | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
希尔排序 | O(n) | O(nlogn) | O(1) | 不稳定 |
如果你觉得这篇内容对你有帮助的话:
1、点赞支持下吧,让更多的人也能看到这篇内容
2、关注公众号:看那个码农,我们一起学习一起进步。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情