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 相关文章推荐
在Mac OS上部署Nginx和FastCGI以及Flask框架的教程
May 02 Python
Python编程中对super函数的正确理解和用法解析
Jul 02 Python
Python实现拷贝多个文件到同一目录的方法
Sep 19 Python
Windows下安装python MySQLdb遇到的问题及解决方法
Mar 16 Python
python利用paramiko连接远程服务器执行命令的方法
Oct 16 Python
python微信跳一跳系列之棋子定位颜色识别
Feb 26 Python
python实现flappy bird小游戏
Dec 24 Python
Python 实现大整数乘法算法的示例代码
Sep 17 Python
Python元组 tuple的概念与基本操作详解【定义、创建、访问、计数、推导式等】
Oct 30 Python
python实现将range()函数生成的数字存储在一个列表中
Apr 02 Python
python如何解析复杂sql,实现数据库和表的提取的实例剖析
May 15 Python
Python unittest如何生成HTMLTestRunner模块
Sep 08 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 进度条实现代码
2009/03/10 PHP
浅析php变量作用域的一些问题
2013/08/08 PHP
PHP面向对象程序设计之接口的继承定义与用法详解
2018/12/20 PHP
JavaScript 直接操作本地文件的实现代码
2009/12/01 Javascript
js 获取radio按钮值的实例
2013/08/17 Javascript
js实现键盘操作实现div的移动或改变的原理及代码
2014/06/23 Javascript
深入浅析javascript立即执行函数
2015/10/23 Javascript
详解Angular开发中的登陆与身份验证
2016/07/27 Javascript
jQuery插件FusionCharts实现的3D帕累托图效果示例【附demo源码】
2017/03/25 jQuery
对VUE中的对象添加属性
2018/09/18 Javascript
VuePress 快速踩坑小结
2019/02/14 Javascript
微信小程序传值以及获取值方法的详解
2019/04/29 Javascript
layer.open 获取不到表单信息的解决方法
2019/09/26 Javascript
vue监听用户输入和点击功能
2019/09/27 Javascript
Vue 3.0双向绑定原理的实现方法
2019/10/23 Javascript
Vue实现渲染数据后控制滚动条位置(推荐)
2019/12/09 Javascript
uniapp实现可滑动选项卡
2020/10/21 Javascript
Vue实现小购物车功能
2020/12/21 Vue.js
[45:46]2014 DOTA2国际邀请赛中国区预选赛5.21 HGT VS DT
2014/05/23 DOTA
scrapy自定义pipeline类实现将采集数据保存到mongodb的方法
2015/04/16 Python
在Docker上开始部署Python应用的教程
2015/04/17 Python
python使用Tkinter实现在线音乐播放器
2018/01/30 Python
python+opencv识别图片中的圆形
2020/03/25 Python
Python3实现爬取指定百度贴吧页面并保存页面数据生成本地文档的方法
2018/04/22 Python
python+pandas+时间、日期以及时间序列处理方法
2018/07/10 Python
Python 面试中 8 个必考问题
2018/11/16 Python
tensor和numpy的互相转换的实现示例
2019/08/02 Python
Python读取yaml文件的详细教程
2020/07/21 Python
python实现人工蜂群算法
2020/09/18 Python
css3 响应式媒体查询的示例代码
2019/09/25 HTML / CSS
面试后的英文感谢信
2014/02/01 职场文书
党组织公开承诺书
2014/03/29 职场文书
社区党员志愿服务活动方案
2014/08/18 职场文书
导游词幽默开场白
2019/06/26 职场文书
撤回我也能看到!教你用Python制作微信防撤回脚本
2021/06/11 Python
Win10玩csgo闪退如何解决?Win10玩csgo闪退的解决方法
2022/07/23 数码科技