本文系转载

原文地址:

http://www.limerence2017.com/2019/06/29/golang07/

前面已经介绍golang基本的语法和容器了,这一篇文章用golang实现四种排序算法,快速排序,插入排序,选择排序,冒泡排序。既可以总结前文的基础知识,又可以熟悉下golang如何实现这四种排序。

快速排序

算法介绍

假设用户输入了如下数组

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 6 | 2 | 7 | 3 | 8 | 9 |

创建变量i=0(指向第一个数据), j=5(指向最后一个数据), k=6(赋值为第一个数据的值)
我们要把所有比k小的数移动到k的左面,所以我们可以开始寻找比6小的数,从j开始,从右往左找,不断递减变量j的值,我们找到第一个下标3的数据比6小,于是把数据3移到下标0的位置,把下标0的数据6移到下标3,完成第一次比较

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 3 | 2 | 7 | 6 | 8 | 9 |

i=0 j=3 k=6
接着,开始第二次比较,这次要变成找比k大的了,而且要从前往后找了。递加变量i,发现下标2的数据是第一个比k大的,于是用下标2的数据7和j指向的下标3的数据的6做交换,数据状态变成下表:

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 3 | 2 | 6 | 7 | 8 | 9 |

i=2,j=3,k=6
接下来继续重复上边的步骤,从j开始,从右往左找比k小的,此时i=2,j=3,j再移动一位就和i相等了,此时就完成了k=6的排序,此时k=6,i和j相等都为2,6右边的数都比6大,6左边的数比6小。
接下来分别比较6左边的序列(下标从0到1)和6右边(下标从3到5)的序列,同样采用上述办法,直到所有序列都比较完成。

算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
func quickSort(slice []int, begin int, end int) {
//slice为空
if len(slice) == 0 {
return
}
//end越界
if end >= len(slice) {
return
}
//begin越界
if begin < 0 {
return
}
//下标碰头无须比较
if begin >= end {
return
}
//i从左到右,j从右到左
i := begin
j := end
//value就是比较的值
value := slice[i] for {
//从右往左比较,找到比value小的交换位置
index := j
for ; index > i; index-- {
if value > slice[index] {
slice[i] = slice[index]
//slice[index] = value
break
}
}
//更新j的位置
j = index
//从左往右比较
for index = i; index < j; index++ {
if value < slice[index] {
slice[j] = slice[index]
//slice[index] = value
break
}
}
//更新i的位置
i = index
//i和j碰头则更新value的位置,并且比较value左右序列
//fmt.Println(i, j)
if i >= j {
slice[i] = value
quickSort(slice, begin, i-1)
quickSort(slice, i+1, end)
return
}
//否则继续比较,此时i,j已经缩小范围
} }
上述算法时间复杂度达到O(nlogn)

插入排序

算法描述

假设用户输入了如下数组

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 6 | 2 | 7 | 3 | 8 | 9 |

假设从小到大排序
插入排序先从下标为1的元素2开始,比较前边下标为0的元素6,2比6小,则将6移动到2的位置,2放到6的位置

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 2 | 6 | 7 | 3 | 8 | 9 |

记下来比较下标为2的元素7,和前边0~1下标的元素对比,从后往前找,如果找到比7大的元素,则将该元素后边的序列依次后移,将7插入该元素位置
目前7不需要移动。
接下来寻找下标为3 的元素3,从下标3往前找,由于下标1,下标2的元素都比3大,所以依次后移,将3放倒下标1的位置。

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 2 | 3 | 6 | 7 | 8 | 9 |
以此类推,进行比较。

算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func insertSort(slice []int) {
if len(slice) <= 0 {
return
} for i := 1; i < len(slice); i++ {
//下标i的元素temp
temp := slice[i]
for j := i - 1; j >= 0; j-- {
//从i-1的位置往前查找,如果前边的元素比temp大
//就进行后移
if temp < slice[j] {
slice[j+1] = slice[j]
}
//否则找到比temp小的就将tmep插入。
slice[j+1] = temp
break
}
}
}

该算法时间复杂度为O(n*n)

冒泡排序

算法描述

假设用户输入了如下数组

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 6 | 2 | 7 | 3 | 8 | 9 |
冒泡排序依次比较相邻的两个元素 ,将大的元素后移即可。
先比较下标为0和下标为1的元素,6比2大,所以6和2交换位置。

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 2 | 6 | 7 | 3 | 8 | 9 |
接下来比较下标为1和下标为2的元素,6比7小所以不做交换。然后比较7和3,7比3大,7和三交换位置,以此类推,直到比较到最后一个元素

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 2 | 6 | 3 | 7 | 8 | 9 |
经过这一轮相邻元素的比较,将最大的元素9冒泡到最后的位置。
接下来重复上述步骤,从下标0开始到下标4两两比较,将第二大元素放到下标4的位置,因为下标5已经是最大元素,所以不参与比较。

算法实现

1
2
3
4
5
6
7
8
9
func bubbleSort(slice []int) {
for i := 0; i < len(slice); i++ {
for j := 0; j < len(slice)-i-1; j++ {
if slice[j] > slice[j+1] {
slice[i], slice[j+1] = slice[j+1], slice[j]
}
}
}
}

选择排序

算法描述

假设用户输入了如下数组

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 6 | 2 | 7 | 3 | 8 | 9 |
从下标0开始,比较6和其他位置的元素,找到最小的元素2和6交换位置

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 2 | 6 | 7 | 3 | 8 | 9 |
接下来从下标1开始,比较6和后边位置的元素,选择最小的和6交换位置。

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 2 | 3 | 7 | 6 | 8 | 9 |
以此类推,从下标2开始,比较7和后边的元素,选择最小的6交换位置

下标 | 0 | 1 | 2 | 3 | 4 | 5 |
数值 | 2 | 3 | 6 | 7 | 8 | 9 |
以此类推,直到下标5的位置元素都比较完。

算法实现

1
2
3
4
5
6
7
8
9
func selectSort(slice []int) {
for i := 0; i < len(slice); i++ {
for j := i + 1; j < len(slice); j++ {
if slice[i] > slice[j] {
slice[i], slice[j] = slice[j], slice[i]
}
}
}
}

该算法时间复杂度为o(n*n)

main函数中调用并测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
array := [...]int{6, 2, 7, 3, 8, 9}
slice := array[:]
quickSort(slice, 0, len(slice)-1)
fmt.Println(slice)
slice2 := array[:]
bubbleSort(slice2)
fmt.Println(slice2)
slice3 := array[:]
selectSort(slice3)
fmt.Println(slice3)
slice4 := array[:]
insertSort(slice4)
fmt.Println(slice4) }

到此为止,四种基本的比较算法已经完成,感兴趣的可以自己实现以下。
上述所有源码下载地址
源码下载地址
谢谢关注我的公众号

golang实现四种排序(快速,冒泡,插入,选择)的更多相关文章

  1. Java四种排序:冒泡,选择,插入,二分(折半插入)

    四种排序:冒泡,选择,插入,二分(折半插入) public class Test{ // public static void main(String[] args) { // Test t=new ...

  2. AJPFX关于Java中运用数组的四种排序方法

    JAVA中在运用数组进行排序功能时,一般有四种方法:快速排序法.冒泡法.选择排序法.插入排序法.快速排序法主要是运用了Arrays中的一个方法Arrays.sort()实现.冒泡法是运用遍历数组进行比 ...

  3. 【C++】四种排序算法的时间比较

    四种排序算法的时间比较 [注]clock函数对输入(用户输入)元素N排序的计时 #include<iostream> #include<time.h> using namesp ...

  4. 左神算法第一节课:复杂度、排序(冒泡、选择、插入、归并)、小和问题和逆序对问题、对数器和递归(Master公式)

    第一节课 复杂度 排序(冒泡.选择.插入.归并) 小和问题和逆序对问题 对数器 递归 1.  复杂度 认识时间复杂度常数时间的操作:一个操作如果和数据量没有关系,每次都是固定时间内完成的操作,叫做常数 ...

  5. SQL Server - 四种排序, ROW_NUMBER() /RANK() /DENSE_RANK() /ntile() over()

    >>>>英文版 (更简洁易懂)<<<< 转载自:https://dzone.com/articles/difference-between-rownum ...

  6. 【SQL】四种排序开窗函数

    一 .简单了解什么是开窗函数 什么是开窗函数,开窗函数有什么作用,特征是什么? 所谓开窗函数就是定义一个行为列,简单讲,就是在你查询的结果上,直接多出一列值(可以是聚合值或是排序号),特征就是带有ov ...

  7. Hive 中的四种排序详解,再也不会混淆用法了

    Hive 中的四种排序 排序操作是一个比较常见的操作,尤其是在数据分析的时候,我们往往需要对数据进行排序,hive 中和排序相关的有四个关键字,今天我们就看一下,它们都是什么作用. 数据准备 下面我们 ...

  8. Java 二维数组,排序、切换顺序,查表法二进制十进制,这班查找、排序(冒泡、选择)、遍历,获取最大小值(4)

    Java 二维数组,排序.切换顺序,查表法二进制十进制,折半查找.排序(冒泡.选择).遍历,获取最大小值(4)

  9. php -- 四种基础排序:冒泡、选择、插入、快速

    冒泡排序 思路分析:法如其名,就是像冒泡一样,每次从数组当中 冒一个最大的数出来. 第一轮:从第一个到最后一个冒泡比较,运行结果:最后一个最大 第二轮:从第一个到倒数第二个冒泡比较, 运行结果:最后一 ...

随机推荐

  1. Access数据库LIKE问题

    access里like的通配符用法是这样:“?”表示任何单一字符: “*”表示零个或多个字符: “#”表示任何一个数字 有时候用%作为通配符不行,需要用*号作为通配符select * from tab ...

  2. kotlin面向对象入门

    之前在学kotlin基础语法时咱们是采用三方jar包在eclipse工程下进行的,很显然这工具在实际商用中基本上很少用到了,最终是要编写android程序,所以说从这里起得更换一个更加智能更加贴近实际 ...

  3. Mybatis映射文件中数据库表列名称和POJO成员域的联系

    下面是Mybatis的SQL映射文件. <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ma ...

  4. linux高级技巧:heartbeat+lvs

    linux高级技巧:heartbeat+lvs   Heartbeat 项目是 Linux-HA 工程的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组件,在 He ...

  5. ESP8266乐鑫版本的(支持云端升级 (Boot 模式)烧写方法,(V1.5.4官方介绍如下)(BOOT模式)

    硬件平台: nodeMCU devkit核心板,带ch340g,应该是仿造的,官方是cp2102驱动,安信可科技有连接https://wiki.ai-thinker.com/esp8266/board ...

  6. CSS 中蒙版相关设置二三事

    写 蒙版 时会使用透明度,第一反应会使用 opacity 但这个会使子元素继承,蒙版内还有内容会被影响,从而会设置 background 属性的 rgba 值. 需要注意的是 rgba 和 gba 颜 ...

  7. jQuery事件之绑定事件

    语法: $(selector).bind(eventType[, eventData], handler(eventObject)); 参数解释: eventType(String): 一个包含一个或 ...

  8. LOJ #2733 [JOI2016春季合宿]Sandwiches (DP)

    题目链接 https://loj.ac/problem/2733 题解 神仙题-- 首先可以观察到一个结论: 目标块的两块小三明治一定分别是最后和倒数第二个被吃的. 由此我们可以考虑这两块谁先被吃.这 ...

  9. 2017多校联合训练2—HDU6054--Is Derek lying?(思维题)

    Is Derek lying? Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  10. HDU 5818 Joint Stacks ——(栈的操作模拟,优先队列)

    题意:有两个栈A和B,有3种操作:push,pop,merge.前两种都是栈的操作,最后一种表示的是如果“merge A B”,那么把B中的元素全部放到A中,且满足先入后出的栈原则. 分析:显然,我们 ...