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模拟实现POST请求提交图片的方法
Jul 25 Python
Python的argparse库使用详解
Oct 09 Python
Python爬取数据保存为Json格式的代码示例
Apr 09 Python
python实现名片管理器的示例代码
Dec 17 Python
Python全面分析系统的时域特性和频率域特性
Feb 26 Python
Python格式化输出--%s,%d,%f的代码解析
Apr 29 Python
python中数字是否为可变类型
Jul 08 Python
python 浮点数四舍五入需要注意的地方
Aug 18 Python
pycharm 添加解释器的方法步骤
Aug 31 Python
python如何将图片转换素描画
Sep 08 Python
Python远程linux执行命令实现
Nov 11 Python
python sleep和wait对比总结
Feb 03 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
php $_SERVER windows系统与linux系统下的区别说明
2014/02/14 PHP
php简单判断文本编码的方法
2015/07/30 PHP
Yii2.0表关联查询实例分析
2016/07/18 PHP
PHPExcel 修改已存在Excel的方法
2018/05/03 PHP
jquery 子窗口操作父窗口的代码
2009/09/21 Javascript
谈谈关于JavaScript 中的 MVC 模式
2013/04/11 Javascript
JQuery之focus函数使用介绍
2013/08/20 Javascript
jQuery操作CheckBox的方法介绍(选中,取消,取值)
2014/02/04 Javascript
如何正确使用Nodejs 的 c++ module 链接到 OpenSSL
2014/08/03 NodeJs
快速入门Vue
2016/12/19 Javascript
Bootstrap的基本应用要点浅析
2016/12/19 Javascript
jQuery选择器实例应用
2017/01/05 Javascript
B/S(Web)实时通讯解决方案分享
2017/04/06 Javascript
JS和jQuery通过this获取html标签中的属性值(实例代码)
2017/09/11 jQuery
Vue组件全局注册实现警告框的实例详解
2018/06/11 Javascript
React组件内事件传参实现tab切换的示例代码
2018/07/04 Javascript
详解vue-cli官方脚手架配置
2018/07/20 Javascript
Vue中qs插件的使用详解
2020/02/07 Javascript
[46:43]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#2LGD VS MVP.Phx第二局
2016/03/02 DOTA
python简单判断序列是否为空的方法
2015/06/30 Python
你眼中的Python大牛 应该都有这份书单
2017/10/31 Python
Python wxPython库使用wx.ListBox创建列表框示例
2018/09/03 Python
解决python opencv无法显示图片的问题
2018/10/28 Python
对python同一个文件夹里面不同.py文件的交叉引用方法详解
2018/12/15 Python
Python计算时间间隔(精确到微妙)的代码实例
2019/02/26 Python
Python远程视频监控程序的实例代码
2019/05/05 Python
python实战串口助手_解决8串口多个发送的问题
2019/06/12 Python
Python docutils文档编译过程方法解析
2020/06/23 Python
使用Keras建立模型并训练等一系列操作方式
2020/07/02 Python
JINS眼镜官方网站:日本最大的眼镜邮购
2016/10/14 全球购物
英国最大最好的无人机商店:Drones Direct
2019/07/12 全球购物
酒店管理专业自荐信
2014/05/23 职场文书
通知范文怎么写
2015/04/16 职场文书
Python实现拼音转换
2021/06/07 Python
Redis分布式锁的7种实现
2022/04/01 Redis
如何利用python实现Simhash算法
2022/06/28 Python