python查找第k小元素代码分享


Posted in Python onDecember 18, 2013
# -*- coding: utf-8 -*-
from random import randint
from math import ceil, floor
def _partition(A, l, r, i):
    """以A[i]为主元划分数组A[l..r],使得:
    A[l..m-1] <= A[m] < A[m+1..r]
    """
    A[i], A[r] = A[r], A[i] # i交换到末位r,作为主元
    pivot = A[r] # 主元
    m = l # 索引标记
    for n in xrange(l, r): # l..r-1
        if A[n] <= pivot:
            A[m], A[n] = A[n], A[m] # 交换
            m += 1 # 后移
    A[m], A[r] = A[r], A[m] # 主元到m位
    return m
def _rand(A, l, r):
    """随机划分主元"""
    return randint(l, r) # A[l..r]随机取一个
def _select(A, l, r, k, pivot_selector = _rand):
    """利用快排,得A[l..r]中第k小的数,k in [l+1,r+1]:
    其尾递归方式,伪码如下:
    SELECT(A, l, r, k)
    1  while true:
    2    i ← ? // 划分主元位置
    3    m ← PARTITION(A, l, r, i) // 数组划分
    4    n ← m - l + 1 // A[l..m]元素个数
    5    if k = n // 检查A[m]是否是第k小的元素
    6      then return A[m]
    7    elseif k < n // 左划分区
    8      r = m - 1
    9    else // 右划分区
    10     k = k - n
    11     l = m + 1
    Args:
        pivot_selector(Function): 主元选取方法,默认随机方式
    """
    if not A:
        return None
    if l == r:
        return A[l]
    while True:
        i = pivot_selector(A, l, r)
        m = _partition(A, l, r, i)
        n = m - l + 1
        if k == n:
            return A[m]
        elif k < n:
            r = m - 1
        else:
            k = k - n
            l = m + 1
def rand_select(A, k):
    """默认随机划分主元方式,k in [1, len(A)]
    E[T(n)] = O(n)
    """
    return _select(A, 0, len(A) - 1, k);

def _median(A, l, r):
    """对A[l..r]插入排序(原地)后选取其中位数位置"""
    for j in xrange(l, r + 1):
        k = A[j]
        i = j
        while i > l and A[i-1] > k:
            A[i] = A[i-1]
            i -= 1
        A[i] = k
    return l + int((r - l) * 0.5) # 下中位数
def _medianOfMedians(A, l, r):
    """中位数的中位数方式:
    1. 划分为floor(n/5)个5元组,剩下(n%5)组成最后一组。
    2. 找出ceil(n/5)个组各自的中位数。先对每组插入排序,再从中选出中位数。
    3. 对第2步中找出的ceil(n/5)个中位数重复上述操作,直到仅有一个中位数。
    """
    if l == r:
        return l
    n = r - l + 1 # 元素个数
    m = int(ceil(n / 5.0)) # 划分组数,每组5个元素
    for i in xrange(m):
        # 每组起始位和结束位
        sub_l = l + i * 5
        sub_r = sub_l + 4
        if sub_r > r:
            sub_r = r
        # 对每组元素插入排序后,选取中位数
        sub_m = _median(A, sub_l, sub_r) # 中位数索引
        # 交换中位数到前几位
        j = l + i
        A[j], A[sub_m] = A[sub_m], A[j]
    return _medianOfMedians(A, l, l + m - 1) # 中位数的中位数
def bfprt_select(A, k):
    """中位数的中位数方式(BFPRT算法)
    T(n) = O(n)
    """
    return _select(A, 0, len(A) - 1, k, _medianOfMedians);

def _median3(A, l, r):
    """三数中位数方式,取l,r,(l+r)/2三数中位数"""
    c = (l + r) / 2
    keys = [l, c, r]
    i = _median(keys, 0, 2)
    return keys[i]
def median_select(A, k):
    """三数中位数方式,以消除最坏情况"""
    return _select(A, 0, len(A) - 1, k, _median3);

if __name__ == '__main__':
    import random, time
    from copy import copy
    print('preparing data...')
    n = 1000000
    nums = range(n)
    random.shuffle(nums)
    print('ready go!')
    def timeit(fnc, *args, **kargs):
        print('%s starts processing' % fnc.__name__)
        begtime = time.clock()
        retval = fnc(*args, **kargs)
        endtime = time.clock()
        print('%s takes time : %f' % (fnc.__name__, endtime - begtime))
        return retval
    test_methods = [rand_select, bfprt_select, median_select]
    k = random.randrange(n) + 1
    dashes = '---' * 10
    for test in test_methods:
        print(dashes)
        nums_new = copy(nums)
        result = timeit(test, nums_new, k)
        print('the %dth smallest element: %d' % (k, result))
Python 相关文章推荐
python实现dnspod自动更新dns解析的方法
Feb 14 Python
详解Python函数作用域的LEGB顺序
May 14 Python
TensorFlow实现卷积神经网络CNN
Mar 09 Python
Python数据结构之哈夫曼树定义与使用方法示例
Apr 22 Python
python3实现随机数
Jun 25 Python
Python线程之定位与销毁的实现
Feb 17 Python
PyTorch的深度学习入门教程之构建神经网络
Jun 27 Python
python3的url编码和解码,自定义gbk、utf-8的例子
Aug 22 Python
Python调用graphviz绘制结构化图形网络示例
Nov 22 Python
pycharm新建Vue项目的方法步骤(图文)
Mar 04 Python
Django ValuesQuerySet转json方式
Mar 16 Python
68行Python代码实现带难度升级的贪吃蛇
Jan 18 Python
python获取beautifulphoto随机某图片代码实例
Dec 18 #Python
python使用urllib2模块获取gravatar头像实例
Dec 18 #Python
python2.7删除文件夹和删除文件代码实例
Dec 18 #Python
python使用xmlrpc实例讲解
Dec 17 #Python
python三元运算符实现方法
Dec 17 #Python
用python写asp详细讲解
Dec 16 #Python
python模块restful使用方法实例
Dec 10 #Python
You might like
在Nginx上部署ThinkPHP项目教程
2015/02/02 PHP
php字符串操作常见问题小结
2016/10/11 PHP
PHP实现找出链表中环的入口节点
2018/01/16 PHP
Laravel框架模板加载,分配变量及简单路由功能示例
2018/06/11 PHP
JS版网站风格切换实例代码
2008/10/06 Javascript
iframe子父页面调用js函数示例
2013/11/07 Javascript
php的文件上传入门教程(实例讲解)
2014/04/10 Javascript
jQuery中get()方法用法实例
2014/12/27 Javascript
JavaScript 事件对象介绍
2015/04/13 Javascript
很棒的Bootstrap选项卡切换效果
2016/07/01 Javascript
js实现各种复制到剪贴板的方法(分享)
2016/10/27 Javascript
js鼠标跟随运动效果
2017/03/11 Javascript
vue2 中如何实现动态表单增删改查实例
2017/06/09 Javascript
详解Vue路由History mode模式中页面无法渲染的原因及解决
2017/09/28 Javascript
利用Vue构造器创建Form组件的通用解决方法
2018/12/03 Javascript
微信小程序中如何计算距离某个节日还有多少天
2019/07/15 Javascript
详解关于Vue单元测试的几个坑
2020/04/26 Javascript
vue实现五子棋游戏
2020/05/28 Javascript
JS定时器如何实现提交成功提示功能
2020/06/12 Javascript
解决新建一个vue项目过程中遇到的问题
2020/10/22 Javascript
Ant Design的可编辑Tree的实现操作
2020/10/31 Javascript
Python切片工具pillow用法示例
2018/03/30 Python
opencv python统计及绘制直方图的方法
2019/01/21 Python
通过selenium抓取某东的TT购买记录并分析趋势过程解析
2019/08/15 Python
全网最全python库selenium自动化使用详细教程
2021/01/12 Python
德国在线购买葡萄酒网站:Geile Weine
2019/09/24 全球购物
英国最大的天然和有机产品在线零售商之一:Big Green Smile
2020/05/06 全球购物
办理信用卡工作证明
2014/01/11 职场文书
京剧自荐信
2014/01/26 职场文书
毕业自我鉴定总结
2014/03/24 职场文书
幼儿园区域活动总结
2014/05/08 职场文书
公司新员工欢迎词
2015/09/30 职场文书
强烈推荐:小学生:暑假作息时间表(值得收藏)
2019/07/09 职场文书
教你用python实现12306余票查询
2021/06/30 Python
MySQL表类型 存储引擎 的选择
2021/11/11 MySQL
Go并发4种方法简明讲解
2022/04/06 Golang