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中使用HTMLParser解析html实例
Feb 08 Python
Python网页解析利器BeautifulSoup安装使用介绍
Mar 17 Python
Python中Class类用法实例分析
Nov 12 Python
Python3导入自定义模块的三种方法详解
Apr 13 Python
flask框架实现连接sqlite3数据库的方法分析
Jul 16 Python
pycharm使用matplotlib.pyplot不显示图形的解决方法
Oct 28 Python
基于python cut和qcut的用法及区别详解
Nov 22 Python
Python终端输出彩色字符方法详解
Feb 11 Python
django中的数据库迁移的实现
Mar 16 Python
使用Dajngo 通过代码添加xadmin用户和权限(组)
Jul 03 Python
Python提取视频中图片的示例(按帧、按秒)
Oct 22 Python
python自动化发送邮件实例讲解
Jan 04 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
Windows下PHP的任意文件执行漏洞
2006/10/09 PHP
小偷PHP+Html+缓存
2006/11/25 PHP
php 代码优化的42条建议 推荐
2009/09/25 PHP
一个简单的php加密解密函数(动态加密)
2013/06/19 PHP
PHP模块memcached使用指南
2014/12/08 PHP
基于php伪静态的实现方法解析
2020/07/31 PHP
JavaScript 设计模式学习 Factory
2009/07/29 Javascript
JavaScript 图像动画的小demo
2012/05/23 Javascript
jquery 插件学习(四)
2012/08/06 Javascript
Jquery遍历Json数据的方法
2015/04/20 Javascript
jQuery实现文本框输入同步的方法
2015/06/20 Javascript
浅谈javascript中new操作符的原理
2016/06/07 Javascript
Jquery揭秘系列:ajax原生js实现详解(推荐)
2016/06/08 Javascript
vue2 如何实现div contenteditable=“true”(类似于v-model)的效果
2017/02/08 Javascript
vue-router路由简单案例介绍
2017/02/21 Javascript
js 毫秒转天时分秒的实例
2017/11/17 Javascript
Vue 项目代理设置的优化
2018/04/17 Javascript
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
2019/04/26 Javascript
Vue.js@2.6.10更新内置错误处机制Fundebug同步支持相应错误监控
2019/05/13 Javascript
layer ui 导入文件之前传入数据的实例
2019/09/23 Javascript
Vue 中获取当前时间并实时刷新的实现代码
2020/05/12 Javascript
[03:08]Ti4观战指南上
2014/07/07 DOTA
python二分法实现实例
2013/11/21 Python
在Python中使用PIL模块处理图像的教程
2015/04/29 Python
python+selenium识别验证码并登录的示例代码
2017/12/21 Python
使用Python+Splinter自动刷新抢12306火车票
2018/01/03 Python
对pandas进行数据预处理的实例讲解
2018/04/20 Python
Python静态类型检查新工具之pyright 使用指南
2019/04/26 Python
Matplotlib scatter绘制散点图的方法实现
2020/01/02 Python
Python 字符串处理特殊空格\xc2\xa0\t\n Non-breaking space
2020/02/23 Python
Python退出时强制运行一段代码的实现方法
2020/04/29 Python
Python基于pandas爬取网页表格数据
2020/05/11 Python
Python分析最近大火的网剧《隐秘的角落》
2020/07/02 Python
python中slice参数过长的处理方法及实例
2020/12/15 Python
模范家庭事迹材料
2014/02/10 职场文书
红色经典电影观后感
2015/06/18 职场文书