数据结构和算法-Go泛型实现:第二章算法效率、排序与搜索-2. 排序算法

51 阅读3分钟

2. 排序算法 (Sorting Algorithms)

2.1 冒泡排序 (Bubble Sort)

冒泡排序是一种简单的排序算法,它通过重复地遍历列表,比较相邻的元素并根据需要交换它们来逐步排序。虽然冒泡排序在大多数情况下不是最有效的,但它对于理解基本排序原理很有帮助。

泛型实现:

package main

import "fmt"

// BubbleSort 泛型函数实现
func BubbleSort[T any](arr []T, less func(T, T) bool) {
	n := len(arr)
	for i := 0; i < n-1; i++ {
		for j := 0; j < n-i-1; j++ {
			if less(arr[j+1], arr[j]) {
				arr[j], arr[j+1] = arr[j+1], arr[j]
			}
		}
	}
}

func main() {
	arr := []int{5, 3, 8, 4, 2}
	BubbleSort(arr, func(a, b int) bool {
		return a < b
	})
	fmt.Println("Sorted array:", arr)
}

2.2 快速排序 (Quick Sort)

快速排序是一种高效的分治排序算法。它通过选择一个“枢轴”元素并将其他元素重新排序,使得所有小于枢轴的元素位于枢轴之前,所有大于枢轴的元素位于枢轴之后,然后递归地排序子数组。

泛型实现:

package main

import "fmt"

// QuickSort 泛型函数实现
func QuickSort[T any](arr []T, less func(T, T) bool) {
	if len(arr) <= 1 {
		return
	}
	pivotIndex := partition(arr, less)
	QuickSort(arr[:pivotIndex], less)
	QuickSort(arr[pivotIndex+1:], less)
}

func partition[T any](arr []T, less func(T, T) bool) int {
	pivot := arr[len(arr)/2]
	left := 0
	right := len(arr) - 1

	for left <= right {
		for less(arr[left], pivot) {
			left++
		}
		for less(pivot, arr[right]) {
			right--
		}
		if left <= right {
			arr[left], arr[right] = arr[right], arr[left]
			left++
			right--
		}
	}
	return left
}

func main() {
	arr := []int{5, 3, 8, 4, 2}
	QuickSort(arr, func(a, b int) bool {
		return a < b
	})
	fmt.Println("Sorted array:", arr)
}

2.3 快速排序的最坏情况 (Worst Case for Quick Sort)

快速排序的最坏情况出现在每次选择的枢轴总是数组中最小或最大的元素,这使得每次递归调用只减少一个元素。这种情况下,时间复杂度为O(n²)。

2.4 冒泡排序与快速排序的比较 (Comparison of Bubble Sort and Quick Sort)

  • 冒泡排序:时间复杂度为O(n²),适合小规模数据。
  • 快速排序:平均时间复杂度为O(n log n),适合大规模数据。

2.5 并发快速排序 (Concurrent Quick Sort)

通过使用goroutines,可以并发地实现快速排序,以提高性能。

并发快速排序的泛型实现:

package main

import (
	"fmt"
	"sync"
)

// ConcurrentQuickSort 泛型函数实现
func ConcurrentQuickSort[T any](arr []T, less func(T, T) bool) {
	if len(arr) <= 1 {
		return
	}

	var wg sync.WaitGroup
	pivotIndex := partition(arr, less)
	wg.Add(2)

	go func() {
		defer wg.Done()
		ConcurrentQuickSort(arr[:pivotIndex], less)
	}()

	go func() {
		defer wg.Done()
		ConcurrentQuickSort(arr[pivotIndex+1:], less)
	}()

	wg.Wait()
}

func main() {
	arr := []int{5, 3, 8, 4, 2}
	ConcurrentQuickSort(arr, func(a, b int) bool {
		return a < b
	})
	fmt.Println("Sorted array:", arr)
}

2.6 归并排序 (Merge Sort)

归并排序是另一种分治排序算法,它将数组分成两半,分别排序,然后合并已排序的子数组。

泛型实现:

package main

import "fmt"

// MergeSort 泛型函数实现
func MergeSort[T any](arr []T, less func(T, T) bool) []T {
	if len(arr) <= 1 {
		return arr
	}

	mid := len(arr) / 2
	left := MergeSort(arr[:mid], less)
	right := MergeSort(arr[mid:], less)

	return merge(left, right, less)
}

func merge[T any](left, right []T, less func(T, T) bool) []T {
	result := make([]T, 0, len(left)+len(right))
	i, j := 0, 0
	for i < len(left) && j < len(right) {
		if less(left[i], right[j]) {
			result = append(result, left[i])
			i++
		} else {
			result = append(result, right[j])
			j++
		}
	}
	result = append(result, left[i:]...)
	result = append(result, right[j:]...)
	return result
}

func main() {
	arr := []int{5, 3, 8, 4, 2}
	sortedArr := MergeSort(arr, func(a, b int) bool {
		return a < b
	})
	fmt.Println("Sorted array:", sortedArr)
}

2.7 并发归并排序 (Concurrent Merge Sort)

同样,归并排序也可以通过使用goroutines来实现并发,以提高性能。

并发归并排序的泛型实现:

package main

import (
	"fmt"
	"sync"
)

// ConcurrentMergeSort 泛型函数实现
func ConcurrentMergeSort[T any](arr []T, less func(T, T) bool) []T {
	if len(arr) <= 1 {
		return arr
	}

	var wg sync.WaitGroup
	mid := len(arr) / 2

	var left, right []T

	wg.Add(2)

	go func() {
		defer wg.Done()
		left = ConcurrentMergeSort(arr[:mid], less)
	}()

	go func() {
		defer wg.Done()
		right = ConcurrentMergeSort(arr[mid:], less)
	}()

	wg.Wait()
	return merge(left, right, less)
}

func main() {
	arr := []int{5, 3, 8, 4, 2}
	sortedArr := ConcurrentMergeSort(arr, func(a, b int) bool {
		return a < b
	})
	fmt.Println("Sorted array:", sortedArr)
}

这些例子展示了如何使用Go的泛型功能来实现各种排序算法,包括并发版本,以提高程序的效率和灵活性。