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使用logging模块发送邮件代码示例
Jan 18 Python
python在非root权限下的安装方法
Jan 23 Python
Python面向对象程序设计OOP深入分析【构造函数,组合类,工具类等】
Jan 05 Python
ORM Django 终端打印 SQL 语句实现解析
Aug 09 Python
Python多叉树的构造及取出节点数据(treelib)的方法
Aug 09 Python
python设置随机种子实例讲解
Sep 12 Python
python实现字符串和数字拼接
Mar 02 Python
Django 解决model 反向引用中的related_name问题
May 19 Python
python神经网络编程实现手写数字识别
May 27 Python
Python 通过爬虫实现GitHub网页的模拟登录的示例代码
Aug 17 Python
python安装及变量名介绍详解
Dec 12 Python
单身狗福利?Python爬取某婚恋网征婚数据
Jun 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
关于BIG5-HKSCS的解决方法
2007/03/20 PHP
PHP中英混合字符串截取函数代码
2011/07/17 PHP
PHP之autoload运行机制实例分析
2014/08/28 PHP
orm获取关联表里的属性值
2016/04/17 PHP
PHP延迟静态绑定的深入讲解
2018/04/02 PHP
PHP操作Postgresql封装类与应用完整实例
2018/04/24 PHP
PHP进阶学习之Geo的地图定位算法详解
2019/06/19 PHP
JavaScript实现GriwView单列全选(自写代码)
2013/05/13 Javascript
JS过滤url参数特殊字符的实现方法
2013/12/24 Javascript
javascript执行环境及作用域详解
2016/05/05 Javascript
javascript判断firebug是否开启的方法
2016/11/23 Javascript
详解AngularJS通过ocLazyLoad实现动态(懒)加载模块和依赖
2017/03/01 Javascript
Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条
2019/06/24 Javascript
vue 地区选择器v-distpicker的常用功能
2019/07/23 Javascript
Vue的双向数据绑定实现原理解析
2020/02/17 Javascript
[46:14]完美世界DOTA2联赛PWL S3 Magma vs INK ICE 第一场 12.11
2020/12/16 DOTA
Python入门之三角函数atan2()函数详解
2017/11/08 Python
python编程线性回归代码示例
2017/12/07 Python
简单谈谈python中的lambda表达式
2018/01/19 Python
Python中文件的读取和写入操作
2018/04/27 Python
python十进制和二进制的转换方法(含浮点数)
2018/07/07 Python
Python中的groupby分组功能的实例代码
2018/07/11 Python
python将处理好的图像保存到指定目录下的方法
2019/01/10 Python
python SocketServer源码深入解读
2019/09/17 Python
python中使用asyncio实现异步IO实例分析
2021/02/26 Python
python 实现有道翻译功能
2021/02/26 Python
世界顶级俱乐部的官方球衣和套装:Subside Sports
2018/04/22 全球购物
新加坡网上化妆品店:Best Buy World
2018/05/18 全球购物
高性能装备提升营地:Kammok
2019/02/27 全球购物
北京鼎普科技股份有限公司软件测试面试题
2012/04/07 面试题
剪彩仪式主持词
2014/03/19 职场文书
优秀班集体申报材料
2014/12/25 职场文书
2015年建筑工作总结报告
2015/05/04 职场文书
销售人员管理制度
2015/08/06 职场文书
岗位聘任协议书
2015/09/21 职场文书
2016保送生自荐信范文
2016/01/29 职场文书