排序算法实现-go语言

快速排序

// 快速排序,时间复杂度O(nlogn),空间复杂度O(logn)
func FastSort(a []int) {
	// 数量为1时,不用排序
	if len(a) < 2 {
		return
	}
	// 选择第一个作为基准
	pivot := a[0]
	// i表示大于等于基准的数的起始位置
	i := 1
	for j := 1; j < len(a); j++ {
		// 找到小于基准的数,就交换位置,并且i++
		if a[j] < pivot {
			a[i], a[j] = a[j], a[i]
			i++
		}
	}
	// 将基准放到正确的位置
	a[0], a[i-1] = a[i-1], a[0]
	// 递归调用
	FastSort(a[:i-1])
	FastSort(a[i:])
}

插入排序

// 插入排序, 时间复杂度O(n^2),空间复杂度O(1)
func InsertSort(a []int) {
	for i := 1; i < len(a); i++ {
		// 把第i个元素插入到前面已经排好序的序列[0,j-1]中
		for j := i; j > 0; j-- {
			if a[j] < a[j-1] {
				a[j], a[j-1] = a[j-1], a[j]
			}
		}
	}
}

希尔排序

// 希尔排序, 时间复杂度O(n^1.3), 空间复杂度O(1)
func ShellSort(a []int) {
	// 初始步长
	h := 1
	for h < len(a)/3 {
		h = h*3 + 1
	}
	for h >= 1 {
		for i := h; i < len(a); i++ {
			for j := i; j >= h && a[j] < a[j-h]; j -= h {
				a[j], a[j-h] = a[j-h], a[j]
			}
		}
		h /= 3
	}
}

归并排序

// 归并排序, 时间复杂度O(nlogn), 空间复杂度O(n)
func MergeSort(a []int) {
	mergeSort(a, 0, len(a)-1)
}

func mergeSort(a []int, l, r int) {
	if l >= r {
		return
	}
	mid := (l + r) / 2
	mergeSort(a, l, mid)
	mergeSort(a, mid+1, r)
	merge(a, l, mid, r)
}

func merge(a []int, l, mid, r int) {
	// 创建临时数组
	tmp := make([]int, r-l+1)
	i, j, k := l, mid+1, 0
	for i <= mid && j <= r {
		if a[i] < a[j] {
			tmp[k] = a[i]
			i++
		} else {
			tmp[k] = a[j]
			j++
		}
		k++
	}
	// 剩余部分拷贝到临时数组
	for i <= mid {
		tmp[k] = a[i]
		i++
		k++
	}
	for j <= r {
		tmp[k] = a[j]
		j++
		k++
	}
	// 拷贝到原数组
	for i := 0; i < len(tmp); i++ {
		a[l+i] = tmp[i]
	}
}

选择排序

// 选择排序, 时间复杂度O(n^2), 空间复杂度O(1)
func SelectSort(a []int) {
	for i := 0; i < len(a); i++ {
		min := i
		for j := i + 1; j < len(a); j++ {
			if a[j] < a[min] {
				min = j
			}
		}
		a[i], a[min] = a[min], a[i]
	}
}

冒泡排序

// 冒泡排序, 时间复杂度O(n^2), 空间复杂度O(1)
func BubbleSort(a []int) {
	for i := 0; i < len(a); i++ {
		for j := 0; j < len(a)-i-1; j++ {
			if a[j] > a[j+1] {
				a[j], a[j+1] = a[j+1], a[j]
			}
		}
	}
}

堆排序

// 堆排序, 时间复杂度O(nlogn), 空间复杂度O(1)
func HeapSort(a []int) {
	// 创建大顶堆
	for i := len(a) / 2; i >= 0; i-- {
		heapAdjust(a, i, len(a))
	}
	// 堆排序
	for i := len(a) - 1; i > 0; i-- {
		a[0], a[i] = a[i], a[0]
		heapAdjust(a, 0, i)
	}
}

func heapAdjust(a []int, i, length int) {
	tmp := a[i]
	for k := 2*i + 1; k < length; k = 2*k + 1 {
		if k+1 < length && a[k] < a[k+1] {
			k++
		}
		if a[k] > tmp {
			a[i] = a[k]
			i = k
		} else {
			break
		}
	}
	a[i] = tmp
}

桶排序

// 桶排序, 时间复杂度O(n), 空间复杂度O(n)
func BucketSort(a []int) {
	if a == nil {
		return
	}
	// 桶数组
	min := a[0]
	max := min
	for _, i := range a {
		if i < min {
			min = i
		}
		if i > max {
			max = i
		}
	}
	total := (max-min)/len(a) + 1
	buckets := make([][]int, total)
	// 初始化桶数组
	for i := 0; i < len(a); i++ {
		idx := (a[i] - min) / len(a)
		buckets[idx] = append(buckets[idx], a[i])
	}

	// 每个桶进行排序
	for i := 0; i < len(buckets); i++ {
		InsertSort(buckets[i]) // 使用插入排序
	}
	// 拷贝桶数组
	k := 0
	for i := 0; i < len(buckets); i++ {
		for j := 0; j < len(buckets[i]); j++ {
			a[k] = buckets[i][j]
			k++
		}
	}
}

代码验证

  • 测试代码
package sort

import (
	"math/rand"
	"testing"
)

func TestSort(t *testing.T) {
	var a []int
	for i := 10; i > 0; i-- {
		a = append(a, rand.Intn(65536)%1000)
	}

	assert := func(a, b []int) bool {
		if len(a) != len(b) {
			return false
		}
		for i := 0; i < len(a); i++ {
			if a[i] != b[i] {
				return false
			}
		}
		return true
	}
	expect := make([]int, len(a))
	copy(expect, a)
	InsertSort(expect)
	t.Logf("before sort: %v\n", a)
	t.Logf("expect: %v\n", expect)
	t.Run("FastSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		FastSort(b)
		if !assert(b, expect) {
			t.Errorf("FastSort: %v\n", b)
		}
	})
	t.Run("ShellSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		ShellSort(b)
		if !assert(b, expect) {
			t.Errorf("ShellSort: %v\n", b)
		}
	})
	t.Run("MergeSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		MergeSort(b)
		if !assert(b, expect) {
			t.Errorf("MergeSort: %v\n", b)
		}
	})
	t.Run("SelectSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		SelectSort(b)
		if !assert(b, expect) {
			t.Errorf("SelectSort: %v\n", b)
		}
	})
	t.Run("BubbleSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		BubbleSort(b)
		if !assert(b, expect) {
			t.Errorf("BubbleSort: %v\n", b)
		}
	})
	t.Run("HeapSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		HeapSort(b)
		if !assert(b, expect) {
			t.Errorf("HeapSort: %v\n", b)
		}
	})
	t.Run("BucketSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		BucketSort(b)
		if !assert(b, expect) {
			t.Errorf("BucketSort: %v\n", b)
		}
	})
	t.Run("InsertSort", func(t *testing.T) {
		b := make([]int, len(a))
		copy(b, a)
		InsertSort(b)
		if !assert(b, expect) {
			t.Errorf("InsertSort: %v\n", b)
		}
	})
}

func BenchmarkSort(b *testing.B) {
	var a []int
	for i := 10000; i > 0; i-- {
		a = append(a, rand.Intn(1000000))
	}
	b.Run("InsertSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			InsertSort(c)
		}
	})
	b.Run("ShellSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			ShellSort(c)
		}
	})
	b.Run("MergeSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			MergeSort(c)
		}
	})
	b.Run("SelectSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			SelectSort(c)
		}
	})
	b.Run("BubbleSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			BubbleSort(c)
		}
	})
	b.Run("HeapSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			HeapSort(c)
		}
	})
	b.Run("BucketSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			BucketSort(c)
		}
	})
	b.Run("FastSort", func(b *testing.B) {
		c := make([]int, len(a))
		copy(c, a)
		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			FastSort(c)
		}
	})
}
  • 测试命令
go test -v -bench=. -benchmem
  • 测试结果
=== RUN   TestSort
    sort_test.go:28: before sort: [313 439 911 211 177 638 25 932 584 340]
    sort_test.go:29: expect: [25 177 211 313 340 439 584 638 911 932]
=== RUN   TestSort/FastSort
=== RUN   TestSort/ShellSort
=== RUN   TestSort/MergeSort
=== RUN   TestSort/SelectSort
=== RUN   TestSort/BubbleSort
=== RUN   TestSort/HeapSort
=== RUN   TestSort/BucketSort
=== RUN   TestSort/InsertSort
--- PASS: TestSort (0.00s)
    --- PASS: TestSort/FastSort (0.00s)
    --- PASS: TestSort/ShellSort (0.00s)
    --- PASS: TestSort/MergeSort (0.00s)
    --- PASS: TestSort/SelectSort (0.00s)
    --- PASS: TestSort/BubbleSort (0.00s)
    --- PASS: TestSort/HeapSort (0.00s)
    --- PASS: TestSort/BucketSort (0.00s)
    --- PASS: TestSort/InsertSort (0.00s)
goos: linux
goarch: amd64
pkg: coco/sort
cpu: Intel(R) Xeon(R) Gold 6133 CPU @ 2.50GHz
BenchmarkSort
BenchmarkSort/InsertSort
BenchmarkSort/InsertSort-8                    40          27907640 ns/op               0 B/op          0 allocs/op
BenchmarkSort/ShellSort
BenchmarkSort/ShellSort-8                   9962            109687 ns/op               0 B/op          0 allocs/op
BenchmarkSort/MergeSort
BenchmarkSort/MergeSort-8                   1437            819987 ns/op         1112713 B/op       9999 allocs/op
BenchmarkSort/SelectSort
BenchmarkSort/SelectSort-8                    16          67707251 ns/op               0 B/op          0 allocs/op
BenchmarkSort/BubbleSort
BenchmarkSort/BubbleSort-8                    16          63796250 ns/op               0 B/op          0 allocs/op
BenchmarkSort/HeapSort
BenchmarkSort/HeapSort-8                    1987            567119 ns/op               0 B/op          0 allocs/op
BenchmarkSort/BucketSort
BenchmarkSort/BucketSort-8                  1996            589339 ns/op          206690 B/op        801 allocs/op
BenchmarkSort/FastSort
BenchmarkSort/FastSort-8                     100          36424629 ns/op               0 B/op          0 allocs/op
PASS
ok      coco/sort       13.064s
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值