快速排序算法 - go实现
在分析redis集群中大Key的时候,通常都采用分析rdb文件的方式;但是这种方式需要在每一台redis服务器上部署分析程序及分析脚本,而像salt之类的工具运维没有开放给我们使用,一台一台部署不好管理。正好我们的总redis规模不大,大概在200个集群左右,考虑到cluster集群,需要分析的redis实例数在300左右,所以就想着能不能通过scan的方式来进行。
通过scan命令扫描从库,将集群中key深度大于指定值的key扫描出来,将这些 key 放在一个slice中,取 top N,这就需要对 slice中的 key按照深度进行排序。300个实例说多不多,说少不少,排序算法的性能还是很重要的。快速排序针对小数据量排序性能很好,正好mysql在使用sort buffer进行排序时采用的是快速排序,这里就用go实现来复习一下快速排序算法。
func sortBigKeySlice(bigKeySlice []*bigKeyInstance) {
if len(bigKeySlice) < 2 {
return
}
sortBigKey(bigKeySlice, 0, len(bigKeySlice))
} //使用递归实现
func sortBigKey(bigKeySlice []*bigKeyInstance, low, high int) {
if low >= high {
return
}
p := partition(bigKeySlice, low, high)
sortBigKey(bigKeySlice, low, p)
sortBigKey(bigKeySlice, p + 1, high)
}
//普通快速排序,对于普通快速排序,将第一个元素作为基准,小于该元素的放在左边,大于等于该元素的放在右边
func partition(bigKeySlice []*bigKeyInstance, low, high int) int{
//直接将第一个元素作为分隔值
pivotIns := bigKeySlice[low]
//当前第一个元素点位作为标记点
pivotPos := low //去除第一个分割值,遍历元素,如果元素比分割值小,将标记点右移一位,交换元素的值,大于等于则继续比较下一个元素
for i := low + 1; i < high; i++ {
if bigKeySlice[i].size < pivotIns.size {
pivotPos += 1
bigKeySlice[pivotPos], bigKeySlice[i] = bigKeySlice[i], bigKeySlice[pivotPos]
} else {
continue
}
}
//不要忘记最后的互换,将分隔值与标记点元素互换
bigKeySlice[low], bigKeySlice[pivotPos] = bigKeySlice[pivotPos], bigKeySlice[low]
return pivotPos
}
普通快速排序默认左边的第一个元素作为基准数,对于渐进有序的数组来说,这就导致小于基准的数会相当少,而大于等于基准的数相当多,造成分区不平衡的问题,普通排序就会退化,严重的将退化成O(n^2)。所以对其改进:不再默认选择第一个数,而是随机选一个数作为基准,这样的快排称为随机普通快排。
//随机普通快速排序,不使用第一个元素作为基准,而是使用一个随机元素作为基准
func partition(bigKeySlice []*bigKeyInstance, low, high int) int {
//取slice中的一个随机元素作为分割点,而不是第一个元素开始分割
rand_low := low + rand.Intn(high - low)
bigKeySlice[low], bigKeySlice[rand_low] = bigKeySlice[rand_low], bigKeySlice[low]
pivotPos := low
for i := low + 1; i < high; i++ {
if bigKeySlice[i].size < bigKeySlice[low].size {
pivotPos += 1
bigKeySlice[pivotPos], bigKeySlice[i] = bigKeySlice[i], bigKeySlice[pivotPos]
} else {
continue
}
}
bigKeySlice[low], bigKeySlice[pivotPos] = bigKeySlice[pivotPos], bigKeySlice[low]
return pivotPos
}
对于含有大量重复元素的数组,则对于与基准数相同的数,要么分到了左边,要么分到了右边,同样会造成分治不平衡的问题,造成性能退化。这时,采用双路排序或三路排序进行改进。
双路排序 & 三路排序待续....
快速排序算法 - go实现的更多相关文章
- 快速排序算法 java 实现
快速排序算法 java 实现 快速排序算法Java实现 白话经典算法系列之六 快速排序 快速搞定 各种排序算法的分析及java实现 算法概念 快速排序是C.R.A.Hoare于1962年提出的一种划分 ...
- C# 集合扩展快速排序算法
/// <summary> /// 对集合进行排序,如 /// List<Person> users=new List<Person>(){.......} /// ...
- PHP描述冒泡排序和快速排序算法
使用PHP描述冒泡排序和快速排序算法,对象可以是一个数组.使用PHP描述顺序查找和二分查找(也叫做折半查找)算法,顺序查找必须考虑效率,对象可以是一个有序数组.写一个二维数组排序算法函数,能够具有通用 ...
- 快速排序算法(Java)
快速排序算法的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另外一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序. class Parti ...
- 快速排序算法-C语言实现
注:本篇内容为翻译,之所以选择这篇进行翻译原因是该文章含有动画,能够更加直观地展示快速排序.同时,可以仔细看一下代码,代码中把结构化的思想给予了更加充分地表现.按照功能进行模块划分的思想得到了彻底地贯 ...
- C#快速排序算法基础入门篇
相信算法对于许多开发人员来说都是一大难点,之所以难,就像设计模式一样,许多人在阅读之后,没有很好地理解,也不愿意动手上机操作,只停留在理论的学习上面,随着时间推移就慢慢淡忘. 有些东西,你可以发明创造 ...
- 快速排序算法 Quick sort
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046189.html 首先随机选择一个轴,并调整数组内各个数字,使得比轴值大的数在轴的右边, ...
- PHP实现快速排序算法
快速排序(Quick Sort)是对冒泡排序的一种改进,属不稳定排序算法,由东尼·霍尔在1962年提出.快速排序基本步骤:从数列中挑出一个元素(一般称为称为“基准”),通过一趟排序将要排序的数据分割成 ...
- Java快速排序算法
快速排序算法思想: 快速排序(Quicksort)是对冒泡排序的一种改进. 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一 ...
- 排序系列 之 快速排序算法 —— Java实现
基本思想: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变 ...
随机推荐
- spring——使用注解开发
注意:spring4之后,使用注解开发需要导入AOP包org.springframework:spring-aop:5.2.5.RELEASE以及context约束,增加注解的支持 <?xml ...
- CF1404E Bricks (最大权独立集)
考虑把答案进行转化,通过分矩形条,我们能去掉一些夹在#之间的边 那么答案= #个数 - 能去掉的边个数 但去掉是有限制的,同一个#格子的横边和竖边不能同时去掉 把边转化成点,限制变成边. 横竖边的点 ...
- 浅谈systemd原理和应用
多不说,直接上代码(可谓配置): [Unit] Description=demo app After=network-is-online.target [Service] Type=Simple Ex ...
- 羽夏逆向指引—— Hook
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的, ...
- phpstorm chrome 添加xdebug扩展
转:https://blog.csdn.net/ltcm_sakura/article/details/102967859 一.Xdebug helper:php调试插件 http://chromec ...
- 什么是 Spring Cloud Bus?我们需要它吗?
考虑以下情况:我们有多个应用程序使用 Spr ng Cloud Config 读取属性,而S ring Cloud Config 从GIT 读取这些属性. 下面的例子中多个员工生产者模块从 Employe ...
- SpingMvc中的控制器的注解一般用那个,有没有别的注解可以替代?
答:一般用@Controller注解,也可以使用@RestController,@RestController注解相当于@ResponseBody + @Controller,表示是表现层,除此之外, ...
- Spring 对 DAO 的支持?
Spring 对数据访问对象(DAO)的支持旨在简化它和数据访问技术如 JDBC, Hibernate or JDO 结合使用.这使我们可以方便切换持久层.编码时也不用担心 会捕获每种技术特有的异常.
- 数组(Array)和列表(ArrayList)有什么区别
Array可以包含基本类型和对象类型,ArrayList只能包含对象类型 Array大小固定,ArrayList的大小是动态变化的. ArrayList提供了更多的方法和特性:比如 :addAll() ...
- 学习MFS(四)
一.搭建Master Server 1.安装相关编译器.工具包 [root@master ~]# yum -y install gcc gcc-c++ zlib-devel 2.创建进程用户 [roo ...