十大排序算法-Golang实现

十大排序算法

1、选择排序:

package main

import "fmt"

/*

1, 2, 5, 23, 0, 42, 8, 12

第一次
0, 2, 5, 23, 1, 42, 8, 12
|

都二次
0, 1, 5, 23, 2, 42, 8, 12
   |


都三次
0, 1, 2, 23, 5, 42, 8, 12
       |

都四次
0, 1, 2, 5, 23, 42, 8, 12
          |


都五次
0, 1, 2, 5, 8, 42, 23, 12
             |

都六次
0, 1, 2, 5, 8, 12, 23, 42
                |

都七次
0, 1, 2, 5, 8, 12, 23, 42
                    |

时间复杂度  o(n^2)

*/

func selectionSort(arr []int) {
	if arr == nil || len(arr) < 2 {
		return
	}
	n := len(arr)

	for i := 0; i < n-1; i++ {
		minindex := i
		for j := i + 1; j < n; j++ {
			if arr[j] < arr[minindex] {
				minindex = j
			}
		}
		swap(arr, i, minindex)

	}

}

func swap(arr []int, i int, j int) {
	tmp := arr[i]
	arr[i] = arr[j]
	arr[j] = tmp

}

func main() {
	arr := []int{1, 2, 5, 23, 0, 42, 8, 12}
	fmt.Println(arr)
	selectionSort(arr)
	fmt.Println(arr)

}



2、插入排序:

package main

import (
	"fmt"
)

/*
插入排序
时间复杂度 0(n^2) 空间复杂度o(1)
对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增 1 的有序表

。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。

1 4 2 5 7 0

1-》
1 4 2 5 7 0

2-》
1 2 4 5 7 0

3-》
1 2 4 5 7 0

4-》
1 2 4 5 7 0

5-》
1 2 4 5 7 0
1 2 4 5 0 7
1 2 4 0 5 7
1 2 0 4 5 7
1 0 2 4 5 7
0 1 2 4 5 7

*/

func insertSort(arr []int) {
	if arr == nil || len(arr) < 2 {
		return
	}
	n := len(arr)

	for i := 1; i < n; i++ {
		// i 只是用来处理循环次数的 ,真正的判断大小是j 和j-1
		for j := i; j > 0; j-- {
			if arr[j-1] > arr[j] {
				swap(arr, j-1, j)
			}

		}

	}

}

func swap(arr []int, i int, j int) {
	tmp := arr[i]
	arr[i] = arr[j]
	arr[j] = tmp

}

func main() {
	arr := []int{1, 4, 2, 5, 7, 0}
	fmt.Println(arr)
	insertSort(arr)
	fmt.Println(arr)
}

3、冒牌排序:

package main

import "fmt"

/*
冒牌排序
时间复杂度 0(n^2) 空间复杂度 o(1)

冒泡排序是一种基于比较和交换操作的排序算法。 每轮冒泡的过程都是从第一个元素开始,将该元素和相邻下一个元素进行比较和交换,使得较大的元素向右移动(如果该元素大于下一个元素,则两个元素交换;如果该元素小于等于下一个元素,则保持不变)。这样一来,每轮冒泡的过程都可以确定一个元素放在正确的位置上,而这个元素就是剩余元素中最大的元素,正确的位置就是剩余位置中的最右侧的位置。这个过程就像是气泡上浮一样,所以叫做冒泡排序。

1 4 2 8 7 6

第一次
1 4 2 8 7 6
...






*/

func maopao(arr []int) {
	if arr == nil || len(arr) < 2 {
		return
	}
	n := len(arr)

	for i := 0; i < n; i++ {
		for j := i + 1; j < n; j++ {
			if arr[j] < arr[i] {
				swap(arr, i, j)
				//tmp := arr[j]
				//arr[j] = arr[i]
				//arr[i] = tmp
			}
		}

	}

}

func swap(arr []int, i int, j int) {
	tmp := arr[i]
	arr[i] = arr[j]
	arr[j] = tmp

}

func main() {

	arr := []int{1, 4, 2, 8, 7, 6}
	fmt.Println(arr)
	maopao(arr)
	fmt.Println(arr)
}

4、希尔排序:


package main

import (
	"fmt"
	"log"
)

/*
希尔排序
希尔排序
希尔排序是基于直接插入排序改进的一种高效的版本,也称“缩小增量排序”。它的基本思想是 把记录按下标的一定增量分组,
对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。


原数组: [6 5 1 7 4 8 9 3 2]
第一次是 len(arr) /2 		然后进行插入排序
第二次是 len(arr) /2 /2 	然后进行插入排序
依次类推 直到  len(arr)/2/2/xx = 1 结束

[6 4 2]   [5 8]   [1 9]   [7 3]

[6 5 1 7 4 8 9 3 2]




*/

func shellSort(arr []int) {
	count := len(arr)
	fmt.Println(count)
	for d := len(arr) / 2; d > 0; d /= 2 {
		for i := d; i < len(arr); i++ {
			//log.Println(d, i)
			for j := i; j >= d; j -= d {
				log.Println(j-d, j)
				if arr[j-d] > arr[j] {
					arr[j], arr[j-d] = arr[j-d], arr[j]
				}
			}
		}

	}

}

func myselfShellSort(arr []int) {

	count := len(arr)
	log.Println(count)
	// [6 5 1 7 4 8 9 3 2]
	// [6 4 2]   [5 8]   [1 9]   [7 3]
	for h := len(arr) / 2; h > 0; h /= 2 {
		for i := h; i < count; i++ {
			for j := i; j >= h; j -= h {
				if arr[j-h] > arr[j] {
					arr[j], arr[j-h] = arr[j-h], arr[j]
				}
			}
		}

	}

}

func main() {
	arr := []int{6, 5, 1, 7, 4, 8, 9, 3, 2}
	//shellSort(arr)
	myselfShellSort(arr)
	log.Println(arr)

	arr1 := []int{2, 3}
	log.Println(arr1)
	arr1[0], arr[1] = arr1[1], arr1[0]
	log.Println(arr1)

}

5、归并排序:

package main

import "log"

/*
归并排序的采用分治思想,如果要排序一个数组,我们先把数组从中间分成前后两个部分,
然后对前后两个部分分别进行排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。核心是merge()合并函数。

*/

func guiBinSort(arr []int) []int {
	lenArr := len(arr)
	if lenArr <= 1 {
		return arr
	}
	mid := len(arr) / 2
	log.Println(mid)
	leftArr := guiBinSort(arr[:mid])
	rightArr := guiBinSort(arr[mid:])
	return merge(leftArr, rightArr)

}

func merge(leftArr []int, rightArr []int) []int {
	leftIndex, rightIndex, mergeArr := 0, 0, []int{}
	for leftIndex < len(leftArr) && rightIndex < len(rightArr) {
		if leftArr[leftIndex] <= rightArr[rightIndex] {
			mergeArr = append(mergeArr, leftArr[leftIndex])
			leftIndex += 1
		} else {
			mergeArr = append(mergeArr, rightArr[rightIndex])
			rightIndex += 1
		}
	}
	if leftIndex < len(leftArr) {
		mergeArr = append(mergeArr, leftArr[leftIndex:]...)
	}
	if rightIndex < len(rightArr) {
		mergeArr = append(mergeArr, rightArr[rightIndex:]...)

	}

	return mergeArr
}

func main() {

	arr := []int{6, 5, 1, 7, 4, 8, 9, 3, 2}
	arr = guiBinSort(arr)
	log.Println(arr)

}

6、快速排序:


package main

import (
	"log"
	"math/rand"
)

/*
快速排序(Quick Sort)是一种效率很高的排序算法,是对冒泡排序的一种改进排序算法。

快速排序首先任意选取一个数据(通常选待排序列表中的第一个数)作为基准数据,
将待排序列表中的数据分割成独立的两部分,所有比基准数据小的数都放到它左边,所有比基准数据大的数都放到它右边,
此时基准数据排序完成,第一轮快速排序完成。然后再按此方法对两部分的数据分别进行快速排序,整个排序过程可以递归进行
直到被分割的数据只有一个或零个时,递归结束,列表排序完成。

快速排序的名字起得简单直接,因为这种排序算法速度快,效率高,是处理大数据最快的排序算法之一。



*/

func quickSort(arr []int, leftIndex, rightIndex int) []int {

	if leftIndex < rightIndex {
		pivot := partion(arr, leftIndex, rightIndex)
		quickSort(arr, leftIndex, pivot-1)
		quickSort(arr, pivot+1, rightIndex)
	}
	log.Println(arr)
	return arr

}

func partion(arr []int, leftIndex, rightIndex int) int {
	i := leftIndex
	j := rightIndex

	pivot := arr[leftIndex]

	for i != j {
		for i < j && arr[j] > pivot {
			j -= 1
		}
		for i < j && arr[i] <= pivot {
			i += 1
		}
		if i < j {
			arr[i], arr[j] = arr[j], arr[i]
		}
	}
	arr[leftIndex], arr[i] = arr[i], arr[leftIndex]

	return i

}

func main() {
	arr := []int{}
	for i := 0; i <= 10; i++ {
		arr = append(arr, rand.Intn(14))
	}
	log.Println(arr)

	b := quickSort(arr, 0, len(arr)-1)
	log.Println(b)
}


7、堆排序:

package main

import (
	"log"
	"math/rand"
)

/*

时间复杂度为O(nlogn)的排序算法

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆, 注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。
每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆


堆排序的基本思想是:

将待排序序列构造成一个大顶堆
此时,整个序列的最大值就是堆顶的根节点。
将其与末尾元素进行交换,此时末尾就为最大值。
然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

*/
func heapify(arr []int, low, hight int) {
	i := low
	j := low*2 + 1
	temp := arr[i]
	for j <= hight {
		if j+1 <= hight && arr[j] < arr[j+1] {
			j += 1
		}
		if arr[j] > temp {
			arr[i] = arr[j] // 进行赋值
			i = j
			j = 2*i + 1
		} else {
			break
		}

	}
	arr[i] = temp

}

func heapSort(arr []int) []int {

	n := len(arr)

	for i := n/2 - 1; i > -1; i-- {
		log.Println("this is i", i)
		heapify(arr, i, n-1)
	}

	// 挨个出数

	for hight := n - 1; hight > -1; hight-- {
		log.Println("hight", hight)
		arr[0], arr[hight] = arr[hight], arr[0]
		heapify(arr, 0, hight-1)
	}

	return arr

}

func main() {

	arr := []int{}
	for i := 0; i < 10; i++ {
		arr = append(arr, rand.Intn(100))
	}
	log.Println(arr)
	arr = heapSort(arr)
	log.Println(arr)
}

8、桶排序:

package main

import (
	"log"
	"math/rand"
	"sort"
)

func tongSort(arr []int) []int {
	if len(arr) == 0 {
		return []int{}
	}

	// 1.找到最大值和最小值

	min := arr[0]
	max := arr[0]

	for _, element := range arr {
		if element > max {
			max = element
		}
		if element < min {
			min = element
		}
	}

	// 2构建技术捅
	defaultBuckets := 2
	bucketCount := (max-min)/defaultBuckets + 1
	buckets := make([][]int, bucketCount)
	for i := 0; i < bucketCount; i++ {
		buckets[i] = make([]int, 0)
	}

	// 3 将元素放到计数捅内计数

	for _, element := range arr {
		i := (element - min) / defaultBuckets
		buckets[i] = append(buckets[i], element)
	}
	// 4.遍历计数捅 取出元数排序

	arrIndex := 0

	for _, buckets := range buckets {
		// 捅内排序
		sort.SliceIsSorted(buckets, func(i, j int) bool {
			return buckets[i] < buckets[j]
		})
		for _, elemet := range buckets {
			arr[arrIndex] = elemet
			arrIndex++
		}
	}

	return arr
}

func main() {

	arr := []int{}
	for i := 0; i < 10; i++ {
		arr = append(arr, rand.Intn(100))
	}
	log.Println(arr)
	arr = tongSort(arr)
	log.Println(arr)
}

9、计数排序:

package main

import (
	"log"
	"math/rand"
)

func countingSort(arr []int) []int {

	// 参数处理
	if len(arr) == 0 {
		log.Println("")
		return []int{}
	}

	// 1.寻找最大值
	max := arr[0]
	for _, element := range arr {
		if element > max {
			max = element
		}
	}

	// 构建计数捅

	buckets := make([]int, max+1)
	// 3.将元素放到计数桶里面计数

	for _, element := range arr {
		buckets[element] += 1

	}

	// 4. 遍历计数桶取出元素排序

	arrIndex := 0

	for element, elementNum := range buckets {

		for elementNum > 0 && arrIndex < len(arr) {
			arr[arrIndex] = element
			elementNum--
			arrIndex++
		}

	}
	return arr
}

func main() {
	arr := []int{}
	for i := 0; i < 10; i++ {
		arr = append(arr, rand.Intn(100))
	}
	log.Println(arr)
	arr = countingSort(arr)
	log.Println(arr)
}

10、基数排序:

package main

import (
	"fmt"
	"log"
	"math/rand"
	"sort"
)

func RadixSort(arr []int) []int {
	//参数处理
	if len(arr) == 0 {
		fmt.Printf("%s\n", "err: len(arr) == 0")
		return []int{}
	}

	// 2. 构建计数捅
	defaultRadix := 10
	defaultBucketsCount := 10
	buckets := make([][]int, defaultBucketsCount)
	for i := 0; i < defaultBucketsCount; i++ {
		buckets[i] = make([]int, 0)
	}
	//3. 将元素放到计数桶里面计数

	for _, element := range arr {
		i := element / defaultRadix
		if i > defaultBucketsCount {
			i = defaultBucketsCount - 1

		} else if i < 0 {
			i = 0

		}
		buckets[i] = append(buckets[i], element)
	}

	//4. 遍历计数桶取出元素排序
	arrIndex := 0
	for _, bucket := range buckets {
		sort.Slice(bucket, func(i, j int) bool {
			return bucket[i] < bucket[j]
		})
		for _, element := range bucket {
			arr[arrIndex] = element
			arrIndex++
		}

	}
	return arr

}

func main() {
	arr := []int{}
	for i := 0; i < 10; i++ {
		arr = append(arr, rand.Intn(100))
	}
	//arr := []int{1, 2, 4, 45, 6, 6, 8, 5, 7, 67}
	log.Println(arr)
	arr = RadixSort(arr)
	log.Println(arr)
}

11、桶排序:

package main

import (
	"log"
	"math/rand"
)

/*
木桶排序

木桶排序的核心思想

关键词:分桶

将数组分到有限数量的桶子里,每个桶子再个别排序。

其实木桶排序和基数排序很相似,区别在于基数排序需要多趟桶排序,并且记录当前排序的结果。
*/

func selectMax(arr []int) (min, max int) {

	if len(arr) == 0 {
		return 0, 0
	}

	min = arr[0]
	max = arr[1]

	for i := 0; i < len(arr); i++ {
		if arr[i] > arr[0] {
			max = arr[i]
		}
		if arr[i] < arr[0] {
			min = arr[i]
		}

	}
	return min, max

}

func selectSort(arr []int) []int {
	// 复习选择排序
	lenth := len(arr)

	if lenth <= 1 {
		return arr
	}

	for i := 0; i < lenth-1; i++ {
		min := 1
		for j := i + 1; j < lenth; j++ {
			if arr[min] > arr[j] {
				min = j
			}
		}
		if i != min {
			arr[i], arr[min] = arr[min], arr[i]
		}
	}
	return arr

}

func buckSort(arr []int) []int {
	length := len(arr)
	if length <= 1 {
		return arr
	}
	num := length // 长度

	min, max := selectMax(arr)
	log.Println(max, min)

	index := 0

	buckets := make([][]int, num)

	for i := 0; i < length; i++ {
		index = arr[i] * (num - 1) / max
		buckets[index] = append(buckets[index], arr[i])

	}

	log.Println(buckets)

	// 木桶排序
	tmppose := 0

	for i := 0; i < num; i++ {
		bucketslen := len(buckets[i])
		if bucketslen > 0 {
			buckets[i] = selectSort(buckets[i])
			copy(arr[tmppose:], buckets[i])
			tmppose += bucketslen
		}
	}

	return arr
}

func main() {

	arr := []int{}

	for i := 0; i < 10; i++ {
		arr = append(arr, rand.Intn(100))
	}
	log.Println(arr)

	arr = buckSort(arr)
	log.Println(arr)
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值