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解析中国天气网的天气数据
Mar 21 Python
Python编程对列表中字典元素进行排序的方法详解
May 26 Python
tensorflow 打印内存中的变量方法
Jul 30 Python
Python实现的读取/更改/写入xml文件操作示例
Aug 30 Python
网易有道2017内推编程题 洗牌(python)
Jun 19 Python
简单了解python中对象的取反运算符
Jul 01 Python
python连接PostgreSQL过程解析
Feb 09 Python
Python爬虫爬取百度搜索内容代码实例
Jun 05 Python
python实现登录与注册系统
Nov 30 Python
django中cookiecutter的使用教程
Dec 03 Python
python基于opencv 实现图像时钟
Jan 04 Python
python中PyQuery库用法分享
Jan 15 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中Cookie与Session的异同
2016/02/19 PHP
thinkphp下MySQL数据库读写分离代码剖析
2017/04/18 PHP
PHP递归的三种常用方式
2019/02/28 PHP
模拟多级复选框效果的jquery代码
2013/08/13 Javascript
jquery的attr方法禁用表单元素禁用输入内容
2014/06/23 Javascript
基于javascript代码实现通过点击图片显示原图片
2015/11/29 Javascript
javascript原型继承工作原理和实例详解
2016/04/07 Javascript
seajs学习之模块的依赖加载及模块API的导出
2016/10/20 Javascript
详解百度百科目录导航树小插件
2017/01/08 Javascript
vue.js+Echarts开发图表放大缩小功能实例
2017/06/09 Javascript
你有必要知道的10个JavaScript难点
2017/07/25 Javascript
判断div滑动到底部的scroll实例代码
2017/11/15 Javascript
前端必备插件之纯原生JS的瀑布流插件Macy.js
2017/11/22 Javascript
element-ui 表格实现单元格可编辑的示例
2018/02/26 Javascript
详解Angular5 路由传参的3种方法
2018/04/28 Javascript
详解Puppeteer 入门教程
2018/05/09 Javascript
简述vue-cli中chainWebpack的使用方法
2019/07/30 Javascript
Taro小程序自定义顶部导航栏功能的实现
2020/12/17 Javascript
ES2020让代码更优美的运算符 (?.) (??)
2021/01/04 Javascript
删除DataFrame中值全为NaN或者包含有NaN的列或行方法
2018/11/06 Python
详解python3 + Scrapy爬虫学习之创建项目
2019/04/12 Python
Python 函数绘图及函数图像微分与积分
2019/11/20 Python
Python 字节流,字符串,十六进制相互转换实例(binascii,bytes)
2020/05/11 Python
python 删除excel表格重复行,数据预处理操作
2020/07/06 Python
浅谈matplotlib 绘制梯度下降求解过程
2020/07/12 Python
解决Python 函数声明先后顺序出现的问题
2020/09/02 Python
建筑系毕业生自我鉴定
2014/01/24 职场文书
《东方明珠》教学反思
2014/04/20 职场文书
廉洁教育学习材料
2014/05/19 职场文书
纪检干部对照检查材料
2014/08/22 职场文书
办理收楼委托书范本
2014/10/09 职场文书
以权谋私检举信范文
2015/03/02 职场文书
成品仓管员岗位职责
2015/04/01 职场文书
汽车销售员工作总结
2015/08/12 职场文书
微信小程序结合ThinkPHP5授权登陆后获取手机号
2021/11/23 PHP
MySQL详解进行JDBC编程与增删改查方法
2022/06/16 MySQL