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选择排序算法的实现代码
Nov 21 Python
Python实现的数据结构与算法之基本搜索详解
Apr 22 Python
Python中用于计算对数的log()方法
May 15 Python
python使用mysql数据库示例代码
May 21 Python
Python实现模拟分割大文件及多线程处理的方法
Oct 10 Python
Python检测数据类型的方法总结
May 20 Python
python查看文件大小和文件夹内容的方法
Jul 08 Python
python实现人工智能Ai抠图功能
Sep 05 Python
基于python使用tibco ems代码实例
Dec 20 Python
Python交互环境下打印和输入函数的实例内容
Feb 16 Python
Python新手学习标准库模块命名
May 29 Python
什么是python的必选参数
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 park、unpark、ord 函数使用方法(二进制流接口应用实例)
2010/10/19 PHP
PHP函数eval()介绍和使用示例
2014/08/20 PHP
PHP Callable强制指定回调类型的方法
2016/08/30 PHP
php图像验证码生成代码
2017/06/08 PHP
基于php双引号中访问数组元素报错的解决方法
2018/02/01 PHP
javascript从右边截取指定字符串的三种实现方法
2013/11/29 Javascript
swtich/if...else的替代语句
2015/08/16 Javascript
jquery原理以及学习技巧介绍
2015/11/11 Javascript
JS常见问题之为什么点击弹出的i总是最后一个
2016/01/05 Javascript
Angular.js中angular-ui-router的简单实践
2017/07/18 Javascript
SeaJS中use函数用法实例分析
2017/10/10 Javascript
详解vue 实例方法和数据
2017/10/23 Javascript
利用canvas中toDataURL()将图片转为dataURL(base64)的方法详解
2017/11/20 Javascript
vue2.0与bootstrap3实现列表分页效果
2017/11/28 Javascript
tangram.js库实现js类的方式实例分析
2018/01/06 Javascript
Vue.js获取被选择的option的value和text值方法
2018/08/24 Javascript
vue制作抓娃娃机的示例代码
2020/04/17 Javascript
[42:20]Winstrike vs VGJ.S 2018国际邀请赛淘汰赛BO3 第二场 8.23
2018/08/24 DOTA
用Python的Django框架编写从Google Adsense中获得报表的应用
2015/04/17 Python
Python 实现在文件中的每一行添加一个逗号
2018/04/29 Python
numpy中以文本的方式存储以及读取数据方法
2018/06/04 Python
python3 实现对图片进行局部切割的方法
2018/12/05 Python
python 定时器,轮询定时器的实例
2019/02/20 Python
Python垃圾回收机制三种实现方法
2020/04/27 Python
在Mac中配置Python虚拟环境过程解析
2020/06/22 Python
CSS3简单实现照片墙
2014/12/12 HTML / CSS
雅萌 (YA-MAN) :日本美容家电领域的龙头企业
2017/05/12 全球购物
Zooplus葡萄牙:欧洲领先的网上宠物商店
2018/07/01 全球购物
大专自我鉴定范文
2013/10/23 职场文书
11月红领巾广播稿
2014/01/17 职场文书
互联网创业计划书的书写步骤
2014/01/28 职场文书
颂军魂爱军营演讲稿
2014/09/13 职场文书
秋冬农业生产标语
2014/10/09 职场文书
检讨书1000字
2014/10/11 职场文书
2019年世界儿童日宣传标语
2019/11/22 职场文书
排查并解决MySQL生产库内存使用率高的报警
2022/04/11 MySQL