golang 排序_数据结构与算法-冒泡排序-插入排序-选择排序-9

一、冒泡排序

  • 冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求,如果不满足就让它俩互换。
  • 稳定性:冒泡排序是稳定的排序算法。
  • 空间复杂度:冒泡排序是原地排序算法。
  • 时间复杂度:
    (1) 最好情况(满有序度):O(n)。
    (2) 最坏情况(满逆序度):O(n^2)。
de6f8c71c1506625c1fbef04d98a9c7d.gif

冒泡排序图解

830f19c004eace62c0821538f86d8ce1.png

冒泡排序降序golang语言实现图

func bubbleSort(array []int) {  for i := 0; i < len(array)-1; i++ {    fmt.Printf("第%d次循环:", i)    for j := i + 1; j < len(array); j++ {      fmt.Printf("数组array第%d个元素与第%d个元素比较", i, j)if array[i] > array[j] {array[i], array[j] = array[j], array[i]}fmt.Printf("第%d次冒泡结果: %v ", i, array)}}输出:/**冒泡排序old array= [4 5 6 1 3 2]第0次循环:数组 array 第0个元素与第1个元素比较数组 array 第0个元素与第2个元素比较数组 array 第0个元素与第3个元素比较数组 array 第0个元素与第4个元素比较数组 array 第0个元素与第5个元素比较第0次冒泡结果: [1 5 6 4 3 2]第1次循环:数组 array 第1个元素与第2个元素比较数组 array 第1个元素与第3个元素比较数组 array 第1个元素与第4个元素比较数组 array 第1个元素与第5个元素比较第1次冒泡结果: [1 2 6 5 4 3]第2次循环:数组 array 第2个元素与第3个元素比较数组 array 第2个元素与第4个元素比较数组 array 第2个元素与第5个元素比较第2次冒泡结果: [1 2 3 6 5 4]第3次循环:数组 array 第3个元素与第4个元素比较数组 array 第3个元素与第5个元素比较第3次冒泡结果: [1 2 3 4 6 5]第4次循环:数组 array 第4个元素与第5个元素比较第4次冒泡结果: [1 2 3 4 5 6]new array= [1 2 3 4 5 6]*/

二、插入排序

  • 插入排序将数组数据分成已排序区间和未排序区间。初始已排序区间只有一个元素,即数组第一个元素。在未排序区间取出一个元素插入到已排序区间的合适位置,直到未排序区间为空。
  • 空间复杂度:插入排序是原地排序算法。
  • 时间复杂度:
    (1) 最好情况:O(n)。
    (2) 最坏情况:O(n^2)。
    (3) 平均情况:O(n^2)(往数组中插入一个数的平均时间复杂度是O(n),一共重复n次)。
  • 稳定性:插入排序是稳定的排序算法。
eadb7fb2caf5e7e63820b0ffa816ff32.gif

插入排序图解

3eac9c25675572b58a015c570136290b.png

插入排序降序golang语言实现

func InsertSort(array []int) {  length := len(array)  if length <= 1 {return}for i := 1; i < length; i++ {    //从第二个数开始,从左向右依次取数tmp := array[i]     //下标从0开始,依次从左向右j := i - 1fmt.Printf("第%d次循环: i=%d j=%d", i, i, j)//每次取到的数都跟左侧的数做比较    //如果左侧的数比取的数大,就将左侧的数右移一位    //直至左侧没有数字比取的数大为止for ; j >= 0; j-- {fmt.Printf("temp:array[%d]=%d array[%d]=%d",i,tmp,j,array[j])if tmp < array[j] {array[j+1] = array[j]} else {fmt.Println("break")break}fmt.Println("数据移动", array, "j=", j, "i=", i)}fmt.Println("当前数组 ", array, "j=", j, "i=", i)//将取到的数插入到不小于左侧数的位置//array[j+1] = tmp//数据未移动,不替换if j+1 != i {array[j+1] = tmp}fmt.Printf("第%d次循环结果%v", i, array)}}输出:/**old array= [4 5 6 1 3 2]第1次循环: i=1 j=0 temp:array[1]=5 array[0]=4 break当前数组  [4 5 6 1 3 2] j= 0 i= 1第1次循环结果[4 5 6 1 3 2]第2次循环: i=2 j=1 temp:array[2]=6 array[1]=5 break当前数组  [4 5 6 1 3 2] j= 1 i= 2第2次循环结果[4 5 6 1 3 2]第3次循环: i=3 j=2 temp:array[3]=1 array[2]=6 数据移动 [4 5 6 6 3 2] j= 2 i= 3 temp:array[3]=1 array[1]=5 数据移动 [4 5 5 6 3 2] j= 1 i= 3 temp:array[3]=1 array[0]=4 数据移动 [4 4 5 6 3 2] j= 0 i= 3当前数组  [4 4 5 6 3 2] j= -1 i= 3第3次循环结果[1 4 5 6 3 2]第4次循环: i=4 j=3 temp:array[4]=3 array[3]=6 数据移动 [1 4 5 6 6 2] j= 3 i= 4 temp:array[4]=3 array[2]=5 数据移动 [1 4 5 5 6 2] j= 2 i= 4 temp:array[4]=3 array[1]=4 数据移动 [1 4 4 5 6 2] j= 1 i= 4 temp:array[4]=3 array[0]=1 break当前数组  [1 4 4 5 6 2] j= 0 i= 4第4次循环结果[1 3 4 5 6 2]第5次循环: i=5 j=4 temp:array[5]=2 array[4]=6 数据移动 [1 3 4 5 6 6] j= 4 i= 5 temp:array[5]=2 array[3]=5 数据移动 [1 3 4 5 5 6] j= 3 i= 5 temp:array[5]=2 array[2]=4 数据移动 [1 3 4 4 5 6] j= 2 i= 5 temp:array[5]=2 array[1]=3 数据移动 [1 3 3 4 5 6] j= 1 i= 5 temp:array[5]=2 array[0]=1 break当前数组  [1 3 3 4 5 6] j= 0 i= 5第5次循环结果[1 2 3 4 5 6]new array= [1 2 3 4 5 6]*/

三、选择排序

  • 选择排序将数组分成已排序区间和未排序区间。初始已排序区间为空。每次从未排序区间中选出最小的元素插入已排序区间的末尾,直到未排序区间为空。
  • 空间复杂度:选择排序是原地排序算法。】
  • 时间复杂度:(都是O(n^2))
    (1) 最好情况:O(n^2)。
    (2) 最坏情况:O(n^2)。
    (3) 平均情况:O(n^2)。
  • 稳定性:选择排序不是稳定的排序算法。
dde62f8385ee516eb133dfec6f60c6fa.gif

选择排序图解

34e95d41efe569914b2085b6af8db1f3.png

选择排序降序golang语言实现

func SelectSort(values []int) {length := len(values)if length <= 1 {return}for i := 0; i < length; i++ {    //初始的最小值位置从0开始,依次向右min := i //从i右侧的所有元素中找出当前最小值所在的下标for j := length - 1; j > i; j-- {if values[j] < values[min] {min = j}}fmt.Printf("i:%d minIndex:%d", i, min)//把每次找出来的最小值与之前的最小值做交换values[i], values[min] = values[min], values[i]fmt.Println(values)}}输出:/**old array= [4 5 6 1 3 2]i:0 minIndex:3[1 5 6 4 3 2]i:1 minIndex:5[1 2 6 4 3 5]i:2 minIndex:4[1 2 3 4 6 5]i:3 minIndex:3[1 2 3 4 6 5]i:4 minIndex:5[1 2 3 4 5 6]i:5 minIndex:5[1 2 3 4 5 6]new array= [1 2 3 4 5 6]*/

四、思考

  • 选择排序和插入排序的时间复杂度相同,都是O(n^2),在实际的软件开发中,为什么我们更倾向于使用插入排序而不是冒泡排序算法呢?
  • 答:从代码实现上来看,冒泡排序的数据交换要比插入排序的数据移动要复杂,冒泡排序需要3个赋值操作,而插入排序只需要1个,所以在对相同数组进行排序时,冒泡排序的运行时间理论上要长于插入排序。

下一节:数据结构与算法-归并排序-快速排序-10

上一节:数据结构与算法-递归-8


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值