通过计算实现分级定位的排序和查找的方法

文档序号:6654014阅读:300来源:国知局
专利名称:通过计算实现分级定位的排序和查找的方法
一种计算机对于一组无序的数据进行排序和一组有序的数据进行查找的方法。
目前时间复杂度较好的有快速排序、堆排序、希尔排序、归并排序等,除希尔排序外,其它几种都是借助“比较”进行排序的算法,根据斯特林公式,有[log2(n!)]=O(nlogn),上述结论从数量级上告诉我们,借助“比较”进行排序的算法在最坏情况下能达到的最好时间复杂度为O(nlogn)。基数排序不是借助“比较”进行排序的算法,时间复杂度为O(d*n),其中d为关键字从最高位到最低位的位数。这就是说,以上都是多趟排序。而且前三种是不稳定排序。
有没有一种理想化的排序方法呢?对于完全无序的n个数进行排序,理想化的方法应该是每取出一个数,可以通过计算直接找到其所应该排在的位置,当n个数全部经过一趟计算后,全部找到其所应该排在的位置,这样就完成了排序。显然,理想化排序应该只要进行一趟排序即可完成排序,这大概不可能。
本发明的目的之一是要提供一种一趟或少数趟即可完成的稳定排序方法,使对于完全无序的数据进行排序,其时间复杂度降低至接近O(n),即接近理想化的排序。目的之二是提供一种通过计算查找,直接在n个数中确定一个很小的查找范围,以利于提高查找速度。目的之三是改造传统的归并排序法,屏弃归并排序法所采用的递归调用方法,只用一个单一的程序实现归并排序,从而提高排序速度。
在本发明的原理描述中,为统一起见,本说明以类pascal为基本语言,规定数组下标为从1开始的正整数,并增加规定可以使用动态数组或可调数组。本方法完全可以应用于其它语言,数组下标为不同规定的情况。为了叙述简便,将待排序关键字X(j).Key都简化为待排序数X(j)。
本发明是分级定位排序和分级定位查找,其基本原理是将排序和查找都各分为分级处理阶段和完成阶段。所谓分级处理是将待排序数的分布范围或待搜索数的分布范围划分为多个级别,用一个作为分级变量的数组来表示这些级别,使每个级别的大小对应着一个分级变量数组元素的下标值,当取出一个待处理数(即待排序数或待查找数)时,用一个变换关系得到该待处理数与上述数组元素的下标值的对应关系,使该待处理数直接进入它所对应的级别。分级定位排序的两个阶段为一、分级排序阶段。根据待排序数X(j)(j=1…n)所在的级别大小进行分级排序,待排序数的最大数为Max,最小数为Min,所以待排序数的分布范围为Max-Min,将分布范围预设为m个大小级别,每个级别对应一个数组元素B(i),B(i)称为分级变量,其中的下标i用于表示级别大小(i=1…m),称为级别变量,每个分级变量B(i)都能够容纳多个数,每当取出一个待排序数,对应其大小,可以直接通过计算换算为B(i)下标值i的大小,找到其所应该归属的级别B(i),从而无须查找就可以直接放入分级变量B(i)之中;当待排序的n个数全部经过一趟计算后,都直接找到其所应该归属的分级变量B(i),就完成了按级别大小的分级排序。在分级排序前是全程无序,在分级排序后仅仅是级内无序,级与级之间已有序化,排序难度降低。分级排序的每个分级变量B(i)都必须能够存放多个数据,所以B(i)包含着下级静态数组或动态数组或指向一个动态数据结构。比如,为了节省辅助存储空间,采用数组堆栈结构,数组B的每一个元素B(i)都是指向一个堆栈的指针,于是,当某个数据划分到分级变量B(i)时,就被压入到B(i)所指向的堆栈之中。同时,每个级别都有一个级内计数器k(i)统计该级别中数据个数,之所以要用数组变量k(i)的形式,为的是不至于使某一级别的计数器与其它级别的计数器搞混淆。
二、完全排序阶段,包括数据收集和级内排序两项操作。当遇到空级别(该级别中无关键字)k(i)=0时,跳转处理下个级别;当遇到恰好一个关键字的级别k(i)=1时,将关键字收集到数组D(t)之中,再跳转处理下个级别;当遇到多个关键字的级别k(i)>1时,先进行级内排序,再将关键字收集到数组D(t)之中,然后跳转处理下个级别。当数据被收集到数组D(t)之中时,假定级别B(i)中的数据在数组D(t)中基准位置(起始位置或结束位置)为t,为了以后的分级查找的需要,将t保存到数组E(i)中。
分级定位查找的两个阶段为一、确定查找范围阶段。给出一个待查找数据X后,传统方法是在待搜索数域全程查找,分级查找是在分级排序基础上,将X直接通过变换,成为E(i)下标i的大小,根据E(i)中存放的t,找到X在数组D(t)中的基准位置t,又根据k(i)确定其查找跨度。
二、定位查找阶段。在由t和k(i)确定的范围内进行查找,比如二分查找。
分级定位排序的操作过程实施例结合附图进行解释。


图1表示了待排序数X的概率密度曲线f(x)与分级排序的关系。横坐标为待排序数X的大小值,纵坐标为X的概率密度f(x),在图1示的概率密度曲线中,数据的最小值为MIN,最大值为MAX,曲线上的竖格对应的数据(1)、(2)、(3)、(i-1)、(i)、(i+1)、(n-1)、(n)不是横坐标X的大小,而是分级变量B(i)的下标值(i)的大小,它们对应的X坐标值分别为X1、X2、X3、Xi-1、Xi、Xi+1、Xn-1、Xn,我们可以将每一个小区间的X值通过一个变换G,换算成(i)的大小G(X)=(1),当X∈[X1,X2);G(X)=(2),当X∈[X2,X3);…;G(X)=(i-1), 当X∈[Xi-1、Xi);G(X)=(i),当X∈[Xi,Xi+1);…;G(X)=(n-1), 当X∈[Xn-1,Xn);G(X)=(n),当X=Xn。
每一个X值都对应于一个下标值(i),于是,每一个X值都可以分配到对应的数组元素B(i)之中。
图2是分级排序示意图。1-待排序数。2-由数组B(i)引导的分级变量(i=1..6),数组B的每一个元素B(i)都有一个箭头,这是指向一个堆栈的指针。3-级内堆栈,当某个数据划分到分级变量B(i)时,就被压入到B(i)所指向的堆栈之中。
图3是分级排序流程图。4-定义分级变量最大下标。X(N)为待排序数组,B(M)为分级变量数组指针,D(N)为完全排序后的数组,以上三个数组都预知最大下标,可以定义为静态数组变量。5-将待排序关键字送入一个数组变量X(j),为计算大小级别B(i)作准备;如果程序安排为逐个送入变量X,也可以不用将待排序关键字送入数组变量。6-将级内计数器k(i)赋初值,令k(i)=0(i=1..M),为计数作准备;同时,求出Max、Max2...MaxQ和Min、Min2...MinR,Max为最大数,Max2为第2大数,MaxQ为第Q大数;Min为最小数、Min2为第2小数,MinR为第R小数;确定待排序数的分布范围,在此范围内的字视为有效关键字,简称关键字;在此范围外的字视为无效关键字,简称结束字。7-逐个对N个关键字进行分级处理。8-将关键字的范围均匀划分为M个等级的分级运算表达式,计算出分级变量B(i)的级别i,分级函数表达式为i=1+trunc((m-1)*(X(j)-MIN)/(MAX-MIN)),实际上就是对均匀分布函数取整,还可以根据N、M和Max、Max2...MaxQ、Min、Min2...MinR的分布情况,选择其它分布函数进行分级运算,如正态分布函数、指数分布函数、t分布函数、F分布函数、x2分布函数、泊松分布函数;表达式中出现的“+1”,是由于通常PASCAL语言中的数组下标最小值等于1,如果没有这个限制,当然不要“+1”这项。9-B(i)…表示数组元素B(i)所指向的堆栈;当某个数X(j)被确定级别i后,压入由数组元素B(i)所指向的一个堆栈B(i)…,如[new(bbb);bbb^.c1=a[j];bbb^.link=b[i];b[i]=bbb;];同时,令级内计数器K(i)=K(i)+1,统计第i级堆栈中被压入数据个数。
图4是数据收集和级内排序程序流程图。
10-逐级对已经分为M个级别的数据进行数据收集和级内排序处理。11-当遇到空级别(该级别中无关键字)k(i)=0时,跳转处理下个级别。12-当遇到恰好一个关键字的级别k(i)=1时,将堆栈B(i)…中的数收集到数组D(t)之中,并登记该关键字在数组D(t)中的位置t至数组E(i),再跳转处理下个级别。13-当遇到多个关键字的级别k(i)>1时,先进行级内排序;如果级内数据量小(k(i)<N1),调用冒泡排序法速度快;如果级内数据量大,调用归并排序法速度快;如果级内数据量很大,可以递归调用分级排序程序。14-级内排序后,将该级别收集到数组D(t)的第一个位置t登记到数组E(i)。15-将级内排序后的数据收集到数组D(t)之中,再跳转处理下个级别。
图5是分级查找的程序流程图。
16-对待查找数据X进行分级计算,得出级别i值。17-如果K(i)=0,表示该级别中没有数据,结束查找。18-如果K(i)>0,由E(i)的值确定X在数组D(t)中的起始查找位置t,由K(i)确定查找跨度。19-从t至t+K(i)-1范围内查找数组D(t)中有无X存在,这一步查找可以调用传统的任何一种查找方法,比如调用二分查找法。
从以上分级定位排序方法可知,排序时间由三部分构成,1、分级排序时间;2、级内排序时间;3、关键字收集时间。
分级排序时间取决于待排序关键字的个数n和分级函数的计算复杂度,而与分级数m无关,如果将待排序关键字的个数n和分级函数的计算复杂度固定,分级排序时间即固定,同时可知,均布分级函数计算复杂度最低,所用时间最少。
级内排序时间,取决于(1)所采用的排序方法优劣;(2)多关键字级别个数;(3)级内多关键字个数。换句话说,取决于分级数m,m越大则(2)和(3)都会降低,所以级内排序时间越短。
关键字收集时间与分级数m有关,收集操作次数等于n加空级别数目,至少为n,所以m<n是不合理的,应该取m值大于n。当m>n时,空级别数目不小于m-n,当m>>n时,空级别数目大致为m-n≈m。分级数增加将引起空级别数增加,从而引起关键字收集时间变长。
综合考虑三个时间因素,由于关键字收集时对空级别的操作复杂度相对于分级排序和级内排序的复杂度低得多,所以适量增加分级数m,虽然会增加空级别数目,但是可以较大地降低多关键字级别个数和级内多关键字个数,减少级内排序时间,降低总时间,所以,m应该是数倍于n,比如选择m=(2~5)*n是可取的。
以下实施例以PASCAL为编程工具,提供分级排序程序。为了节省版面,用“//”表示另起一行。
*分级排序程序*<pre listing-type="program-listing"><![CDATA[PROGRAM aspx(input,output);CONST //N=11;M=22;TYPE //count=1..M;//pt=^pt1;//pt1=record//c1integer;//linkpt;//end;VAR //i,j,tcount;//a,d,e,kARRAY[count] OF integer;//b,bbarray[1..m] of pt;//bbbpt;//min,max,q,rinteger;BEGIN//{假定有以下待排序数}a[1]=21;a[2]=11;a[3]=6;a[4]=2;a[5]=22;a[6]=23;a[7]=9;a[8]=32;a[9]=45;a[10]=19;a[11]=21;for t=1 to M do k[t]=0//max=a[1];min=a[1];for t=2 to n do//begin//if max<a[t]then max=a[t]//else;if min>a[t]then min=a[t]//end;{分级排序}m1=m-1;//mm=max-min;for j=1 to n do//begin//i=trunc(m1*(a[j]-min)/mm)+1;k[i]=k[i]+1;//new(bbb);//bbb^.c1=a[j];bbb^.link=b[i];//b[i]=bbb;//end;{数据收集和级内排序}t=1;//for i=1 to m do//begin//if k[i]>0 then//beginif k[i]=1 then//begin//d[t]=b[i]^.c1;//e[i]=t;//t=t+1;//end elsebegin//e[i]=t;//for r=1 to k[i] do{调用级内排序子程序,如冒泡排序或归并排序,然后收集到d[t]中}end;//end;//end; {分级查找,待查数为X}i=trunc(m1*(X-min)/mm)+1;//t=e[i];//for j=t to t+k[i]-1 do{调用二分查找子程序}//end.]]></pre>归并排序法是一种快速且稳定的排序方法,但是传统归并排序法采用子程序递归调用的方法还是对运算速度有阻碍。为了屏弃传统归并排序法中的子程序递归调用方法,提出一种走路式归并排序法。考虑到在分级排序的基础上,每一级的数据不会很多,内存占用不会很多,故可以采用数组以提高运行速度;如果数据量较大,也可以采用数组堆栈。下面结合附图6、附图7进行说明。
图6是走路式归并排序第一趟排序的框图。
20-归并排序时,将分级排序中的级内数据个数K(i)作为归并排序时的待排序个数n。21-设级别i的分级变量B(i)中有n个待排序数B(i).C(h)(h=1..n)。22-第一趟排序循环,第一趟排序时,待排序数B(i).C(h)的个数为n个,视为n列,两两相邻列数据为一组进行排序,即1列与2列、3列与4列…(2*t-1)列与(2*t)列,等等,将2*t列排序为t列,循环t=1 to trunc(t/2)是为了将前偶数列排序。23-将(2*t-1)列与(2*t)列数据两两比较,排序为t列p序列,P(t)表示P序列的第t列,C(k)表示序列中的第k个元素;每个p序列以MAX+1作为结束字,在走路式归并排序中,所有的序列都以结束字结尾,根据结束字判断该序列是否结束,即通过判断结束字来控制循环,而无须考虑某一列有多少数据元素。24-如果被排序序列为奇数个,将最后一列作为一个p序列。
图7是走路式归并排序的走路式框图。
25-当被排序序列个数为大于1时,进行走路式归并排序,不断地进行将p序列两两排序为q序列,又将q序列两两排序为p序列,再将p序列两两排序为q序列,…,的循环运算,直至最后为一个序列。26-将被排序列数t赋值给n;27-进行一趟排序,将p序列中的前偶数列两两排序为q序列,即1列与2列、3列与4列…(2*t-1)列与(2*t)列,并将每个q序列以MAX+1作为结束字;28-两个序列都有数据时的算法;29-比较两列顶部数据的大小并排序;Q(t)表示Q序列的第t列,P(t)表示P序列的第t列;C(k)表示序列中的第k个元素。30-31-两p序列中,只剩一列有数据时,将剩下的这些数据直接送入q序列。32-每个q序列以结束字结束;33-如果被排序p序列为奇数个,将最后一个p序列直接换成一个q序列。34-将上一趟的序列个数t作为这一趟的待排序序列个数n;35-进行下一趟排序,将q序列两两排序为p序列,与27至33的过程相同,27至34进行的排序是将p序列两两排序为q序列,而35所进行的是将q序列两两排序为p序列。35后再回转到25处,循环进行将p序列两两排序为q序列,将q序列两两排序为p序列,直至最后为一个序列。
以下以FOXPRO为编程工具,提供“走路式归并排序程序”,p(t,i)表示P序列中第t列的第i个元素;q(t,j)表示q序列中第t列的第j个元素;X(i)为待排序数。
*****走路式归并排序<pre listing-type="program-listing"><![CDATA[input″请输入待排序元素个数″to N//dime X(N),p(N,N),q(N,N) *将N个数两两归并为N/2列或N/2+1列。t=1//do while t<=int(N/2)//if X(2*t-1)<=X(2*t)//p(t,1)=X(2*t-1)//p(t,2)=X(2*t)//p(t,3)=max+1//t=t+1//elsep(t,1)=X(2*t)//p(t,2)=X(2*t-1)//p(t,3)=max+1//t=t+1ENDIF//enddo//if int (N/2)<N/2p(t,1)=X(2*t-1)//p(t,2)=max+1//t=t+1//endif//t=t-1 *走路式归并do while t>1 {当列个数大于1时,进入下面归并程序}*将N列P序列两两归并为N/2列或N/2+1列Q序列*n=t//t=1//do while t<=int(N/2)//store 1 to i,j,kdo while p(2*t-1,i)<(max+1).And.p(2*t,j)<(max+1)if p(2*t-1,i)<=p(2*t,j)//q(t,k)=p(2*t-1,i)//i=i+1//elseq(t,k)=p(2*t,j)//j=j+1//endif//k=k+1//enddodo while p(2*t-1,i)<max+1//q(t,k)=p(2*t-1,i)//k=k+1//i=i+1//enddodo while p(2*t,j)<max+1//q(t,k)=p(2*t,j)//k=k+1//j=j+1//enddoq(t,k)=max+1//t=t+1//enddo//t=t-1//store 1 to i,k//if int(N/2)<N/2//t=t+1//do while p(2*t-1,i)<max+1//q(t,k)=p(2*t-1,i)//k=k+1//i=i+1//enddoq(t,k)=max+1//endif*将N列Q序列两两归并为N/2列或N/2+1列P序列*n=t//t=1//do while t<=int(n/2)//store 1 to i,j,kdo while q(2*t-1,i)<(max+1).And.q(2*t,j)<(max+1)if q(2*t-1,i)<=q(2*t,j)//p(t,k)=q(2*t-1,i)//i=i+1//elsep(t,k)=q(2*t,j)//j=j+1//endif//k=k+1//enddodo while q(2*t-1,i)<max+1//p(t,k)=q(2*t-1,i)//k=k+1//i=i+1//enddodo while q(2*t,j)<max+1//p(t,k)=q(2*t,j)//k=k+1//j=j+1//enddop(t,k)=max+1//t=t+1//enddo//t=t-1//store 1 to i,k//if int(N/2)<N/2//t=t+1do while q(2*t-1,i)<max+1//p(t,k)=q(2*t-1,i)//k=k+1//i=i+1//enddop(t,k)=max+1//endif//enddo]]></pre>
权利要求
1.一种通过计算实现分级定位的排序和查找的方法,目前已有多种排序和查找本发明的特征是将待排序数的分布范围或待搜索数的分布范围划分为多个级别,用一个作为分级变量的数组来表示这些级别,每个级别的大小对应着一个分级变量数组元素的下标值,当取出一个待处理数(即待排序数或待查找数)时,用一个变换关系得到该待处理数与上述数组元素的下标值的对应关系,使该待处理数直接进入它所对应的级别。
2.根据权利要求1所述的分级定位的排序和查找的方法,其进一步的特征是将排序分为分级排序阶段和完全排序阶段,所谓分级排序是,根据待排序数X(j)(j=1…n)所在的级别大小进行分级排序,待排序数的最大数为Max,最小数为Min,所以待排序数的分布范围为Max-Min,将分布范围预设为m个大小级别,每个级别对应一个数组元素B(i),B(i)称为分级变量,其中的下标i用于表示级别大小(i=1…m),称为级别变量,每个分级变量B(i)都能够容纳多个数,每当取出一个待排序数,对应其大小,可以直接通过变换关系换算为B(i)下标值i的大小,找到其所应该归属的级别B(i),从而无须查找就可以直接放入分级变量B(i)之中;当待排序的n个数全部经过一趟计算后,都直接找到其所应该归属的分级变量B(i),就完成了按级别大小的分级排序。
3.根据权利要求1、2所述的分级定位的排序方法,其进一步的特征是分级排序的每个分级变量B(i)都能够存放多个数据,分级变量B(i)中存放多个数据的结构可以采用数组堆栈结构,也可以在每一级分级变量B(i)中采用一个静态数组或动态数组;当待排序数据量大时,分级变量B(i)中存放多个数据的结构采用数组堆栈结构,分级变量数组B的每一个元素B(i)都是指向一个堆栈的指针,于是,当某个数据划分到分级变量B(i)时,就被压入到B(i)所指向的堆栈之中。
4.根据权利要求1、2所述的分级定位的排序方法,其进一步的特征是每个级别的分级变量B(i)都有一个级内计数器k(i)统计该级别中数据个数。
5.根据权利要求1、2所述的分级定位的排序方法,其进一步的特征是分级变换关系包括各种分布函数分级,如均匀分布函数、正态分布函数、指数分布函数、t分布函数、F分布函数、x2分布函数、泊松分布函数。
6.根据权利要求1、2所述的分级定位的排序方法,其进一步的特征是在分级排序后,当分级变量B(i)中有两个以上数据时,需要对该级内的数据进行排序,当某级中的数据非常多时,可以对该级别使用分级排序;当某级中的数据不很多时,可以用传统的排序方法。
7.根据权利要求1所述的分级定位的排序和查找的方法,其进一步的特征是定义一个数据收集数组D(t),将完成了分级排序和级内排序的数组收集到其中;在数据收集时,首先判断所处理的这个级别中数据是否为零,如果为零则立即跳转处理下个级别;否则再判断所处理的这个级别B(i)中数据是否为1,如果为1则将该数据收集到数据收集数组D(t)中,同时将该数据在D(t)中的位置t登记于数组元素E(i),然后跳转处理下个级别;如果所处理的这个级别B(i)中数据大于1,先要进行级内排序,然后再将该级别中的k(i)个数据收集于D(t)中,同时,将该级别数据在D(t)中的起始位置t或终了位置t登记于数组元素E(i),数组元素E(i)表示第i级数据在D(t)中的基准位置。
8.根据权利要求1所述的分级定位的排序和查找的方法,其进一步的特征是在分级定位排序的基础上,给出一个待查找数据X后,首先根据待查找数据大小,直接通过变换关系换算为E(i)下标值i的大小,然后根据E(i)中存放的t,找到X在数组D(t)中的基准位置t,又根据k(i)确定其查找跨度,从而确定了待查找数据的小范围,然后在此小范围内使用传统的方法如二分法查找。
9.根据权利要求1所述的分级定位的排序和查找的方法,在级内排序时,如果级内数据量比较大,可以采用传统的排序方法,其进一步的特征是采用走路式归并排序,①、第一趟排序,将待排序数两两排序为p序列,并将每个结果序列以结束字结尾;②、将每两个P序列排列成一个q序列,并将每个结果序列以结束字结尾;如果P序列为奇数个,将最后一个P序列直接换成q序列;③、将每两个q序列排列成一个p序列,并将每个结果序列以结束字结尾;如果q序列为奇数个,将最后一个q序列直接换成P序列;④、象走路一样,②-③-②-③-②-③-……,不断地进行将P序列两两归并为Q序列,又将Q序列两两归并为P序列的循环运算,直至最后为一个序列。
10.根据权利要求1所述的分级定位的排序和查找的方法,其进一步的特征是在走路式归并排序过程中,所有的序列都以结束字结尾,编程时,通过判断结束字来控制循环,只根据结束字来判断该序列是否结束,而无须考虑该列有多少数据元素。
全文摘要
一种通过计算实现分级定位的排序和查找的方法,将排序分为分级排序和完全排序两个过程。分级排序的思想是,将待排序数1的范围预设为m个大小级别B(1)-B(m),每取出一个数通过计算后,直接找到其所应该归属的级别2,即级别B(1)-B(m),当待排序的n个数全部经过一趟计算后,全部找到其所应该归属的级别,完成按级别大小的分级排序。然后再进行完全排序,包括数据收集和级内排序。
文档编号G06F12/00GK1380606SQ0110699
公开日2002年11月20日 申请日期2001年4月11日 优先权日2001年4月11日
发明者陈启星 申请人:陈启星
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1