入门Go语言排序算法详解
Posted qinziteng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了入门Go语言排序算法详解相关的知识,希望对你有一定的参考价值。
1、冒泡排序
冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的两个元素,并在必要时交换它们的位置,直到没有任何一对元素需要交换为止。该算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
package main
import "fmt"
// 我们定义了一个名为`bubbleSort`的函数,该函数接收一个整数数组`arr`作为参数。
// 在函数内部,我们首先获取数组的长度`n`,然后使用两个嵌套的循环来遍历数组。在内部循环中,
// 我们比较相邻的两个元素,如果前一个元素比后一个元素大,则交换它们的位置。最后,
// 当内部循环结束时,我们可以确定该数组已经排好序。
func bubbleSort(arr []int)
n := len(arr)
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+1], arr[j]
func main()
arr := []int64, 25, 12, 22, 11
bubbleSort(arr)
fmt.Println("Sorted array:", arr)
代码输出内容:
Sorted array: [11 12 22 25 64]
第二个案例:
package main
import "fmt"
func main()
s := []int9, 8, 7, 6, 5, 4, 3, 2, 1, 0
var temp int
for i := 0; i < len(s)-1; i++ // 比较9次
for j := 0; j < len(s)-1-i; j++
if s[j] > s[j+1]
temp = s[j]
s[j] = s[j+1]
s[j+1] = temp
fmt.Println(s)
代码输出内容:
[0 1 2 3 4 5 6 7 8 9]
总结:
- 从切片头部开始,不断比较相邻的两个元素的大小,让较大的元素逐渐往后移动(交换两个元素的值),直到切片的末尾。经过第一轮的比较,就可以找到最大的元素,并移动至最后一个位置。
- 第一轮结束后,继续第二轮。仍然从切片头部开始比较,让较大的元素逐渐往后移动,直到切片的倒出第二个元素为止。经过第二轮的比较,就可以找到次大的元素,并将它放到倒数第二的位置。
- 以此类推,进行n-1(n切片的长度)轮,"冒泡"后,就可以将所有的元素都排序好。
2、选择排序
选择排序(Selection Sort)是一种简单直观的排序算法,其基本思想是:首先在未排序的数列中找到最小(大)元素,然后将其存放到数列的起始位置,接着再从剩余未排序的元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
package main
import "fmt"
func main()
s := []int9, 8, 7, 6, 5, 4, 3, 2, 1, 0
for j := 0; j < len(s)-1; j++
min := s[j]
minIndex := j
for i := j + 1; i < len(s); i++
if min > s[i]
min = s[i]
minIndex = i
if minIndex != j
s[j], s[minIndex] = s[minIndex], s[j]
fmt.Println(s)
代码输出内容:
[0 1 2 3 4 5 6 7 8 9]
总结:
- 第一趟排序在所有待排序的n个记录中选出关键字最小的记录,将它与列表中第一个进行交换,使关键字最小的记录在数据表最前端。
- 第二趟在剩下的n-1记录中在选出关键字最小的记录,将其与数据表中的第二个记录交换位置,使关键字次小的记录处于数据表第二个位置。
- 重复这样的操作,最终实现数据表的升序排序。
希尔排序ShellSort算法详解Java/Go/Python/JS/C不同语言实现
【希尔排序算法详解】Java/Go/Python/JS/C不同语言实现
说明
希尔排序(Shell Sort)是插入排序的一种改进版,也称递减增量排序算法(Diminishing Increment Sort),其实质是将数列分组,然后再按插入算法分别排序,因DL.Shell于1959年提出而得名。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
- 插入排序在对几乎已经排好序的数据操作时效率较高,可以达到线性排序的效率。
- 但插入排序对于一般不规则数列来说是低效的,因为插入排序每次只能挪动一位数据。
实现过程
- 定义一个分组间隔(步长),分组规则可以是1/2数组长度或其他。
- 按步长间隔取出数字组成子序列,针对子序列按照插入算法进行排序。
- 步长按照分组规则缩量递减,继续新一轮子序列的插入排序。
- 待步长为1时,再对全体元素进行一次插入排序,排序完成。
步长间隔怎么取呢?在希尔的原稿中建议的初始步长是N/2,就是将每一次排序分成两半,这样取步长在大多数情况下会比插入排序好,但也不是最好。
示意图
性能分析
平均时间复杂度:O(Nlog^2N)
最差时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:不稳定
复杂性:较复杂
代码
Java
// java希尔排序算法 class ShellSort /* 1. 希尔排序标准版,基于插入排序进行分组排序,步长按1/2缩减。 */ static int[] shellSort1(int arr[]) int len = arr.length; // 设置分组增量值(步长)为1/2的数组长度 int gap = len / 2; // 根据步长得到子序列如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (int i = gap; i < len; i++) int current = arr[i]; int j = i; // 根据步长得到子序列,对子序列按照插入排序 while (j >= gap && current < arr[j - gap]) System.out.println("gap=" + gap + " i=" + i + " j=" + j + " arr:" + Arrays.toString(arr)); arr[j] = arr[j - gap]; j -= gap; // 交换当前项 arr[j] = current; // 缩短一半步长 gap = gap / 2; return arr; /* 2. 希尔排序,基于插入排序进行分组排序,步长按3倍递减。 */ public static int[] shellSort2(int[] arr) int len = arr.length; int gap = 1; // 初始步长按3倍递增,小于1/3数组长度 while (gap < len / 3) gap = gap * 3 + 1; // 如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (int i = gap; i < len; i++) int current = arr[i]; int j = i - gap; // 根据步长得到子序列,对子序列按照插入排序 for (; j >= 0 && arr[j] > current; j -= gap) System.out.println("gap=" + gap + " i=" + i + " j=" + j + " arr:" + Arrays.toString(arr)); arr[j + gap] = arr[j]; arr[j + gap] = current; // 步长按3倍缩减 gap /= 3; return arr;
Python
# python希尔排序算法 # 1. 希尔排序标准版,基于插入排序进行分组排序,步长按1/2缩减。 def shell_sort1(arr): size = len(arr) # 设置分组增量值(步长)为1/2的数组长度 gap = size // 2 # 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while gap > 0: for i in range(gap, size): current = arr[i] j = i # 对子序列按照插入排序 while j >= gap and current < arr[j - gap]: print(\'gap=\' + str(gap) + \' i=\' + str(i) + \' j-gap=\' + str(j - gap) + \' j=\' + str(j)) arr[j] = arr[j - gap] j -= gap # 交换当前项 arr[j] = current # 调整步长为1/2 gap = gap // 2 return arr # 2. 希尔排序,基于插入排序进行分组排序,步长按3倍递减。 def shell_sort2(arr): size = len(arr) gap = 1 # 初始步长按3倍递增,小于1/3数组长度 while gap < (size // 3): gap = gap * 3 + 1 # 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while (gap > 0): for i in range(gap, size): current = arr[i] j = i - gap # 对子序列按照插入排序s while j >= 0 and arr[j] > current: print(\'gap=\' + str(gap) + \' i=\' + str(i) + \' j=\' + str(j) + \' j+gap=\' + str(j + gap)) arr[j + gap] = arr[j] j -= gap # 还原当前位置 arr[j + gap] = current # 步长按3倍缩减 gap = gap // 3 return arr
Go
// go语言希尔排序算法 // 1. 希尔排序标准版,基于插入排序进行分组排序,步长按1/2缩减。 func shellSort1(arr []int) []int var arrLen int = len(arr) // 设置分组间隔 var gap int = (arrLen / 2) // 如果间隔大于0,则表示还可以继续分 for gap > 0 for i := 0; i < arrLen; i++ var current = arr[i] var j = i // 分组按照插入排序 for j >= gap && current < arr[j-gap] fmt.Println("gap=", gap, "i=", i, " j-gap=", j-gap, " j=", j) arr[j] = arr[j-gap] j -= gap // 交换当前项 arr[j] = current // 调整步长为1/2 gap = (gap / 2) return arr // 2. 希尔排序,基于插入排序进行分组排序,步长按3倍递减。 func shellSort2(arr []int) []int var arrLen int = len(arr) // 设置分组间隔 var gap int = 1 // 初始步长按3倍递增,小于1/3数组长度 for gap < (arrLen / 3) gap = gap*3 + 1 // 如果间隔大于0,则表示还可以继续分 for gap > 0 for i := gap; i < arrLen; i++ var current = arr[i] var j = i - gap // 对子序列按照插入排序 for ; j >= 0 && arr[j] > current; j -= gap fmt.Println("gap=", gap, "i=", i, " j=", j, " j+gap=", (j + gap)) arr[j+gap] = arr[j] arr[j+gap] = current // 步长按3倍缩减 gap = (gap / 3) return arr
JS
// js希尔排序算法 /* 1. 希尔排序标准版,基于插入排序进行分组排序,步长按1/2缩减。 */ function shellSort1(arr) const len = arr.length // 设置分组增量值(步长)为1/2的数组长度 let gap = Math.floor(len / 2) // 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (let i = 0; i < len; i++) const current = arr[i] let j = i // 对子序列按照插入排序 while (j >= gap && current < arr[j - gap]) console.log(\'gap=\' + gap + \' i=\' + i + \' j=\' + j + \' (j - gap)=\' + (j - gap), \'arr:\', arr) arr[j] = arr[j - gap] j -= gap // 交换当前项 arr[j] = current // 调整步长为1/2 gap = Math.floor(gap / 2) return arr /* 2. 希尔排序,基于插入排序进行分组排序,步长按3倍递减。 */ function shellSort2(arr) const len = arr.length let gap = 1 // 初始步长按3倍递增,小于1/3数组长度 while (gap < Math.floor(len / 3)) gap = gap * 3 + 1 // 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (let i = gap; i < len; i++) const current = arr[i] let j = i - gap // 对子序列按照插入排序 for (; j >= 0 && arr[j] > current; j -= gap) console.log(\'gap=\' + gap + \' i=\' + i + \' j=\' + j + \' (j + gap)=\' + (j + gap), \'arr:\', arr) arr[j + gap] = arr[j] arr[j + gap] = current // 步长按3倍缩减 gap = Math.floor(gap / 3) return arr
TS
// TS希尔排序算法 // 1. 希尔排序,基于插入排序进行了分组排序 class ShellSort shellSort1(arr: number[]): number[] const len = arr.length // 设置分组增量值(步长)为1/2的数组长度 let gap = Math.floor(len / 2) // 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (let i = 0; i < len; i++) const current = arr[i] let j = i // 对子序列按照插入排序 while (j >= gap && current < arr[j - gap]) console.log( \'gap=\' + gap + \' i=\' + i + \' j=\' + j + \' (j - gap)=\' + (j - gap), \'arr:\', arr ) arr[j] = arr[j - gap] j -= gap // 交换当前项 arr[j] = current // 调整步长为1/2 gap = Math.floor(gap / 2) return arr /* 2. 希尔排序,基于插入排序进行分组排序,步长按3倍递减。 */ shellSort2(arr: number[]): number[] const len = arr.length let gap = 1 // 初始步长按3倍递增,小于1/3数组长度 while (gap < Math.floor(len / 3)) gap = gap * 3 + 1 // 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (let i = gap; i < len; i++) const current = arr[i] let j = i - gap // 对子序列按照插入排序 for (; j >= 0 && arr[j] > current; j -= gap) console.log( \'gap=\' + gap + \' i=\' + i + \' j=\' + j + \' (j + gap)=\' + (j + gap), \'arr:\', arr ) arr[j + gap] = arr[j] arr[j + gap] = current // 步长按3倍缩减 gap = Math.floor(gap / 3) return arr
C
// C语言希尔排序算法 /* 1. 希尔排序标准版,基于插入排序进行分组排序,步长按1/2缩减。 */ float *shell_sort1(float arr[], int len) // 设置分组增量值(步长)为1/2的数组长度 int gap = len / 2; // 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (int i = 0; i < len; i++) float current = arr[i]; int j = i; // 对子序列按照插入排序 while (j >= gap && current < arr[j - gap]) arr[j] = arr[j - gap]; j -= gap; // 交换当前项 arr[j] = current; // 调整步长为1/2 gap = gap / 2; return arr; /* 2. 希尔排序标准版,基于插入排序进行分组排序,步长按1/2缩减。 */ int *shell_sort2(int arr[], int len) // 设置分组增量值(步长)为1/2的数组长度 int gap = 1; // 初始步长按3倍递增,小于1/3数组长度 while (gap < len / 3) gap = gap * 3 + 1; // 根据步长得到子序列,如果间隔大于0,则表示还可以继续分组 while (gap > 0) for (int i = 0; i < len; i++) int current = arr[i]; int j = i - gap; // 对子序列按照插入排序 for (; j >= 0 && arr[j] > current; j -= gap) arr[j + gap] = arr[j]; arr[j + gap] = current; // 步长按3倍缩减 gap = (gap / 3); return arr;
链接
希尔排序算法源码:https://github.com/microwind/algorithms/tree/master/sorts/shellsort
以上是关于入门Go语言排序算法详解的主要内容,如果未能解决你的问题,请参考以下文章