中南大学数据结构与算法第9章查找课后作业答案.docx

上传人:b****6 文档编号:5077552 上传时间:2022-12-13 格式:DOCX 页数:15 大小:59.94KB
下载 相关 举报
中南大学数据结构与算法第9章查找课后作业答案.docx_第1页
第1页 / 共15页
中南大学数据结构与算法第9章查找课后作业答案.docx_第2页
第2页 / 共15页
中南大学数据结构与算法第9章查找课后作业答案.docx_第3页
第3页 / 共15页
中南大学数据结构与算法第9章查找课后作业答案.docx_第4页
第4页 / 共15页
中南大学数据结构与算法第9章查找课后作业答案.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

中南大学数据结构与算法第9章查找课后作业答案.docx

《中南大学数据结构与算法第9章查找课后作业答案.docx》由会员分享,可在线阅读,更多相关《中南大学数据结构与算法第9章查找课后作业答案.docx(15页珍藏版)》请在冰豆网上搜索。

中南大学数据结构与算法第9章查找课后作业答案.docx

中南大学数据结构与算法第9章查找课后作业答案

第9章查找习题练习答案

1.对含有n个互不相同元素的集合,同时找最大元和最小元至少需进行多少次比较?

 

答:

  设变量max和min用于存放最大元和最小元(的位置),第一次取两个元素进行比较,大的放入max,小的放入min。

从第2次开始,每次取一个元素先和max比较,如果大于max则以它替换max,并结束本次比较;若小于max则再与min相比较,在最好的情况下,一路比较下去都不用和min相比较,所以这种情况下,至少要进行n-1次比较就能找到最大元和最小元。

2.若对具有n个元素的有序的顺序表和无序的顺序表分别进行顺序查找,试在下述两种情况下分别讨论两者在等概率时的平均查找长度:

 

(1)查找不成功,即表中无关键字等于给定值K的记录;

 

(2)查找成功,即表中有关键字等于给定值K的记录。

答:

  查找不成功时,需进行n+1次比较才能确定查找失败。

因此平均查找长度为n+1,这时有序表和无序表是一样的。

  查找成功时,平均查找长度为(n+1)/2,有序表和无序表也是一样的。

因为顺序查找与表的初始序列状态无关。

3.画出对长度为18的有序的顺序表进行二分查找的判定树,并指出在等概率时查找成功的平均查找长度,以及查找失败时所需的最多的关键字比较次数。

答:

      

  等概率情况下,查找成功的平均查找长度为:

    ASL=(1+2*2+3*4+4*8+5*3)/18=3.556 

  查找失败时,最多的关键字比较次树不超过判定树的深度,此处为5.

4.为什么有序的单链表不能进行折半查找?

答:

  因为链表无法进行随机访问,如果要访问链表的中间结点,就必须先从头结点开始进行依次访问,这就要浪费很多时间,还不如进行顺序查找,而且,用链存储结构将无法判定二分的过程是否结束,因此无法用链表实现二分查找。

5.设有序表为(a,b,c,e,f,g,i,j,k,p,q),请分别画出对给定值b,g和n进行折半查找的过程。

解:

 

 

(1)查找b的过程如下(其中方括号表示当前查找区间,圆括号表示当前比较的关键字)

      下标:

 1 2 3 4 5 6  7  8 910111213 

   第一次比较:

[a b c d e f (g) h i j k p q]

   第二次比较:

[a b(c)d e f] g  h i j k p q

   第三次比较:

[a(b)]c d e f  g  h i j k p q

   经过三次比较,查找成功。

 

(2)g的查找过程如下:

    [abcdef(g)hijkpq]

    一次比较成功。

 (3)n的查找过程如下:

       下标:

 1 2 3 4 5 6 7  8 9101112 13 

    第一次比较:

[a b c d e f(g) h i j k p q]

  第二次比较:

 a b c d e f g [h i(j)k p q]

  第三次比较:

 a b c d e f g  h i j[k(p)q]

  第四次比较:

 a b c d e f g  h i j[k]p q]

  经过四次比较,查找失败。

6.将(for,case,while,class,protected,virtual,public,private,do,template,const,if,int)中的关键字依次插入初态为空的二叉排序树中,请画出所得到的树T。

然后画出删去for之后的二叉排序树T',若再将for插入T'中得到的二叉排序树T''是否与T相同?

最后给出T"的先序、中序和后序序列。

答:

  二叉排序树T如下图:

         

 

  删去for后的二叉排序树如下图:

  

  再插入结点for后的二叉排序树T":

    

          

 二叉排序树T"与T不同

   T"的先序序列是:

docaseclassconstwhileprotectedprivateifforintvirtualpublictemplate 

  T"的中序序列是:

caseclassconstdoforifintprivateprotectedpublictemplatevirtualwhile

  T"的后序序列是:

constclasscaseforintifprivatetemplatepublicvirtualprotectedwhiledo

7.对给定的关键字集合,以不同的次序插入初始为空的树中,是否有可能得到同一棵二叉排序树?

答:

   有可能。

如有两个序列:

3,1,2,4和3,4,1,2,它们插入空树所得的二叉排序树是相同的。

8.将二叉排序树T的先序序列中的关键字依次插入一空树中,所得和二叉排序树T'与T否相同?

为什么?

答:

   这两棵二叉树完全相同。

9.设二叉排序树中关键字由1至1000的整数构成,现要查找关键字为363的结点,下述关键字序列哪一个不可能是在二叉排序树上查找到的序列?

 (a)2,252,401,398,330,344,397,363;

 (b)924,220,911,244,898,258,362,363;

 (c)925,202,911,240,912,245,363;

 (d)2,399,387,219,266,382,381,278,363.

答:

  (c)是不可能查找到的序列。

把这四个序列各插入到一个初始为空的二叉排序树中,结果可以发现,(c)序列所形成的不是一条路径,而是有分支的,可见它是不可能在查找过程中访问到的序列。

10.设二叉排序树中关键字互不相同,则其中最小元必无左孩子,最大元必无右孩子。

此命题是否正确?

最小元和最大元一定是叶子吗?

一个新结点总是插在二叉排序树的某叶子上吗?

 

答:

  此命题正确。

假设最小元有左孩子,则根据二叉排序树性质,此左孩子应比最小元更小,如此一来就产生矛盾了,因此最小元不可能有左孩子,对于最大元也是这个道理。

  但最大元和最小元不一定是叶子,它也可以是根、内部结点(分支结点)等,这得根据插入结点时的次序而定。

  新结点总是作为叶子插入在二叉排序树中的。

11.在一棵m阶的B-树中,当将一关键字插入某结点而引起该结点的分裂时,此结点原有多少个关键字?

若删去某结点中的一个关键字,而导致结点合并时,该结点中原有几个关键字?

答:

  在一棵m阶的B-树中,若由于一关键字的插入某结点而引起该结点的分裂时,则该结点原有m-1个关键字。

  若删去某结点中一个关键字而导致结点合并时,该结点中原有┌m/2┐-1个关键字。

12.在一棵B-树中,空指针数总是比关键字数多一个,此说法是否正确?

请问包含8个关键字的3阶B-树(即2-3树)最多有几个结点?

最少有几个结点?

画出这两种情况的B-树。

 

答:

  这个说法是正确的。

包含8个关键字的3阶B-树最多有7个结点,最少有4个结点。

      

13.从空树开始,依次输入20,30,50,52,60,68,70,画出建立2-3树的过程。

并画出删除50和68后的B-树状态。

 

答:

过程如下:

 

(1)插入20,30:

   

 

(2)插入50:

   

 (3)插入52:

   

 (4)插入60:

   

 (5)插入68:

   

 (6)插入70:

   

 (7)删去50:

   

 (8)删去68

   

14.画出依次插入z,v,o,p,w,y到图9.12(h)所示的5阶B-树的过程。

  

解:

 

(1)插入z后:

 

(2)插入v,o后

  

 (3)插入 p,w,y后

  

16.为什么在内存中使用的B-树通常是3阶的,而不使用更高阶的B-树?

答:

   因为查找等操作的cpu时间在B-树上是O(lgn·(m/lgt)),而m/lgt>1,所以m较大时它所费时间比平衡的二叉排序树上相应操作时间大得多,因此,仅在内存中使用的B-树通常取最小值3

17.为什么二叉排序树长高时,新结点总是一个叶子,而B-树长高时,新结点总是根?

哪一种长高能保证树平衡?

 

答:

   因为在二叉排序树中,关键字总是作为一个叶子结点插入以原来的树中,所以当树增高时,新结点总是一个叶子;而B-树中关键字插入总是插入到叶子结点内部,在叶结点中的关键字数目尚未超过它能够容纳的数目之前是不会增加结点的,当关键字数超过结点可容纳的数目时,叶结点就会发生分裂,产生一个新结点(但不一定引起树增高),并且将其中的中间结点传至上一层,只有当这种分裂操作传递至根结点并引起根结点的分裂时,才能引起树高增加,此时产生一个新的根结点。

所以说B树长高时,新结点总是根。

   显然,后一种长高总能保证树的平衡。

19.对于一组给定的、固定不变的关键字序列,有可能设计出无冲突的散列函数H,此时称H为完备的散列函数(perfecthashingfunction),若H能无冲突地将关键字完全填满散列表,则称H是最小完备(minimalperfect)的散列函数。

通常找完备的散列函数非常困难,找最小完备的散列函数就更困难。

请问:

 

(1)若h是已知关键字集合K的完备的散列函数,若要增加一个新的关键字到集合K,一般情况下H还是完备的吗?

 

(2)已知关键字集合为(81,129,301,38,434,216,412,487,234),散列函数为H(x)=(x+18)/63,请问H是完备的吗?

它是最小完备的吗?

 (3)考虑由字符串构成的关键字集合(Bret,Jane,Shirley,Bryce,Michelle,Heather),试为散列表[0..6]设计一个完备的散列函数。

(提示:

考虑每个字符串的第3个字符,即s[2])

答:

 

(1)一般情况下H不是完备的,如果说插入一个新的关键字它还是完备的,那么再插入一个呢?

它岂不是永远是完备的散列函数了?

所以一般情况下它不能总是完备的,只有一些很少的情况下它还可能是完备的。

 

(2)这个H是完备的,其函数值依次为:

1,2,5,0,7,3,6,8,4。

如果散列表长m=9时,它就是最小完备的。

 (3)这个函数如下:

   intHash(charkey[])

     {returnkey[2]%7;}

20.设散列函数为h(key)=key%101,解决冲突的方法为线性探查,表中用"-1"表示空单元。

若删去散列表HT中的304(即令HT[1]=-1)之后,在表HT中查找707将会发生什么?

若将删去的表项标记为"-2",查找时探查到-2继续向前搜索,探查到-1时终止搜索。

请问用这种方法删304后能否正确地查找到707?

   0  1  2  3            100 

  ┌──┬──┬──┬──┬───────────┬─┐

 HT│202│304│507│707│   ......     │ │ 

  └──┴──┴──┴──┴───────────┴─┘ 

答:

   查找707时,首先根据散列函数计算得出该元素应在散列表中的0单元,但是在0单元没有找到,因此将向下一单元探查,结果发现该单元是-1(为空单元),所以结束查找,这将导致707无法找到。

   如果改用"-2"作为删除标记,则可以正确找到707所在的结点。

21.设散列表长度为11,散列函数h(x)=x%11,给定的关键字序列为:

1,13,13,34,38,33,27,22.试画出分别用拉链法和线性探查法解决冲突时所构造的散列表,并求出在等概率情况下,这两种方法查找成功和失败时的平均查找长度。

请问装填因子的值是什么?

 

答:

 

(1)拉链法如下图:

 T[0..10]

   ┌──┐

  0│   │→33→22→∧

   ├──┤

  1│   │→1→12→34→∧

   ├──┤

  2│   │→13→∧

   ├──┤

  3│∧│

   ├──┤

  4│∧│

   ├──┤

  5│   │→38→27→∧

  ├──┤

 6│∧│

   ├──┤

  7│∧│

   ├──┤

  8│∧│

   ├──┤

  9│∧│ 

   ├──┤

 10│∧│

   └──┘

 

(2)线性探查法如下图:

     下标  0  1  2  3  4  5  6  7  8  9 10 

         ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐

 T[0..10]│33│1│13│12│34│38│27│22│ │ │ │

         └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

 探查次数  1  1  1  3  4  1  7  8

 用拉链法的查找成功平均查找长度为:

   ASLsucc=(1*4+2*3+3*1)/8=1.625

 查找失败时平均查找长度为:

   ASLunsucc=(2+3+1+0+0+0+2+0+0+0+0)/11=0.73

 用线性探查法查找成功时平均查找长度为:

   ASLsucc=(1+1+1+3+4+1+7+8)/8=3.25

 查找失败时平均查找长度为:

   ASLunsucc=(9+8+7+6+5+4+3+2+1+1+1)/11=4.3

 装填因子α拉链=4/11=0.36α线性探查=8/11=0.73

22.假定有k个关键字互为同义词,若用线性探查法把这些同义词存入散列表中,至少要进行多少次探查?

答:

   至少要进行1+2+3...+k-1+k次探查。

   也就是说,在散列表的一连串连续空间内,第一个关键字只需探查一次,第二个就要探查2次,如此这般,第k个关键字就要探查k次才能找到位置存放。

所以至少要把它们全加起来才够。

23.为什么说当装填因子非常接近1时,线性探查类似于顺序查找?

为什么说当装填因子比较小(比如α=0.7左右)时,散列查找的平均查找时间为O

(1)?

答:

   当α非常接近1时,整个散列表几乎被装满。

由于线性探查法在关键字同义时解决冲突的办法是线性地向后查找,当整个表几乎装满时,它就很类似于顺序查找了。

   当α比较小时,关键字碰撞的几率比较小,一般情况下只要按照散列函数计算出的结果能够1次性就找到相应结点,因此它的平均查找时间接近于1.

24.设顺序表中关键字是递增有序的,试写一顺序查找算法,将哨兵设在表的高下标端。

然后求出等概率情况下查找成功与失败时的ASL.

答:

 typedefstruct{

   KeyTypekey;

   InfoTypeotherinfo;//此类型依赖于应用

  }NodeType;

 typedefNodeTypeSeqList[n+1];//n号单元用作哨兵

 intSeqSearch(SeqlistR,KeyTypeK)

   {//在关键字递增有序的顺序表R[0..n-1]中顺序查找关键字为K的结点,

    //成功时返回找到的结点位置,失败时返回-1

    inti;

    R[n].key=K;//设置哨兵

    for(i=0;R[i].key<=K;i--);//从表前往后找

    if(i

    elsereturn-1 

   }//SeqSearch

  等概率情况下查找成功ASL=(1+2+3+…+n)/n

  等概率情况下查找失败时的ASL=(1+2+3+…+n+n+1)/(n+1)

25试写出二分查找的递归算法。

解:

 intBinSearch(SeqListR,KeyTypeK,intlow,inthigh)

  {//在有序表R[low..high]中进行二分查找,成功时返回结点的位置,失败时返回零

   intmid;//置当前查找区间上、下界的初值

   if(low<=high){//当前查找区间R[low..high]非空

     mid=(low+high)/2;

     if(R[mid].key==K)returnmid;//查找成功返回

     if(R[mid].kdy>K)

       returnBinSearch(R,K,low,mid-1)//在R[low..mid-1]中查找

     else

       returnBinSearch(R,K,mid+1,high);//在R[mid+1..high]中查找

    }

   return0;//当low>high时表示查找区间为空,查找失败

  }//BinSeareh

26试写一算法判别给定的二叉树是否为二叉排序树,设此二叉树以二叉链表为存储结构,且树中结点的关键字均不相同。

解:

  由二叉排序树的定义可得:

二叉排序树中左子树的所有结点的值都小于根结点的值,所有右子树中结点的值都大于根结点的值。

那么只要对待判定的二叉树中的结点按层遍历并判断即可。

在该算法中要用到队列保存已遍历的结点指针。

 typedefBinTNode*DataType;//循环队列中元素为二叉树结点指针 

 intBinSortStree(BinTreeT)

  { 

   CirQueueQ;

   BinTNode*p;

   if(!

T)return1;//空树为二叉排序树

   InitQueue(&Q);

   EnQueue(&Q,T);

   while(!

QueueEmpty(&Q))

    {

     p=DeQueue(&Q);

     if(p->lchild)

      if(p->datalchild->data)return-1;//不是二叉排序树

      elseEnQueue(&Q,p->lchild);

     if(p->rchild)

      if(p->data>p->rchild->data)return-1;//不是二叉排序树

      elseEnQueue(&Q,p->rchild);

    }

   return1;//是二叉排序树 

  }

27.试写一递归算法,从大到小输出二叉排序树中所有其值不小于x的关键字。

要求算法的时间为O(lgn+m),n为树中结点数,m为输出关键字个数(提示:

先遍历右子树,后遍历左子树)。

答:

 typedefintKeyType;//假定关键字类型为整数

 typedefstructnode{//结点类型

   KeyTypekey;//关键字项

   InfoTypeotherinfo;//其它数据域,InfoType视应用情况而定,下面不处理它

   structnode*lchild,*rchild;//左右孩子指针

  }BSTNode;

 typedefBSTNode*BSTree;

 voidOUTPUTNODE(BSTreeT,KeyTypex)

  {//从大到小输出二叉排序树中所有其值不小于x的关键字

   if(T)

    {

     OUTPUTNODE(T->rchild,x);

     if(T->key>=x)printf("%d",T->key);

     OUTPUTNODE(T->Lchild,x);

    }

  }

28.写一个遍历B-树的算法,使输出的关键字序列递增有序。

算法中的读盘操作可假定为DiskRead。

答:

 #defineMaxl000//结点中关键字的最大数目:

Max=m-1,m是B-树的阶

 #defineMin500//非根结点中关键字的最小数目:

Min=「m/2(-1

 typedefintKeyType;//KeyType应由用户定义

 typedefstructnode{//结点定义中省略了指向关键字代表的记录的指针

   intkeynum;//结点中当前拥有的关键字的个数,keynum<=Max

   KeyTypekey[Max+1];//关键字向量为key[1..keynum],key[0]不用。

   structnode*parent;//指向双亲结点

   structnode*son[Max+1];//孩子指针向量为son[0..keynum]

  }BTreeNode;

 typedefBTreeNode*BTree;

 voidtravelBtree(BTreeT){

  //按关键字递增序输出B-树序列

  inti;

  if(T){

    for(i=0;i<=T->keynum;i++)//T->keynum个关键字的结点有T->keynum+1棵子树

     {

       if(T->son[i]){

         DiskRead(T->son[i]);//读入根结点的第i棵子树

         travelBtree(T->son[i]);//遍历第i棵子树

        }

       if(ikeynmu)//若刚遍历的子树不是最后一棵子树

         printf("%d",T->key[i+1]; 

     }

  }

29若采用除余法作为散列函数,线性探查解决冲突,则9.4.4节中通用的散列表查找算法可改写为对线性探查专用的查找算法:

 intHashSearch(HashTableT,KeyTypeK,int*pos){

  inti=0;//记录探查次数

  *pos=K%m;//散列函数值作为第一个散列地址

  while(i++

   {

    if(T[*pos].key==K)return1;//查找成功返回

    if(T[*pos].key==NIL)return0;//查找失败返回

    *pos=(*pos+1)%m;//用线性探查法求下一个探查地址

   }

  return-1;//查找失败,且表满

 }//HashSearch

  假设散列表上的删除操作已将结点的关键字标记为DELETED(例如,不妨设DELETED为-2)。

请修改上述散列表上的查找算法及插入算法HashInsert,使之能正确地查找和插

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1