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的SimPy库简化复杂的编程模型的介绍
Apr 13 Python
Python下的常用下载安装工具pip的安装方法
Nov 13 Python
Python实现将Excel转换为json的方法示例
Aug 05 Python
python自动化生成IOS的图标
Nov 13 Python
对python中的try、except、finally 执行顺序详解
Feb 18 Python
Python3 使用pillow库生成随机验证码
Aug 26 Python
python 数据分析实现长宽格式的转换
May 18 Python
python如何输出反斜杠
Jun 18 Python
解决python 虚拟环境删除包无法加载的问题
Jul 13 Python
Python使用for生成列表实现过程解析
Sep 22 Python
Python urlopen()参数代码示例解析
Dec 10 Python
Python使用Opencv实现边缘检测以及轮廓检测的实现
Dec 31 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
DOTA2 无惧惊涛骇浪 昆卡大型水友攻略
2020/04/20 DOTA
MySQL时间字段究竟使用INT还是DateTime的说明
2012/02/27 PHP
ThinkPHP调用common/common.php函数提示错误function undefined的解决方法
2014/08/25 PHP
教大家制作简单的php日历
2015/11/17 PHP
Yii2框架redis基本应用示例
2018/07/13 PHP
浅谈laravel中的关联查询with的问题
2019/10/10 PHP
JavaScript实现禁止后退的方法
2006/12/27 Javascript
用js生产批量批处理执行命令
2008/07/28 Javascript
Ajax,UTF-8还是GB2312 eval 还是execScript
2008/11/13 Javascript
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
2011/03/30 Javascript
JS跨域总结
2012/08/30 Javascript
捕获键盘事件(且兼容各浏览器)
2013/07/03 Javascript
动态加载script文件的两种方法
2013/08/15 Javascript
javaScript基础语法介绍
2015/02/28 Javascript
JS动态增删表格行的方法
2016/03/03 Javascript
如何开发出更好的JavaScript模块
2017/12/22 Javascript
彻底理解js面向对象之继承
2018/02/04 Javascript
vue移动端路由切换实例分析
2018/05/14 Javascript
微信小程序MUI导航栏透明渐变功能示例(通过改变rgba的a值实现)
2019/01/24 Javascript
JavaScript常用内置对象用法分析
2019/07/09 Javascript
通过js示例讲解时间复杂度与空间复杂度
2019/08/06 Javascript
Python聚类算法之凝聚层次聚类实例分析
2015/11/20 Python
详解Python中的type和object
2018/08/15 Python
Python中修改字符串的四种方法
2018/11/02 Python
Python Flask框架模板操作实例分析
2019/05/03 Python
python 画3维轨迹图并进行比较的实例
2019/12/06 Python
使用 Python ssh 远程登陆服务器的最佳方案
2020/03/06 Python
pyinstaller打包单文件时--uac-admin选项不起作用怎么办
2020/04/15 Python
菲律宾最大的网上花店和礼品店:PhilFlower.com
2018/02/09 全球购物
英国行业制服供应商:Alexandra
2019/09/14 全球购物
法国滑雪假期的专家:Ski Planet
2019/11/02 全球购物
英国领先的鞋类零售商和顶级品牌的官方零售商:Wynsors
2020/02/17 全球购物
四年的个人工作自我评价
2013/12/10 职场文书
《宋庆龄故居的樟树》教学反思
2014/04/07 职场文书
酒桌上的开场白
2015/06/01 职场文书
详解如何使用Node.js实现热重载页面
2021/05/06 Javascript