go实现十大经典排序

排序代码:

package sort

import (
	"math"
	"math/rand"
	"strconv"
	"time"
)

func NewNums(length int, maxNum int) []int {
	nums := make([]int, length)
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < length; i++ {
		nums[i] = rand.Intn(maxNum)
	}
	return nums
}

func BubbleSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	for i:=0;i<len(nums);i++ {
		for j:=1;j<len(nums)-i;j++ {
			if nums[j-1] > nums[j] {
				nums[j-1], nums[j] = nums[j], nums[j-1]
			}
		}
	}
	return nums
}

func SelectSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	for i:=0;i<len(nums);i++ {
		for j:=i+1;j<len(nums);j++ {
			if nums[i] > nums[j] {
				nums[i], nums[j] = nums[j], nums[i]
			}
		}
	}
	return nums
}

func InsertSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	for i:=1;i<len(nums);i++ {
		tmp := nums[i]
		j := i-1
		for j>=0 && nums[j] > tmp {
			nums[j+1] = nums[j]
			j--
		}
		nums[j+1] = tmp
	}
	return nums
}

func HellSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	for step:=len(nums)/2; step>0; step=step/2 {
		for i:=step; i<len(nums); i++ {
			for j:=i; j-step >=0 && nums[j-step] > nums[j]; j=j-step {
				nums[j-step], nums[j] = nums[j], nums[j-step]
			}
		}
	}
	return nums
}

func MergeSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	merge := func(left []int, right []int) []int {
		res := make([]int, len(left)+len(right))
		var lIndex, rIndex, index int
		for lIndex < len(left) && rIndex < len(right) {
			if left[lIndex] < right[rIndex] {
				res[index] = left[lIndex]
				lIndex++
			} else {
				res[index] = right[rIndex]
				rIndex++
			}
			index++
		}
		copy(res[index:], left[lIndex:])
		copy(res[index+len(left)-lIndex:], right[rIndex:])
		return res
	}
	var sort func(nums []int) []int
	sort = func(nums []int) []int {
		if len(nums) <= 1 {
			return nums
		}
		mid := len(nums)/2
		left := sort(nums[:mid])
		right := sort(nums[mid:])
		return merge(left, right)
	}
	return sort(nums)
}

func MergeSortII(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	merge := func(left []int, right []int) []int {
		res := make([]int, len(left)+len(right))
		var lIndex, rIndex, index int
		for lIndex < len(left) && rIndex < len(right) {
			if left[lIndex] < right[rIndex] {
				res[index] = left[lIndex]
				lIndex++
			} else {
				res[index] = right[rIndex]
				rIndex++
			}
			index++
		}
		copy(res[index:], left[lIndex:])
		copy(res[index+len(left)-lIndex:], right[rIndex:])
		return res
	}
	var sort_iter func(nums []int) []int
	sort_iter = func(nums []int) []int {
		i := 1 //子序列大小初始1
		res := make([]int, 0)
		// i控制每次划分的序列长度
		for i < len(nums) {
			// j根据i值执行具体的合并
			j := 0
			// 按顺序两两合并,j用来定位起始点
			// 随着序列翻倍,每次两两合并的数组大小也翻倍
			for j < len(nums) {
				if j+2*i > len(nums) {
					res = merge(nums[j:j+i], nums[j+i:])
				} else {
					res = merge(nums[j:j+i], nums[j+i:j+2*i])
				}
				// 通过index控制每次将合并的数据填入nums中
				// 重填入的次数和合并及二叉树的高度相关
				index := j
				for _, v := range res {
					nums[index] = v
					index++
				}
				j = j + 2*i
			}
			i *= 2
		}
		return nums
	}
	return sort_iter(nums)
}

func QuickSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	var quick func(left int, right int) []int
	quick = func(left int, right int) []int {
		if left > right {
			return nil
		}
		i, j, pivot := left, right, nums[left]
		for i < j {
			for i<j && nums[j] >= pivot {
				j--
			}
			for i<j && nums[i] <= pivot {
				i++
			}
			nums[i], nums[j] = nums[j], nums[i]
		}
		nums[i], nums[left] = nums[left], nums[i]
		quick(left, i-1)
		quick(i+1, right)
		return nums
	}
	return quick(0, len(nums)-1)
}

func HeapSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	// large heap
	heapify := func(nums []int, root int, end int) {
		for {
			child := root*2 + 1
			if child > end {
				return
			}
			if child < end && nums[child] <= nums[child+1] {
				child++
			}
			if nums[root] > nums[child] {
				return
			}
			nums[root], nums[child] = nums[child], nums[root]
			root = child
		}
	}
	end := len(nums)-1
	for i:=end/2;i>=0;i-- {
		heapify(nums, i, end)
	}
	for i:=end;i>0;i-- {
		nums[0], nums[i] = nums[i], nums[0]
		end--
		heapify(nums, 0, end)
	}
	return nums
}

func SmallHeapSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	// min heap
	heapify := func(nums []int, root int, end int) {
		for {
			child := root*2 + 1
			if child > end {
				return
			}
			if child < end && nums[child] >= nums[child+1] {
				child++
			}
			if nums[root] < nums[child] {
				return
			}
			nums[root], nums[child] = nums[child], nums[root]
			root = child
		}
	}
	end := len(nums)-1
	for i:=end/2;i>=0;i-- {
		heapify(nums, i, end)
	}
	for i:=end;i>=0;i-- {
		nums[0], nums[i] = nums[i], nums[0]
		end--
		heapify(nums, 0, end)
	}
	return nums
}

func TopKHeap(nums []int, k int) []int {
	if len(nums) < 2 {
		return nums
	}
	heapify := func(nums []int, root int, end int) {
		for {
			child := root*2 + 1
			if child > end {
				return
			}
			if child < end && nums[child] >= nums[child+1] {
				child++
			}
			if nums[root] < nums[child] {
				return
			}
			nums[root], nums[child] = nums[child], nums[root]
			root = child
		}
	}
	heap := nums[:k]
	end := len(nums)-1
	for i:=k/2;i>=0;i-- {
		heapify(heap, i, k-1)
	}
	for i:=k;i<=end;i++ {
		if nums[i] > heap[0] {
			heap[0] = nums[i]
			heapify(heap, 0, k-1)
		}
	}
	for i:=k-1;i>=0;i-- {
		heap[0], heap[i] = heap[i], heap[0]
		k--
		heapify(heap, 0, k)
	}
	return heap
}

func CountSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	findMinMax := func(nums []int) (int, int) {
		min, max := nums[0], nums[0]
		for i:=0;i<len(nums);i++ {
			if nums[i] > max {
				max = nums[i]
			}
			if nums[i] < min {
				min = nums[i]
			}
		}
		return min, max
	}
	min, max := findMinMax(nums)

	tmpNums := make([]int, max-min+1)
	for i:=0;i<len(nums);i++ {
		tmpNums[nums[i]-min]++
	}
	j := 0
	for i:=0;i<len(nums);i++ {
		for tmpNums[j] == 0 {
			j++
		}
		nums[i] = j+min
		tmpNums[j]--
	}

	return nums
}

func RadixSort(nums []int) []int {
	if len(nums) < 2 {
		return nums
	}
	max := nums[0]
	for i:=0;i<len(nums);i++ {
		if nums[i] > max {
			max = nums[i]
		}
	}

	for i:=0;i<len(strconv.Itoa(max));i++ {
		buckets := make([][]int, 10)

		for j:=0;j<len(nums);j++ {
			n := nums[j] / int(math.Pow10(i)) % 10
			buckets[n] = append(buckets[n], nums[j])
		}

		m := 0
		for k:=0;k<len(buckets);k++ {
			for p:=0;p<len(buckets[k]);p++ {
				nums[m] = buckets[k][p]
				m++
			}
		}
	}
	return nums
}

func BucketSort(nums []int) []int {
	if len(nums) < 2 {return nums}
	min, max := nums[0], nums[0]
	for i:=0;i<len(nums);i++ {
		if nums[i] > max {
			max = nums[i]
		}
		if nums[i] < min {
			min = nums[i]
		}
	}

	bucketSize := 5
	bucketCap := (max-min)/bucketSize + 1
	buckets := make([][]int, bucketCap)

	for i:=0;i<bucketCap;i++ {
		buckets[i] = make([]int, 0)
	}

	for i:=0;i<len(nums);i++ {
		n := (nums[i]-min) / bucketSize
		buckets[n] = append(buckets[n], nums[i])
	}

	index := 0
	for _, bucket := range buckets {
		// sort in single bucket
		bucket = func(nums []int) []int {
			for i:=0;i<len(nums);i++ {
				tmp := nums[i]
				j := i-1
				for j>=0 && nums[j] > tmp {
					nums[j+1] = nums[j]
					j--
				}
				nums[j+1] = tmp
			}
			return nums
		}(bucket)

		for _, num := range bucket {
			nums[index] = num
			index++
		}
	}
	return nums
}

单元测试代码:

package sort

import (
	"log"
	"sort"
	"testing"
)

func TestBubbleSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = BubbleSort(numsCp)
	log.Printf("Bubble sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Bubble sort is not right!")
		}
	}
	log.Println("Bubble sort passed.")
}

func TestSelectSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = SelectSort(numsCp)
	log.Printf("Select sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Select sort is not right!")
		}
	}
	log.Println("Select sort passed.")
}

func TestInsertSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = InsertSort(numsCp)
	log.Printf("Insert sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Insert sort is not right!")
		}
	}
	log.Println("Insert sort passed.")
}

func TestHellSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = HellSort(numsCp)
	log.Printf("Hell sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Hell sort is not right!")
		}
	}
	log.Println("Hell sort passed.")
}

func TestMergeSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = MergeSort(numsCp)
	log.Printf("Merge sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Merge sort is not right!")
		}
	}
	log.Println("Merge sort passed.")
}

func TestMergeSortII(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = MergeSortII(numsCp)
	log.Printf("MergeII sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("MergeII sort is not right!")
		}
	}
	log.Println("MergeII sort passed.")
}

func TestQuickSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = QuickSort(numsCp)
	log.Printf("Quick sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Quick sort is not right!")
		}
	}
	log.Println("Quick sort passed.")
}

func TestHeapSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Ints(nums)
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = HeapSort(numsCp)
	log.Printf("Heap sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Heap sort is not right!")
		}
	}
	log.Println("Heap sort passed.")
}

func TestSmallHeapSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] > nums[j]
	})
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = SmallHeapSort(numsCp)
	log.Printf("Heap sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Heap sort is not right!")
		}
	}
	log.Println("Heap sort passed.")
}

func TestTopKHeap(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] > nums[j]
	})
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = TopKHeap(numsCp, 10)
	log.Printf("TopHeap sorted nums: %v\n", numsCp)
}

func TestCountSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] < nums[j]
	})
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = CountSort(numsCp)
	log.Printf("Count sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Count sort is not right!")
		}
	}
	log.Println("Count sort passed.")
}

func TestRadixSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] < nums[j]
	})
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = RadixSort(numsCp)
	log.Printf("Radix sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Radix sort is not right!")
		}
	}
	log.Println("Radix sort passed.")
}

func TestBucketSort(t *testing.T) {
	nums := NewNums(10, 100)
	log.Printf("origin nums: %v\n", nums)
	numsCp := make([]int, len(nums))
	copy(numsCp, nums)
	sort.Slice(nums, func(i, j int) bool {
		return nums[i] < nums[j]
	})
	log.Printf("system sorted nums: %v\n", nums)
	numsCp = BucketSort(numsCp)
	log.Printf("Bucket sorted nums: %v\n", numsCp)
	for i:=0;i<len(nums);i++ {
		if nums[i] != numsCp[i] {
			t.Fatal("Bucket sort is not right!")
		}
	}
	log.Println("Bucket sort passed.")
}

posted on 2022-05-11 08:34  进击的davis  阅读(30)  评论(0编辑  收藏  举报

导航