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中nan与inf转为特定数字方法示例
May 11 Python
Python实现导出数据生成excel报表的方法示例
Jul 12 Python
pandas的object对象转时间对象的方法
Apr 11 Python
解决Ubuntu pip 安装 mysql-python包出错的问题
Jun 11 Python
对matplotlib改变colorbar位置和方向的方法详解
Dec 13 Python
Python文件操作中进行字符串替换的方法(保存到新文件/当前文件)
Jun 28 Python
Django获取应用下的所有models的例子
Aug 30 Python
Python流程控制 if else实现解析
Sep 02 Python
python向图片里添加文字
Nov 26 Python
解决python3插入mysql时内容带有引号的问题
Mar 02 Python
django模型动态修改参数,增加 filter 字段的方式
Mar 16 Python
Python结合Window计划任务监测邮件的示例代码
Aug 05 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 cache类代码(php数据缓存类)
2010/04/15 PHP
smarty的section嵌套循环用法示例
2016/05/28 PHP
PHP实现的网站目录扫描索引工具
2016/09/08 PHP
基于JQuery框架的AJAX实例代码
2009/11/03 Javascript
onkeypress字符按键兼容所有浏览器使用介绍
2013/04/24 Javascript
新增加的内容是如何将div的scrollbar自动移动最下面
2014/01/02 Javascript
jQuery修改class属性和CSS样式整理
2015/01/30 Javascript
学习jQuey中的return false
2015/12/18 Javascript
初识angular框架后的所思所想
2016/02/19 Javascript
JavaScript正则表达式exec/g实现多次循环用法示例
2017/01/17 Javascript
JavaScript中的遍历详解(多种遍历)
2017/04/07 Javascript
JavaScript创建对象的七种方式全面总结
2017/08/21 Javascript
基于vue和react的spa进行按需加载的实现方法
2018/09/29 Javascript
react+redux仿微信聊天界面
2019/06/21 Javascript
Vue动态面包屑功能的实现方法
2019/07/01 Javascript
Nuxt.js实战和配置详解
2019/08/05 Javascript
使用vue-router切换页面时实现设置过渡动画
2019/10/31 Javascript
vue 指令和过滤器的基本使用(品牌管理案例)
2019/11/04 Javascript
python判断windows隐藏文件的方法
2014/03/21 Python
Python中处理unchecked未捕获异常实例
2015/01/17 Python
详解Tensorflow数据读取有三种方式(next_batch)
2018/02/01 Python
python实现逆序输出一个数字的示例讲解
2018/06/25 Python
Python list列表中删除多个重复元素操作示例
2019/02/27 Python
解决安装python3.7.4报错Can''t connect to HTTPS URL because the SSL module is not available
2019/07/31 Python
Python爬虫爬取Bilibili弹幕过程解析
2019/10/10 Python
python创建学生成绩管理系统
2019/11/22 Python
pyinstaller打包单文件时--uac-admin选项不起作用怎么办
2020/04/15 Python
Python的Django框架实现数据库查询(不返回QuerySet的方法)
2020/05/19 Python
关于css兼容性问题及一些常见问题汇总
2016/05/03 HTML / CSS
HTML5 Web Workers之网站也能多线程的实现
2013/04/24 HTML / CSS
美发店5.1活动方案
2014/01/24 职场文书
函授毕业自我鉴定
2014/02/04 职场文书
计算机科学技术自荐信
2014/06/12 职场文书
2014年团队工作总结
2014/11/24 职场文书
会计工作态度自我评价
2015/03/06 职场文书
高中生物教学反思
2016/02/20 职场文书