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

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

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

Partition程序如下:

longPartition (longa[],longp1,longp2)

{//对a[p1]~a[p2]进行分割,返回分割点的序号, p1, p2分别为元组的第一//个和最后一个元素longi, j;intx;

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;returni;

}

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

longOrderStatistics(longa[],longp1,longp2,longk)

{//在a[p1]~a[p2] 中, 找出最小值,并返回值longp, num;if(k<1|| k>p2-p1+1)return-1;if(p1 >= p2)returna[p1];//若a[p1]~a[p2] 只有一个元素,则返回该元素p =Partition(a, p1, p2);

num= p-p1;if(k == num +1)returna[p];//第k小元素为分割点if(k <= num)returnOrderStatistics(a, p1, p-1, k);//第k小元素在前部returnOrderStatistics(a, p+1, p2, k-num-1);//第k 小元素在后部}

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

importrandomdefselect(data, n):#创建一个新列表, 处理小于0的索引, 检查索引的有效性data =list(data)ifn<0:

n+=len(data)ifnot0 <= n <len(data):raiseValueError,"can't get rank %d out of %d"%(n, len(data))#主循环, 看上去类似于排序但不需要递归whileTrue:

pivot=random.choice(data)

pcount=0

under, over=[], []

uappend, oappend=under.append, over.appendforelemindata:ifelem <pivot:

uappend(elem)elifelem >pivot:

oappend(elem)else:

pcount+= 1numunder=len(under)ifn <numunder:

data=underelifn < numunder +pcount:returnpivotelse:

data=over

n-= numunder +pcount

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

defselsor(data, n):

data=list(data)

data.sort()returndata[n]

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

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航