首页 > 学院 > 开发设计 > 正文

寻找序列中最小的第N个元素(partition函数实现)

2019-11-14 17:08:57
字体:
来源:转载
供稿:网友

Partition为分割算法,用于将一个序列a[n]分为三部分:a[n]中大于某一元素x的部分,等于x的部分和小于x的部分。

Partition程序如下:

long Partition (long a[], long p1, long p2){//对a[p1]~a[p2]进行分割,返回分割点的序号, p1, p2分别为元组的第一   //个和最后一个元素long i, j;int x;i = p1;j = p2;x = a[i];while (i<j){while ( a[j] >= x && i,j) j--;if (i<j) {a[i] = a[j]; i++;}while (a[i] <= x && i<j) i++;if (i<j) {a [j] = a[i]; j--;}}a[i] = x;return i;}

则利用partition 函数来实现查找第n个元素的程序如下所示:

long OrderStatistics(long a[], long p1, long p2, long k){// 在a[p1]~a[p2] 中, 找出最小值,并返回值long p, num;if (k<1 || k>p2-p1+1) return -1; if (p1 >= p2) return a[p1];//若a[p1]~a[p2] 只有一个元素,则返回该元素p = Partition(a, p1, p2);num = p-p1;if (k == num + 1) return a[p]; //第k小元素为分割点if (k <= num) return OrderStatistics(a, p1, p-1, k); //第k小元素在前部return OrderStatistics(a, p+1, p2, k-num-1); // 第k 小元素在后部 }

Python cookbook 中给出了这一方法的python 实现, 如下所示:

import randomdef select(data, n):# 创建一个新列表, 处理小于0的索引, 检查索引的有效性data = list(data)if n<0:    n += len(data)if not 0 <= n < len(data):    raise ValueError, "can't get rank %d out  of %d" %(n, len(data))# 主循环, 看上去类似于排序但不需要递归while True:    pivot = random.choice(data)    pcount = 0    under, over = [], []    uappend, oappend = under.append, over.append    for elem in data:        if elem < pivot:            uappend(elem)        elif elem > pivot:            oappend(elem)        else:            pcount += 1    numunder = len(under)    if n < numunder:        data = under    elif n < numunder + pcount:        return pivot    else:        data = over        n -= numunder +pcount

作者提到,也可以通过下面的简单方法实现第k个元素的查找:

def selsor(data, n):    data = list(data)    data.sort()    return data[n]

以上两种方法都可以实现,但是“基于列表的sort方法的实现的确简单的多, 实现select也确实需要多付出一点力气, 但如果n足够大而且比较操作的开销也无法忽略的话,select就体现出它的价值了。”


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表