flyfei

排序算法

1. 语法讲解

Go标准库sort包提供了对切片和用户定义集合进行排序的功能。

基本排序接口

// 排序基本类型
sort.Ints(slice []int)
sort.Float64s(slice []float64)
sort.Strings(slice []string)

// 自定义排序
sort.Slice(slice, func(i, j int) bool {
    return slice[i] < slice[j] // 排序条件
})

// 实现sort.Interface接口
type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}
sort.Sort(slice)

2. 应用场景

3. 编程实例

电商产品排序系统

package main

import (
    "fmt"
    "sort"
    "time"
)

type Product struct {
    ID        int
    Name      string
    Price     float64
    Rating    float64
    Sales     int
    CreatedAt time.Time
}

type ProductManager struct {
    products []Product
}

func NewProductManager() *ProductManager {
    return &ProductManager{
        products: []Product{
            {ID: 1, Name: "无线耳机", Price: 299.99, Rating: 4.5, Sales: 1200, CreatedAt: time.Now().Add(-24 * time.Hour)},
            {ID: 2, Name: "智能手机", Price: 3999.99, Rating: 4.8, Sales: 850, CreatedAt: time.Now().Add(-48 * time.Hour)},
            {ID: 3, Name: "蓝牙音箱", Price: 199.50, Rating: 4.2, Sales: 2300, CreatedAt: time.Now().Add(-12 * time.Hour)},
            {ID: 4, Name: "智能手表", Price: 899.00, Rating: 4.6, Sales: 1500, CreatedAt: time.Now().Add(-72 * time.Hour)},
        },
    }
}

func (pm *ProductManager) SortByPrice(ascending bool) {
    if ascending {
        sort.Slice(pm.products, func(i, j int) bool {
            return pm.products[i].Price < pm.products[j].Price
        })
    } else {
        sort.Slice(pm.products, func(i, j int) bool {
            return pm.products[i].Price > pm.products[j].Price
        })
    }
}

func (pm *ProductManager) SortByRating() {
    sort.Slice(pm.products, func(i, j int) bool {
        return pm.products[i].Rating > pm.products[j].Rating
    })
}

func (pm *ProductManager) SortBySales() {
    sort.Slice(pm.products, func(i, j int) bool {
        return pm.products[i].Sales > pm.products[j].Sales
    })
}

func (pm *ProductManager) SortByNewest() {
    sort.Slice(pm.products, func(i, j int) bool {
        return pm.products[i].CreatedAt.After(pm.products[j].CreatedAt)
    })
}

// 多条件排序
func (pm *ProductManager) SortByMultiple() {
    sort.Slice(pm.products, func(i, j int) bool {
        // 主要条件:评分
        if pm.products[i].Rating != pm.products[j].Rating {
            return pm.products[i].Rating > pm.products[j].Rating
        }
        // 次要条件:销量
        if pm.products[i].Sales != pm.products[j].Sales {
            return pm.products[i].Sales > pm.products[j].Sales
        }
        // 第三条件:价格(从低到高)
        return pm.products[i].Price < pm.products[j].Price
    })
}

func (pm *ProductManager) Display() {
    fmt.Println("产品列表:")
    for _, p := range pm.products {
        fmt.Printf("ID: %d, 名称: %s, 价格: ¥%.2f, 评分: %.1f, 销量: %d, 上架: %s\n",
            p.ID, p.Name, p.Price, p.Rating, p.Sales,
            p.CreatedAt.Format("2006-01-02"))
    }
    fmt.Println()
}

func main() {
    pm := NewProductManager()
    
    fmt.Println("=== 按价格排序(从低到高) ===")
    pm.SortByPrice(true)
    pm.Display()
    
    fmt.Println("=== 按评分排序 ===")
    pm.SortByRating()
    pm.Display()
    
    fmt.Println("=== 按销量排序 ===")
    pm.SortBySales()
    pm.Display()
    
    fmt.Println("=== 多条件排序(评分→销量→价格) ===")
    pm.SortByMultiple()
    pm.Display()
}

4. 其他用法

package main

import (
    "fmt"
    "sort"
)

// 实现sort.Interface接口
type Person struct {
	Name string
	Age  int
}
type People []Person

func (p People) Len() int           { return len(p) }
func (p People) Less(i, j int) bool { return p[i].Age < p[j].Age }
func (p People) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

func main() {
    // sort.Interface
    people := People{
		{"张三", 31},
		{"李四", 42},
		{"王五", 17},
		{"小二", 26},
	}
	sort.Sort(people)
	fmt.Println(people) 
    
    numbers := []int{5, 2, 8, 1, 9, 3}    
    // 逆序排序
    sort.SliceStable(numbers, func(i, j int) bool {
        return numbers[i] > numbers[j]
    })
    fmt.Println("逆序排序:", numbers)
    
    // 检查是否已排序
    if sort.IntsAreSorted(numbers) {
        fmt.Println("切片已排序")
    } else {
        fmt.Println("切片未排序")
    }
    
    // 搜索已排序切片
    names := []string{"Alice", "Bob", "Carol", "David"}
    sort.Strings(names)
    index := sort.SearchStrings(names, "Carol")
    fmt.Printf("'Carol'在排序后切片中的索引: %d\n", index)
}

5. 课时总结