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基于Tkinter的HelloWorld入门实例
Jun 17 Python
Python创建对称矩阵的方法示例【基于numpy模块】
Oct 12 Python
python解决js文件utf-8编码乱码问题(推荐)
May 02 Python
Python使用matplotlib绘制随机漫步图
Aug 27 Python
解决python 自动安装缺少模块的问题
Oct 22 Python
python游戏地图最短路径求解
Jan 16 Python
Python爬虫运用正则表达式的方法和优缺点
Aug 25 Python
使用tensorflow显示pb模型的所有网络结点方式
Jan 23 Python
Python 解析pymysql模块操作数据库的方法
Feb 18 Python
python删除指定列或多列单个或多个内容实例
Jun 28 Python
python根据字典的键来删除元素的方法
Aug 16 Python
python爬取代理ip的示例
Dec 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
Discuz!5的PHP代码高亮显示插件(黑暗中的舞者更新)
2007/01/29 PHP
PHP将回调函数作用到给定数组单元的方法
2014/08/19 PHP
php开启与关闭错误提示适用于没有修改php.ini的权限
2014/10/16 PHP
php单例模式实现方法分析
2015/03/14 PHP
PHP 与 UTF-8 的最佳实践详细介绍
2017/01/04 PHP
使用Git实现Laravel项目的自动化部署
2019/11/24 PHP
PHP使用PDO 连接与连接管理操作实例分析
2020/04/21 PHP
JQuery在页面中添加和除移DOM示例代码
2013/06/24 Javascript
一个很有趣3D球状标签云兼容IE8
2014/08/22 Javascript
Egret引擎开发指南之编译项目
2014/09/03 Javascript
JavaScript框架是什么?怎样才能叫做框架?
2015/07/01 Javascript
使用Angular CLI进行Build(构建)和Serve详解
2018/03/24 Javascript
vue 实现在函数中触发路由跳转的示例
2018/09/01 Javascript
vue中的router-view组件的使用教程
2018/10/23 Javascript
vue实现点击追加选中样式效果
2019/11/01 Javascript
[01:03:36]Ti4 循环赛第三日DK vs Titan
2014/07/12 DOTA
[02:22]《新闻直播间》2017年08月14日
2017/08/15 DOTA
[00:10]DOTA2全国高校联赛 以DOTA2会友
2018/05/30 DOTA
[12:21]VICI vs TNC (BO3)
2018/06/07 DOTA
[54:18]DOTA2-DPC中国联赛 正赛 PSG.LGD vs LBZS BO3 第一场 1月22日
2021/03/11 DOTA
python2.7到3.x迁移指南
2018/02/01 Python
python调用百度语音REST API
2018/08/30 Python
html5 sessionStorage会话存储_动力节点Java学院整理
2017/07/06 HTML / CSS
HTML5之SVG 2D入门8—文档结构及相关元素总结
2013/01/30 HTML / CSS
详解HTML5 data-* 自定义属性
2018/01/24 HTML / CSS
Kathmandu澳洲户外商店:新西兰户外运动品牌
2017/11/12 全球购物
The North Face北面英国官网:美国著名户外品牌
2017/12/13 全球购物
Linux内核的同步机制是什么?主要有哪几种内核锁
2013/01/03 面试题
公务员培训自我鉴定
2014/02/01 职场文书
小组合作学习反思
2014/02/18 职场文书
旅行社优秀创业计划书
2014/08/16 职场文书
房地产经营管理专业自荐信
2014/09/02 职场文书
青年文明号申报材料
2014/12/23 职场文书
遗失证明范文
2015/06/19 职场文书
幼儿园音乐教学反思
2016/02/18 职场文书
小学记事作文之200字
2019/08/06 职场文书