计算机软件基础(孟彩霞)第4章查找和排序.ppt
《计算机软件基础(孟彩霞)第4章查找和排序.ppt》由会员分享,可在线阅读,更多相关《计算机软件基础(孟彩霞)第4章查找和排序.ppt(132页珍藏版)》请在三一办公上搜索。
1、第4章 查 找 和 排 序,4.1 线性表查找 4.2 二叉排序树的查找 4.3 哈希查找 4.4 排序 习题,4.1 线性表查找,查找(Searching),也称检索,亦即查表,就是在大量的信息集中寻找一个“特定的”信息元素。人们几乎每天都要做“查找”工作,如查寻电话号码、查字典、查图书目录卡片等。为确切定义查找,先引入几个概念。查找表:由同一类型的数据元素(或记录)构成的集合。,关键字(key):数据元素中可以惟一标识一个数据元素的数据项。如学生的学号,居民身份证号等。查找就是根据给定的关键字值,在查找表中确定一个关键字等于给定值的记录或数据元素。若存在这样的数据元素,则称查找是成功的,否
2、则称查找不成功。决定查找操作的是关键字,因此这里讨论时,只关注记录中的关键字域,而一概忽略记录中其它诸域的信息。,查找是许多重要的计算机程序中最耗费时间的部分,查找算法的优劣密切关系着查找操作的速度,因此对查找算法应认真研究。关于查找,目前主要研究两方面的问题:(1)查找的方法。因为查找某个数据元素依赖于该数据元素在一组数据中所处的位置,即该组数据的组织方式,故应按照数据元素的组织方式决定采用的查找方法;反过来,为了提高查找方法的效率,要求数据元素采用某些特殊的组织方式。,(2)查找算法的评价。衡量一个算法的标准主要有两个:时间复杂度和空间复杂度。就查找算法而言,通常只需要很少的辅助空间,因此
3、更关心的是它的时间复杂度。在查找算法中,基本运算是给定值与关键字的比较,所以算法的主要时间是花费在“比较”上。下面给出一个称为平均查找长度的概念,作为评价查找算法好坏的依据。对于含有n个数据元素的查找表,查找成功时的平均查找长度为,ASL=,其中,Pi为查找第i个数据元素的概率;Ci为查到第i个数据元素时,需与关键字进行比较的次数。,4.1.1 顺序查找 顺序查找是最简单、常用的查找技术。其基本思想是:从表的一端开始,依次将每个元素的关键字同给定值K进行比较,若某个元素的关键字等于给定值K,则表明查找成功,返回该元素的下标;反之,若直到所有元素都比较完毕,仍找不到关键字为K的元素,则表明查找失
4、败,返回特定的值(常用1表示)。,顺序查找方法既适用于以顺序存储结构组织的查找表的查找,也适用于以链式存储结构组织的查找表的查找。在本章的有关查找和排序算法中,假设线性表均采用顺序存储结构,其类型说明为:,#define MAXLEN n/*n为查找表中元素个数的最大可能值*/struct elementint key;/*设关键字的类型为整型*/int otherterm;/*为说明起见,除关键字外只有一个整型数据项*/;typedef struct element DATATYPE;DATATYPE tableMAXLEN;,算法4-1 顺序查找算法。int seqsearch1(DATA
5、TYPE A,int k)int i;i=0;while(Ai.key!=k)if(Ai.key=k),return i;/*查找成功,返回被查元素在表中的相对位置*/elsereturn 1;/*查找失败,返回1*/若对此算法进行一些改进,在表尾增加一个关键字为指定值K的记录,可避免每“比较”一次,就要判别查找是否结束。当n很大时,大约可节省一半的时间。,算法4-2 改进的顺序查找算法。#define MAXLEN n+1int seqsearch2(DATATYPE A,int k)int i;i=0;AMAXLEN1.key=k;,while(Ai.key!=k)i+;if(iMAXLE
6、N1)return i;/*查找成功,返回被查元素在表中的相对位置*/elsereturn 1;/*查找失败,返回1*/,将AMAXLEN1称作监视哨,这个增加的记录起到了边界标识的作用。下面对改进后的算法进行一下性能分析,计算它的平均查找长度。对含有n个记录的表,查找成功时的平均查找长度为,ASL=,从顺序查找的过程看,Ci取决于所查元素在表中的位置,对于第一个记录只要比较一次,对第n个记录,需要比较n次,查找记录Ai时,比较i次。设每个记录的查找概率相等,则Pi=1/n。故此算法在等概率情况下查找成功的平均查找长度为,ASL=,4.1.2 折半查找 如果查找表中的记录按关键字有序,则可以采
7、用一种高效率的查找方法折半查找,也称二分查找。折半查找的基本思想是:对于有序表,查找时先取表中间位置的记录关键字和所给关键字进行比较,若相等,则查找成功;如果给定值比该记录关键字大,则在后半部分继续进行折半查找;否则在前半部分进行折半查找,直到找到或者查找范围为空而查不到为止。,折半查找的过程实际上是先确定待查元素所在的区域,然后逐步缩小区域,直到查找成功或失败为止。算法中需要用到三个变量,low表示区域下界,high表示上界,中间位置mid=(low+high)DIV 2。由于折半查找要求数据元素的组织方式应具有随机存取的特性,所以它只适用于以顺序存储结构组织的有序表。,算法4-3 折半查找
8、算法。#define MAXLEN nint binsearch(DATATYPE A,int k)int low,mid,high;low=0;high=MAXLEN1;while(low=high)mid=(low+high)/2;,if(k=Amid.key)return mid;/*查找成功,返回被查元素在表中的相对位置*/else if(kAmid.key)low=mid+1;elsehigh=mid1;return 1;/*查找失败,返回1*/,折半查找成功的平均查找长度为 ASLbslb(n+1)1(求解过程从略)折半查找的优点是比较次数少,查找速度快,但只能对有序表进行查找。它
9、适用于一经建立就很少变动而又经常需进行查找的有序表。,例4-1 一有序表的关键字序列为(5,12,18,20,35,50,64,72,80,88,95),表长为11,采用折半查找求其在等概率情况下查找成功时的平均查找长度。解:按照折半查找算法,对序列中11个元素的查找过程如下:(1)mid=(1+11)DIV 2 查到第6个元素50,比较1次;(2)mid=(1+5)DIV 2 查到第3个元素18,比较2次;,或mid=(7+11)DIV 2 查到第9个元素80,比较2次;(3)依次类推,查到第1、4、7和第10个元素需比较3次;查到第2、5、8和第11个元素需比较4次。,这个查找过程可用图4
10、-1(a)的二叉树表示。若树中每个结点表示一个记录,结点中的值为该记录在表中的位置,通常这个描述查找过程的二叉树为判定树,如图4-1(b)所示。从判定树上看,查找20的过程恰好是走了一条从根到结点4的路径,比较次数为该路径上的结点数,或结点4在判定树上的层次数。因此,折半查找在查找成功时进行比较的次数最多不超过树的深度。,图4-1 描述折半查找过程的二叉树及判定树(a)描述折半查找的二叉树;(b)描述折半查找的判定树,从判定树上可知 ASLsucc=(1+2+2+3+3+3+3+4+4+4+4)=3 从该例可看出,折半查找成功的平均查找长度与序列中的具体元素无关,只取决于序列中元素的数目。,4
11、.1.3 分块查找 分块查找又称索引顺序查找,这是顺序查找的另一种改进方法。前面介绍的顺序查找速度慢;而折半查找虽速度快,但为换取快速查找所付出的代价是要将线性表按关键字排序,而且表必须采取顺序存储。在顺序结构里执行插入、删除操作都很困难。如果要处理的线性表既希望较快的检索又需要存储结构灵活,可以采用分块查找。分块查找是顺序查找和折半查找的折衷方案,特别适用于索引存储结构。,分块查找的特点是按照表内记录的某种属性把表分成n(n1)个块(子表),每一块中记录的存放是任意的,但是块与块之间是有序的,即所谓“分块有序”。假如按关键字递增顺序进行分块排列,就是指第j块的所有记录的关键字均大于第j1块的
12、所有记录的关键字(j=2,3,n),并建立一个索引表。把每块中的最大关键字值及每块的第一个记录在表中的位置存放在索引项中。整个查找过程分两步进行:(1)确定待查记录所在的块。(2)在块内查找。,例4-2 设给定值K=32,在图4-2所示的索引顺序表中查找关键字等于K的记录。,图4-2 表及其索引表,解:在图4-2的表中有18个记录,分成了三个子表(R1,R2,R6),(R7,R8,R12),(R13,R14,R18)。先将K依次和索引表中各最大关键字进行比较,因为25K45,则关键字为32的记录若存在,必定在第二个子表(块)中。然后从第二块的第一个记录,即表中的第7个记录起进行顺序查找,直到r
13、12.key=K为止。假如此块中没有关键字等于K的记录,则查找不成功。由于索引项的组成按关键字有序,则确定块的查找可以用顺序查找,亦可以用折半查找。而块中记录是任意排列的,则在块中只能是顺序查找。,分块查找的优点是在表中插入或删除一个元素时,只要找到该元素所属的块,然后在块内进行插入和删除。因为块内元素的存放是任意的,所以插入和删除时不需移动大量元素。所付出的代价是增加了存放索引表的辅助空间。分块查找也是常用的一种查找方法。,4.2 二叉排序树的查找,前一节我们介绍了三种基本的查找方法:顺序查找、折半查找和分块查找。其中折半查找的效率最高,但折半查找要求查找表中的数据元素按关键字有序,且不能用
14、链表作存储结构。当对查找表中的数据元素进行插入和删除操作时,为了保持查找表的有序性,势必要移动很多记录,造成新的时间开销。当插入和删除频繁进行时,这种额外开销就会抵消折半查找的优点。,若我们对查找表只作查找运算,则称该表为静态查找表。若对查找表既允许进行查找运算,又允许进行插入和删除运算,则称该表为动态查找表。前一节介绍的查找方法主要适用于静态查找表的查找,所以可称其为静态查找算法。对于动态查找表,为了能在其上方便地进行插入和删除操作,应寻求相应的动态查找算法。动态查找算法又常称为符号表算法,因为编译程序、汇编程序和其它系统子程序都广泛使用这种算法去监视和记录用户所定义的符号。为满足这种要求,
15、需采用树表,包括二叉排序树、二叉平衡树、B树、B+树、键树,这里我们只介绍二叉排序树的查找。,1二叉排序树的查找 二叉排序树(binary sort tree)或者是一棵空树;或者是具有下列性质的二叉树。(1)若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;(2)若它的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;(3)它的左、右子树也分别为二叉排序树。图4-3所示为两棵二叉排序树。,对二叉排序树进行中序遍历,可得到一个有序序列。故用这种方式存储表,可以把顺序表中折半查找速度快的优点与链式结构中插入、删除方便的优点结合起来,使查找表既具有顺序表那样高的检索效率,又
16、具有链表那样插入、删除运算的灵活性。,图4-3 二叉排序树示例,二叉排序树查找的思想是:(1)当二叉排序树不空时,首先将给定值K与根结点的关键字进行比较,若相等则查找成功;(2)若给定值K小于根结点的值,则继续在根的左子树中查找;若给定值K大于根结点的值,则继续在根的右子树中查找。显然这是一个递归查找过程。其查找算法见算法4-4。,算法4-4 二叉排序树的查找。struct treenodeint key;int otherterm;struct treenode*lchild,*rchild;typedef struct treenode TREENODE;TREENODE*bstsearc
17、h(TREENODE*root,int k),if(root=NULL)return NULL;else if(root-key=k)return root;/*查找成功*/else if(root-keyk)return bstsearch(root-lchild,k);/*查找左子树*/elsereturn bstsearch(root-rchild,k);/*查找右子树*/,由于此递归算法的递归调用属于末尾递归(即递归调用语句是函数中最后一条可执行语句)的调用,每次递归调用后返回给函数的各值也是重复的,同时每次递归调用后返回的退栈信息也是没有用的,所以为了减少花费在进出栈上无效的时间和空
18、间,可编写出相应的非递归算法,见算法4-5。,算法4-5 二叉排序树的查找。struct treenodeint key;int otherterm;struct treenode*lchild,*rchild;typedef struct treenode TREENODE;TREENODE*bstsearch(TREENODE*root,int k)TREENODE*p;p=root;,while(p!=NULL)if(p-key=k)return p;/*查找成功,返回非空指针*/else if(p-keyk)p=p-lchild;elsep=p-rchild;return p;/*查找
19、失败,返回空指针*/,2二叉排序树的生成 对一组数据序列K1,K2,Kn,先设一棵空二叉树,然后依次将序列中的元素生成结点后逐个插入到已生成的二叉排序树中。步骤如下:(1)K1是二叉排序树的根;(2)若K2K1,则K2所在的结点应插入到K1的左子树上;否则插入到K1的右子树上;,(3)读Ki,若Ki K1(根),则插入到根的左子树上,否则Ki插入到根的右子树上;(4)若in,则继续执行步骤(3),否则结束。设有一组关键字序列为(48,24,53,20,35,90),这一组数据按二叉排序树组织时,其二叉排序树的构造过程如图4-4所示。从图4-4中可看出,二叉排序树的生成过程就是在二叉排序树上插入
20、结点的过程。设有n个数据元素序列存放在一维数组An中,二叉排序树采用二叉链表存储结构,根结点指针为bst,生成二叉排序树的算法如算法4-6所示。,图4-4 二叉排序树的构造过程,算法4-6 二叉排序树的生成算法。#define N n/*n为二叉排序树中结点个数的最大可能值*/struct tnode int data;struct tnode*lchild,*rchild;typedef struct tnode TNODE;int An;TNODE*create_binary_sort_tree(),int i;TNODE*head,*s,*p,*q;head=NULL;for(i=0;i
21、data=Ai;s-lchild=NULL;s-rchild=NULL;if(head=NULL),head=s;elsep=head;while(p!=NULL)q=p;if(s-datadata)p=p-lchild;elsep=p-rchild;,if(s-datadata)q-lchild=s;elseq-rchild=s;return head;,从二叉排序树的建立过程可以看出,一个无序序列通过构造一棵二叉排序树而变成一从二叉排序树的建立过程可以看出,一个无序序列通过构造一棵二叉排序树而变成一个有序序列(中序遍历二叉排序树可得一个关键字的有序序列),构造二叉树的过程即为对无序序列进行
22、排序的过程。而且从插入过程还可以看到,每次插入的新结点都是二叉排序树上新的叶子结点,则在进行插入操作时,不必移动其它结点,仅需改动指针。,3二叉排序树的查找分析 例4-3 对图4-4(g)所示的二叉排序树进行查找,如要查找的关键字K=35,则K先与根结点比较,因3548,查找左子树;因3524,故在根的左子树的右子树上查找;因以结点24为根的右子树的根正好为35,故查找成功。,由上例可以看出,在二叉排序树中查找成功时走了一条从根结点到所查结点的路径。因此二叉排序树的平均查找长度取决于二叉排序树的深度。这与折半查找类似,与给定值比较的关键字个数不超过树的深度。然而,折半查找长度为n的表的判定树是
23、惟一的,而含有n个结点的二叉排序树却不惟一。所以,二叉排序树查找成功的平均查找长度取决于二叉排序树的形状,而二叉排序树的形状既与结点数目有关,更取决于建立二叉排序树时结点的插入顺序。,例4-4 已知长度为6的线性表是(45,24,53,13,30,85),若按表中元素的顺序依次插入,得到二叉排序树如图4-5(a)所示;若依次序13,24,30,45,53,85插入,得到二叉排序树为图4-5(b)所示,试分别求出在等概率情况下二叉排序树查找成功的平均查找长度。解:因是6个记录等概率查找,所以Pi=。则(a)树的平均查找长度为 ASL(a)=1+2+2+3+3+3=则(b)树的平均查找长度为 AS
24、L(b)=1+2+3+4+5+6=,二叉排序树查找的平均比较次数取决于二叉树的深度。在最好情况下,所生成的二叉排序树中,任一结点的左、右子树的深度相差都不超过1,即二叉排序树是一棵平衡二叉树时,二叉排序树查找的平均比较次数与折半查找相同,其查找效率最高。而在最坏情况下,即当二叉排序树蜕化为单支树时,其平均比较次数就和顺序查找相同了。,图4-5 例4-4构造的二叉排序树(a)二叉排序树;(b)单支树,4.3 哈 希 查 找,无论是顺序查找、折半查找、分块查找,还是二叉排序树查找,都需进行一系列和关键字的比较才能确定被查元素在查找表中的位置,查找的效率依赖于查找过程中所进行的比较次数。而哈希查找的
25、思想与前面四种方法完全不同,哈希查找方法是利用关键字进行某种运算后直接确定元素的存储位置,所以哈希查找方法是用关键字进行计算元素存储位置的查找方法。,在讨论哈希查找之前,先讨论适用于哈希查找的查找表的组织方式哈希表。在一块连续的内存空间采用哈希法建立起来的符号表就称为哈希表。,4.3.1 哈希表的建立 哈希表的建立:以线性表中的每个元素的关键字K为自变量,通过一种函数H(K)计算出函数值,然后将该元素存入H(K)所指定的相应的存储单元。查找时,只要根据要查找的关键字用同样的函数计算出地址H(K),然后直接到相应的单元中去取所要找的元素。称函数H(K)为哈希(Hash)函数,按这个思想建立的表为
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机软件 基础 彩霞 查找 排序
链接地址:https://www.31ppt.com/p-6606885.html