zoukankan      html  css  js  c++  java
  • GO语言学习笔记6-Sort的使用

    GoLang标准库的sort包提供了排序切片和用户自定义数据集以及相关功能的函数。

    Sort操作的对象通常是一个slice,需要满足三个基本的接口,并且能够使用整数来索引。

    sort实现原理

    Sort排序的函数原型如下所示:

    Sort

    // It makes one call to data.Len to determine n, and O(n*log(n)) calls to
    // data.Less and data.Swap. The sort is not guaranteed to be stable.
    func Sort(data Interface) {
    	n := data.Len()
    	quickSort(data, 0, n, maxDepth(n))
    }
    

    interface

    // A type, typically a collection, that satisfies sort.Interface can be
    // sorted by the routines in this package. The methods require that the
    // elements of the collection be enumerated by an integer index.
    type Interface interface {
    	// Len is the number of elements in the collection.
    	Len() int
    	// Less reports whether the element with
    	// index i should sort before the element with index j.
    	Less(i, j int) bool
    	// Swap swaps the elements with indexes i and j.
    	Swap(i, j int)
    }
    

    quickSort

    func quickSort(data Interface, a, b, maxDepth int) {
    	for b-a > 12 { // Use ShellSort for slices <= 12 elements
    		if maxDepth == 0 {
    			heapSort(data, a, b)
    			return
    		}
    		maxDepth--
    		mlo, mhi := doPivot(data, a, b)
    		// Avoiding recursion on the larger subproblem guarantees
    		// a stack depth of at most lg(b-a).
    		if mlo-a < b-mhi {
    			quickSort(data, a, mlo, maxDepth)
    			a = mhi // i.e., quickSort(data, mhi, b)
    		} else {
    			quickSort(data, mhi, b, maxDepth)
    			b = mlo // i.e., quickSort(data, a, mlo)
    		}
    	}
    	if b-a > 1 {
    		// Do ShellSort pass with gap 6
    		// It could be written in this simplified form cause b-a <= 12
    		for i := a + 6; i < b; i++ {
    			if data.Less(i, i-6) {
    				data.Swap(i, i-6)
    			}
    		}
    		insertionSort(data, a, b)
    	}
    }
    

    Sort内部 []int排序

    type IntSlice []int
    // 获取此 slice 的长度
    func (p IntSlice) Len() int           { return len(p) }
    
    // 比较两个元素大小,升序
    func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
    
    // 交换数据
    func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
    
    // Sort is a convenience method.
    func (p IntSlice) Sort() { Sort(p) }
    

    代码实现

    Olymic Game这道题采用Sort排序的实现方法如下:

    package main
    
    import (
    	"fmt"
    	"sort"
    	"strings"
    )
    
    type MedalNum struct {
    	name string
    	gold int
    	silver int
    	bronze int
    }
    
    type MedalNumList []MedalNum
    
    func (m MedalNumList) Len() int {
    	return len(m)
    }
    
    // 奖牌数降序,国家名称字典序
    func (m MedalNumList) Less(i, j int) bool {
    	if m[i].gold > m[j].gold {
    		return true
    	} else if m[i].gold == m[j].gold {
    		if m[i].silver > m[j].silver {
    			return true
    		} else if m[i].silver == m[j].silver {
    			if m[i].bronze > m[j].bronze {
    				return true
    			} else if m[i].bronze == m[j].bronze {
    				if strings.Compare(m[i].name, m[j].name) < 0 {
    					return true
    				}
    			}
    		}
    
    	}
    	return false
    }
    
    func (m MedalNumList) Swap(i, j int) {
    	m[i], m[j] = m[j], m[i]
    }
    
    func main() {
    	var n int
    
    	_, _ = fmt.Scan(&n)
    
    	var medal MedalNumList
    
    	var nameI string
    	var goldI, sliverI, bronzeI int
    
    	i := 0
    	for {
    		if i == n {
    			break
    		}
    		_, err := fmt.Scanln(&nameI, &goldI, &sliverI, &bronzeI);
    
    		if err != nil {
    			break
    		} else {
    			medal = append(medal, MedalNum{name:nameI, gold:goldI, silver:sliverI, bronze:bronzeI})
    		}
    
    		i++
    	}
    
    	sort.Sort(medal)
    
    	for _, m := range medal {
    		fmt.Println(m.name)
    	}
    
    }
    

    Compare是字符串比较函数,函数原型如下所示:

    // Compare returns an integer comparing two strings lexicographically.
    // The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
    func Compare(a, b string) int {
    	if a == b {
    		return 0
    	}
    	if a < b {
    		return -1
    	}
    	return +1
    }
    

    个人主页:

    www.codeapes.cn

  • 相关阅读:
    利用gcc的__attribute__编译属性section子项构建初始化函数表
    Linux调试
    使用C++ stringstream来进行数据类型转换
    UseConcMarkSweepGC
    Django 3.1 发布,异步支持增强
    网易云音乐的消息队列改造之路
    二维码预生成:码上营销的并发之痛
    源码 redis 分布式锁
    跨度实际上是用来计算排位(rank) 目标节点在跳跃表中的排位 有序集 排序计算
    为什么有序集合需要同时使用跳跃表和字典来实现?
  • 原文地址:https://www.cnblogs.com/codeapes666/p/12093813.html
Copyright © 2011-2022 走看看