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实现二分查找算法实例
May 26 Python
python删除文本中行数标签的方法
May 31 Python
使用python实现http及ftp服务进行数据传输的方法
Oct 26 Python
在python里协程使用同步锁Lock的实例
Feb 19 Python
python 通过可变参数计算n个数的乘积方法
Jun 13 Python
python django model联合主键的例子
Aug 06 Python
python Web flask 视图内容和模板实现代码
Aug 23 Python
python3中pip3安装出错,找不到SSL的解决方式
Dec 12 Python
python3读取autocad图形文件.py实例
Jun 05 Python
使用python爬取抖音app视频的实例代码
Dec 01 Python
深入理解python多线程编程
Apr 18 Python
Python使用Opencv打开笔记本电脑摄像头报错解问题及解决
Jun 21 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生成自己的LOG文件
2006/10/09 PHP
ThinkPHP5.1框架数据库链接和增删改查操作示例
2019/08/03 PHP
phpinfo的知识点总结
2019/10/10 PHP
Firebug入门指南(Firefox浏览器)
2010/08/21 Javascript
解决checkbox的attr(checked)一直为undefined问题
2014/06/16 Javascript
JQuery中基础过滤选择器用法实例分析
2015/05/18 Javascript
使用JavaScript刷新网页的方法
2015/06/04 Javascript
字符串反转_JavaScript
2016/04/28 Javascript
JavaScript中如何使用cookie实现记住密码功能及cookie相关函数介绍
2016/11/10 Javascript
如何解决hover在ie6中的兼容性问题
2016/12/15 Javascript
JS 组件系列之 bootstrap treegrid 组件封装过程
2017/04/28 Javascript
mpvue中使用flyjs全局拦截的实现代码
2018/09/13 Javascript
微信小程序使用setData修改数组中单个对象的方法分析
2018/12/30 Javascript
如何利用Node.js与JSON搭建简单的动态服务器
2020/06/16 Javascript
[05:08]DOTA2-DPC中国联赛3月6日Recap集锦
2021/03/11 DOTA
Python实现从订阅源下载图片的方法
2015/03/11 Python
Python实现在matplotlib中两个坐标轴之间画一条直线光标的方法
2015/05/20 Python
简单实现Python爬取网络图片
2018/04/01 Python
Python 找到列表中满足某些条件的元素方法
2018/06/26 Python
对python:threading.Thread类的使用方法详解
2019/01/31 Python
浅析Python 读取图像文件的性能对比
2019/03/07 Python
python线程安全及多进程多线程实现方法详解
2019/09/27 Python
Python 用三行代码提取PDF表格数据
2019/10/13 Python
Pandas+Matplotlib 箱式图异常值分析示例
2019/12/09 Python
pytorch中的自定义反向传播,求导实例
2020/01/06 Python
详解python日志输出使用配置文件格式
2021/02/10 Python
C#如何调用Windows程序打开一个文档
2014/12/26 面试题
应届毕业生如何写求职信
2014/02/16 职场文书
实习推荐信
2014/05/10 职场文书
学校募捐倡议书
2014/05/14 职场文书
校长四风对照检查材料
2014/09/27 职场文书
骨干教师考核评语
2014/12/31 职场文书
2016学习依法治国心得体会
2016/01/15 职场文书
uwsgi+nginx代理Django无法访问静态资源的解决
2021/05/10 Servers
mysql timestamp比较查询遇到的坑及解决
2021/11/27 MySQL
分享五个Node.js开发的优秀实践 
2022/04/07 NodeJs