clllll  

仓库码云地址

远程仓库地址

声明

本人是个菜鸟,不一定对哦。。。
我只测试一个是正确的。还有对于数组只有 一个数或者nil的不考虑。

先写一个公共的方法。替换俩个位置的数。

basicsort/tools.go

package basicsort

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

01 冒泡排序

俩俩比较,大的往后冒。
俩个for循环,每次循环排好一个最大的数
basicsort/01_bubble_sort.go

package basicsort

//函数名首字母大写才能被其他包引用。
func Bubble_sort(arr []int) {
	//冒泡排序
	for i := len(arr) - 1; i > 0; i-- {
		for j := 0; j <= i-1; j++ {
			if arr[j] > arr[j+1] {
				swap(arr, j, j+1)
			}
		}
	}
}
  • main.go 测试
package main

import (
	"fmt"
	"go-alg/basicsort"
)

func main() {
	arr := []int{3, 2, 4, 5, 1, 6, 9, 8, 7, 0}
	basicsort.Bubble_sort(arr)
	fmt.Println(arr)
}

02 选择排序

也是俩层for循环,也是俩俩比较。但是只是记录最大的索引,循环完之后。最大的索引和当前循环到的索引替换。

package basicsort

func Select_sort(arr []int) {

	for i := len(arr) - 1; i > 0; i-- {
		currnet_max_index := i //记录当前循环最大的索引
		for j := 0; j < i; j++ {
			if arr[j] > arr[currnet_max_index] {
				currnet_max_index = j
			}
		}
		swap(arr, i, currnet_max_index) //当前索引交换最大索引 
	}
}

03 插入排序

就相当于打扑克,拿牌一样。前面都是已排好的序,新拿的牌从最后一张开始比较,直到找到自己插入的位置。
默认第一张是已排序。从第二张开始插入。

package basicsort

func Insert_sort(arr []int) {

	for i := 1; i < len(arr); i++ {
		insert_value := arr[i] // 要插入的值
		var j int // j要声明到for循环之外,这是最后确定要插入的索引位置。 python不需要。
		for j = i - 1; j >= 0; j-- {
			if arr[j] > insert_value {
				arr[j+1] = arr[j] //当前牌往后移一个。直接赋值
			} else {
				break
			}
		}
		arr[j+1] = insert_value //插入到指定位置,因为for循环有一个减一操作。所以这里应该是j+1才是要插入的位置
	}
}

04 希尔排序

优化的插入排序。插入排序的插入 步数是一个一个。希尔排序是一次就往前插好几个位置。慢慢回归到1. 加快 数快速移动到自己的位置。
一般是从 n/3 还是 n/2 开始 ,每次除2,慢慢到1.
多了个gap循环,插入排序多了个gap参数。每次插入比较 不是1而是gap了。

package basicsort

func Shell_sort(arr []int) {

	for gap := len(arr) / 2; gap >= 1; gap /= 2 {
		Insert_sort_with_gap(arr, gap)
	}
}

func Insert_sort_with_gap(arr []int, gap int) {

	for i := 1; i < len(arr); i++ {
		insert_value := arr[i] // 要插入的值
		var j int              // j要声明到for循环之外,这是最后确定要插入的索引位置。 python不需要。
		for j = i - gap; j >= 0; j -= gap {
			if arr[j] > insert_value {
				arr[j+gap] = arr[j] //当前牌往后移一个。直接赋值
			} else {
				break
			}
		}
		arr[j+gap] = insert_value //插入到指定位置,因为for循环有一个减一操作。所以这里应该是j+gap才是要插入的位置
	}
}

05 归并排序

分而治之,
先划分到只有1个数的数组,然后俩俩合并。
是个递归函数。
会新增内存。

package basicsort

import "fmt"

func Merge_sort(arr []int) {

	if len(arr) <= 1 {
		return
	}
	mid := len(arr) / 2

	left_arr := make([]int, len(arr[:mid]))
	right_arr := make([]int, len(arr[mid:]))
	copy(left_arr, arr[:mid])
	copy(right_arr, arr[mid:])

	fmt.Println("left_arr:", left_arr)
	fmt.Println("right_arr:", right_arr)

	Merge_sort(left_arr)  // 左边数组排序
	Merge_sort(right_arr) //右边数组排序
	l := 0                // 左边数组的索引
	r := 0                // 右边数组的索引

	c := 0 // 原始数组的索引

	// 开始合并左边数组和右边数组
	for l < len(left_arr) && r < len(right_arr) {

		//比较当前俩个数组哪个小。
		if left_arr[l] <= right_arr[r] {
			arr[c] = left_arr[l]
			l++
		} else {
			arr[c] = right_arr[r]
			r++
		}
		c++
	}
	//走到这说明其中一个数组肯定没数了。把另一个数组的数依次合并到主数组

	for l < len(left_arr) {
		arr[c] = left_arr[l]
		c++
		l++
	}

	for r < len(right_arr) {
		arr[c] = right_arr[r]
		c++
		r++
	}

}

06 快速排序

也是递归和分而治之的思想

找一个基准数,把一个数组分成俩块,左边都是小于基准数,右边都是大于基准数的。

然后递归调用自己.

因数的顺序对时间复杂度影响较大。优化:每次随机选择基准数。

我做不到出来了;

package basicsort

func Quick_sort2(arr []int) {

	help(arr, 0, len(arr)-1)
}

func help(arr []int, l int, r int) {

	if l < r {
		less, more := partation2(arr, l, r)
		help(arr, l, less-1)
		help(arr, more+1, r)
	}

}

func partation2(arr []int, l int, r int) (int, int) {
	less := l - 1
	more := r

	for l < more {
		if arr[l] < arr[r] {
			less++
			swap(arr, less, l)
			l++
		} else if arr[l] > arr[r] {
			more--
			swap(arr, more, l)
		} else {
			l++
		}
	}
	swap(arr, more, r)
	return less + 1, more
}
posted on 2023-01-21 18:51  llcl  阅读(19)  评论(0编辑  收藏  举报