Go语言数据结构和算法(二十三)桶排序算法

39 阅读3分钟

桶排序是一种排序算法.它将未排序的数组元素分成若干组.称为桶.然后通过使用任何合适的排序算法或递归的应用相同的桶算法对每个桶进行排序.

1.步骤:

创建一个最初为空的桶数组.

分解.遍历原始数组.将每个对象放入适当的桶中.

对每个非空桶进行排序.

合并.按顺序访问桶后将所有桶合并到原始数组中.

2.使用场景:

均匀分布的数据:

桶排序算法在对范围内均匀分布的数据集进行排序时效率最高.在这种情况下.可以将元素均匀的划分到桶中.并且可以使用另一种算法然后对桶进行独立排序.

内存分配:

桶排序算法是一种异地排序算法.这意味着它需要额外的内存来保存排序后的元素.这使得它在必须保留原始数据集的场景中非常有用.

3.实现:

3.1方法:


func BucketSort(array []float64, bucketSize int) []float64 {
	var max, min float64
	for _, n := range array {
		if n < min {
			min = n
		}

		if n > max {
			max = n
		}
	}

	nBuckets := int(max-min)/bucketSize + 1
	buckets := make([][]float64, nBuckets)
	for i := 0; i < nBuckets; i++ {
		buckets[i] = make([]float64, 0)
	}

	for _, n := range array {
		index := int(n-min) / bucketSize
		buckets[index] = append(buckets[index], n)
	}

	sort := make([]float64, 0)

	for _, bucket := range buckets {
		if len(bucket) > 0 {
			insertSort(bucket)
			sort = append(sort, bucket...)
		}
	}
	return sort
}

func insertSort(bucket []float64) {
	for i := 0; i < len(bucket); i++ {
		temp := bucket[i]
		j := i - 1
		for ; j >= 0 && temp < bucket[j]; j-- {
			bucket[j+1] = bucket[j]
		}
		bucket[j+1] = temp
	}
}

3.2main方法:

	array := []float64{33, 23, 56, 7, 8, 18, 99, 28}
	bucketSort := data.BucketSort(array, 5)
	fmt.Println(bucketSort)
}

4.实战:

给定一个字符串.要求字符出现频率从高到低重新排列字符串.

4.1方法:

	return bucketSortFrequency(s)
}

func bucketSortFrequency(s string) string {
	bucket := make([][]rune, len(s)+1)
	m := make(map[rune]int)
	result := ""
	for _, value := range s {
		m[value] += 1
	}

	for r, time := range m {
		bucket[time] = append(bucket[time], r)
	}

	for i := len(s); i >= 0; i-- {
		for _, r := range bucket[i] {
			result += strings.Repeat(string(r), i)
		}
	}
	return result
}

4.2main方法:

	str := "ILoveGo"
	frequencySort := data.FrequencySort(str)
	fmt.Println(frequencySort)
}

5.实战:

给定一个数组和一个整数n.返回n个出现频率最高的元素.

5.1方法:

	bucket := make([][]int, len(array)+1)
	freq := make(map[int]int)
	for _, value := range array {
		v, ok := freq[value]
		if ok {
			freq[value] = v + 1
		} else {
			freq[value] = 1
		}
	}
	for k, v := range freq {
		if bucket[v] == nil {
			bucket[v] = make([]int, 0)
		}
		bucket[v] = append(bucket[v], k)
	}
	res := make([]int, len(array))
	cnt := 0
	for i := len(bucket) - 1; i >= 0 && cnt < n; i-- {
		if bucket[i] != nil {
			for _, value := range bucket[i] {
				res[cnt] = value
				cnt++
			}
		}
	}
	res = res[:n]
	return res
}

5.2main方法:

	array := []int{1, 6, 6, 8, 8, 8, 3, 3}
	freq := data.TopNFreq(array, 2)
	fmt.Println(freq)
}

6.实战:

返回一个整数数组中两个连续元素之间的最大差异数.

6.1方法:

	if len(array) < 2 {
		return 0
	}
	min, max := array[0], array[0]
	for _, num := range array {
		if num < min {
			min = num
		}
		if num > max {
			max = num
		}
	}
	bucketSize := int(math.Ceil(float64(max-min) / float64(len(array)-1)))
	bucketMin, bucketMax := make([]int, len(array)-1), make([]int, len(array)-1)
	for i := 0; i < len(array)-1; i++ {
		bucketMin[i], bucketMax[i] = math.MaxInt32, math.MinInt32
	}
	for _, num := range array {
		if num == min || num == max {
			continue
		}
		index := (num - min) / bucketSize
		if num < bucketMin[index] {
			bucketMin[index] = num
		}

		if num > bucketMax[index] {
			bucketMax[index] = num
		}
	}

	maxGap := math.MinInt32
	prev := min
	for i := 0; i < len(array)-1; i++ {
		if bucketMin[i] == math.MaxInt32 && bucketMax[i] == math.MinInt32 {
			continue
		}
		if bucketMin[i]-prev > maxGap {
			maxGap = bucketMin[i] - prev
		}
		prev = bucketMax[i]
	}
	if max-prev > maxGap {
		maxGap = max - prev
	}
	return maxGap
}

6.2main方法:

	array := []int{19, 6, 9, 1}
	diff := data.MaxDiff(array)
	fmt.Println(diff)
}

***来之不易.






如果大家喜欢我的分享的话.可以关注我的微信公众号

念何架构之路