第九章习题.docx

上传人:b****8 文档编号:30561092 上传时间:2023-08-16 格式:DOCX 页数:21 大小:56.78KB
下载 相关 举报
第九章习题.docx_第1页
第1页 / 共21页
第九章习题.docx_第2页
第2页 / 共21页
第九章习题.docx_第3页
第3页 / 共21页
第九章习题.docx_第4页
第4页 / 共21页
第九章习题.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

第九章习题.docx

《第九章习题.docx》由会员分享,可在线阅读,更多相关《第九章习题.docx(21页珍藏版)》请在冰豆网上搜索。

第九章习题.docx

第九章习题

第九章习题

9.1  以关键码序列(503,087,512,061,908,170,897,275,653,426)为例,手工执行以下排序算法,写出每一趟排序结束时的关键码状态:

(1)直接插入排序;          

(2)希尔排序(增量d[1]=5);

(3)快速排序;              (4)堆排序;

(5)归并排序;              (6)基数排序。

9.2  一组关键字码,40,27,28,12,15,50,7,采用快速排序或堆排序,写出每趟排序结果。

 

9.3  不难看出,对长度为n的记录序列进行快速排序时,所需进行的比较次数依赖于这n个元素的初始排列。

n=7时在最好情况下需进行多少次比较?

请说明理由。

对n=7给出一个最好情况的初始排列实例。

9.4假设序列由n个关键字不同的记录构成,要求不经排序而从中选出关键字从大到小顺序的前k(k

试问如何进行才能使所作的关键字间比较次数达到最小?

9.5  插入排序中找插入位置的操作可以通过二分查找的方法来实现。

试据此写一个改进后的插入排序算法。

9.6  编写一个双向起泡的排序算法,即相邻两遍向相反方向起泡。

9.7编写算法,对n个关键字取整数值的记录序列进行整理,以使所有关键字为负值的记录排在关键字为非负值的记录之前,要求:

采取顺序存储结构,至多使用一个记录的辅助存储空间;

算法的时间复杂度O(n);

讨论算法中记录的最大移动次数。

9.8试以单链表为存储结构实现简单选择排序的算法

9.9假设含n个记录的序列中,其所有关键字为值介于v和w之间的整数,且其中很多关键字的值是相同的。

则可按如下方法排序:

另设数组number[v...w]且令number[i]为统计关键字取整数I的记录数,之后按number重排序列以达到有序,编写算法实现上述排序方法,并讨论此方法的优缺点。

9.10已知两个有序序列(a1,a2,...,am)和(am+1,am+2,...,an),并且其中一个序列的记录个数少于s,且s=?

√n?

.    试写一个算法,用O(n)时间和O

(1)附加空间完成这两个有序序列的归并。

9.11偶交换排序如下所述:

第一趟对所有奇数i,将a[i]和a[i+1]进行比较;第二趟对所有偶数i,将a[i]和a[i+1]进行比较,若a[i]>a[i+1],则将两者交换;第一趟对所有奇数i,第二趟对所有偶数i,…,依次类推直至整个序列有序为止。

(1)这种排序方法的结束条件是什么?

(2)分析当初始序列为正序或逆序两种情况下,奇偶交换排序过程中所需进行的关键字比较的次数。

(3)写出奇偶交换排序的算法。

9.12设计一个用链表表示的直接选择排序算法。

9.13插入排序中找插入位置的操作可以通过二分查找的方法来实现。

试据此写一个改进后的插入排序算法。

9.14一个线性表中的元素为正整数或负整数。

设计一个算法,将正整数和负整数分开,使线性表的前一半为负整数,后一半为正整数。

不要求对元素排序,但要尽量减少交换次数。

9.15为什么通常使用一维数组作为堆的存放形式?

9.16已知(k1,k2,…,kn)是堆,写一个算法将(k1,k2,…,kn,kn+1)调整为堆。

按此思想写一个从空堆开始一个一个添入元素的建堆算法。

9.17试比较直接插入排序、简单选择排序、快速排序、堆排序、归并排序、希尔排序和基数排序的时空性能、稳定性和适用情况。

9.18 在供选择的答案中填入正确答案:

    

(1)、排序(分类)的方法有许多种:

__A__法从未排序序列中依次取出元素,与排序序列(初始为空)中的元素作比较,将其放入已排序列的正确位置上;__B__法从未排序序列中挑选元素,并将其依次放入已排序序(初始时为空)的一端;交换排序法是对序列中元素进行一系列的比较,当被比较的两元素逆序时进行交换。

__C___和__D__是基于这类方法的两种排序方法,而__D__是比__C__效率更高的方法,利用某种算法,根据元素的关键值计算出排序位置的方法是__E__。

供选择答案

①      选择排序 ② 快速排序 ③ 插入排序 ④ 冒泡排序

⑤      归并排序 ⑥ 二分排序 ⑦ 哈希排序 ⑧ 基数排序

(2)、一组记录的关键字为(46,79,56,38,40,84),利用快速排序的方法,以第一个记录为基准得到的一次划分结果为      。

A、38,40,46,56,79,84

B、40,38,46,79,56,84

C、40,38,46,56,79,84

D、40,38,46,84,56,79

(3)、下列排序算法中,      算法可能会出现下面情况:

初始数据有序时,花费时间反而最多。

A、堆排序    B、冒泡排序    C、快速排序     D、SHELL排序

9.19 判断正误:

()在一个大堆中,最小元素不一定在最后。

()对n个记录采用快速排序方法进行排序,最坏情况下所需时间是o(nlog2n)。

()在执行某排序算法过程中,出现了排序码朝着与最终排序序列相反方向移动的现象,则称该算法是不稳定的。

 

实习题

 

一、随机生成30个数,试比较直接插入排序、简单选择排序、起泡排序、快速排序、堆排序和希尔排序的时空性能和稳定性。

二、统计成绩。

给出n个学生的考试成绩表,每条信息由姓名与分数组成。

 

(1)按分数高低次序,打印出每个学生在考试中获得的名次,分数相同的为同一名次;

 

(2)按名次列出每个学生的姓名与分数。

9.1

(1)无序表:

顺序查找不成功时,查找长度为n+1;成功时,平均查找长度为1/(n+1)*(1+2+…+(n+1))=(n+2)/2;两者不相同。

(2)表中只有一个关键字等于给定值k的记录,无序表、有序表:

顺序查找成功时,平均查找长度均为1/(n)*(1+2+…+n)=(n+1)/2;两者相同。

(3)表中只有m个关键字等于给定值k的记录,无序表:

ASL=n+1;有序表:

ASL=(n+1)/2+m;两者不相同。

 

9.3

ASL=1/10(1+2*2+4*3+3*4)=2.9

 

9.11

 

 

9.14

 

删除50后

 

 

删除68后

 

9.19

22

67

41

30

 

53

46

 

13

 

01

0

1

2

3

4

5

6

7

8

9

10

 

ASL=(4*1+2*2+3+6)/8=17/8

 

9.25

intSearch-Seq(SSTableST,KeyTypekey){

//在顺序表ST中顺序查找其关键字等于key的数据元素,ST按关键字自大至小有序,

//若找到,则函数值为该元素在表中的位置,否则为0

ST.elem[ST.length+1].key=key;

for(i=1;ST.elem[i].key>key;++i);

if(ST.elem[i].key==key)&&(i<=ST.length)returni

elsereturn0;

}//Search-Seq

 

9.31

TelemTypeMaxv(BitreeT){

//返回二叉排序树T中所有结点的最大值

for(p=T;p->rchild;p=p->rchild);

returnp->data;

}//Maxv

 

TelemTypeMinv(BitreeT){

//返回二叉排序树T中所有结点的最小值

for(p=T;p->lchild;p=p->lchild);

returnp->data;

}//Minv

 

StatusIsBST(BitreeT){

//判别T是否为二叉排序树

if(!

T)returnOK;

elseif((!

T->lchild)||((T->lchild)&&(IsBST(T->lchild)&&(Maxv(T->lchild)data)))

&&((!

T->rchild)||((T->rchild)&&(IsBST(T->rchild)&&(Minv(T->rchild)>T->data)))

returnOK

elsereturnERROR;

}//IsBST

 

9.33

StatusOutputGEx(BitreeT,TelemTypex){

//从大到小输出给定二叉排序树T中所有值不小于x的数据元素

if(T){

if(OutputGEx(T->rchild,x))

if(T->data>=x){

print(T->data);

if(OutputGEx(T->lchild,x))returnOK;

}

elsereturnOK;

}

elsereturnOK;

}//OutputGEx

 

第九章查找

9.25

intSearch_Sq(SSTableST,intkey)//在有序表上顺序查找的算法,监视哨设在高下标端

{

  ST.elem[ST.length+1].key=key;

  for(i=1;ST.elem[i].key>key;i++);

  if(i>ST.length||ST.elem[i].key

  returni;

}//Search_Sq

分析:

本算法查找成功情况下的平均查找长度为ST.length/2,不成功情况下为ST.length.

9.26

intSearch_Bin_Digui(SSTableST,intkey,intlow,inthigh)//折半查找的递归算法

{

  if(low>high)return0;//查找不到时返回0

  mid=(low+high)/2;

  if(ST.elem[mid].key==key)returnmid;

  elseif(ST.elem[mid].key>key)

    returnSearch_Bin_Digui(ST,key,low,mid-1);

  elsereturnSearch_Bin_Digui(ST,key,mid+1,high);

  }

}//Search_Bin_Digui

9.27

intLocate_Bin(SSTableST,intkey)//折半查找,返回小于或等于待查元素的最后一个结点号

{

  int*r;

  r=ST.elem;

  if(key

  elseif(key>=r[ST.length].key)returnST.length;

  low=1;high=ST.length;

  while(low<=high)

  {

    mid=(low+high)/2;

    if(key>=r[mid].key&&key

      returnmid;

    elseif(key

    elselow=mid;

  }//本算法不存在查找失败的情况,不需要return0;

}//Locate_Bin

9.28

typedefstruct{

                intmaxkey;

                intfirstloc;

              }Index;

typedefstruct{

                int*elem;

                intlength;

                Indexidx[MAXBLOCK];//每块起始位置和最大元素,其中idx[0]不利用,其内容初始化为{0,0}以利于折半查找

                intblknum;//块的数目

              }IdxSqList;//索引顺序表类型

intSearch_IdxSeq(IdxSqListL,intkey)//分块查找,用折半查找法确定记录所在块,块内采用顺序查找法

{

  if(key>L.idx[L.blknum].maxkey)returnERROR;//超过最大元素

  low=1;high=L.blknum;

  found=0;

  while(low<=high&&!

found)//折半查找记录所在块号mid

  {

    mid=(low+high)/2;

    if(key<=L.idx[mid].maxkey&&key>L.idx[mid-1].maxkey)

      found=1;

    elseif(key>L.idx[mid].maxkey)

      low=mid+1;

    elsehigh=mid-1;

  }

  i=L.idx[mid].firstloc;//块的下界

  j=i+blksize-1;//块的上界

  temp=L.elem[i-1];//保存相邻元素

  L.elem[i-1]=key;//设置监视哨

  for(k=j;L.elem[k]!

=key;k--);//顺序查找

  L.elem[i-1]=temp;//恢复元素

  if(k

  returnk;

}//Search_IdxSeq

分析:

在块内进行顺序查找时,如果需要设置监视哨,则必须先保存相邻块的相邻元素,以免数据丢失.

9.29

typedefstruct{

                LNode*h;//h指向最小元素

                LNode*t;//t指向上次查找的结点

              }CSList;

LNode*Search_CSList(CSList&L,intkey)//在有序单循环链表存储结构上的查找算法,假定每次查找都成功

{

  if(L.t->data==key)returnL.t;

  elseif(L.t->data>key)

    for(p=L.h,i=1;p->data!

=key;p=p->next,i++);

  else

    for(p=L.t,i=L.tpos;p->data!

=key;p=p->next,i++);

  L.t=p;//更新t指针

  returnp;

}//Search_CSList

分析:

由于题目中假定每次查找都是成功的,所以本算法中没有关于查找失败的处理.由微积分可得,在等概率情况下,平均查找长度约为n/3.

9.30

typedefstruct{

                DLNode*pre;

                intdata;

                DLNode*next;

              }DLNode;

typedefstruct{

                DLNode*sp;

                intlength;

              }DSList;//供查找的双向循环链表类型

DLNode*Search_DSList(DSList&L,intkey)//在有序双向循环链表存储结构上的查找算法,假定每次查找都成功

{

  p=L.sp;

  if(p->data>key)

  {

    while(p->data>key)p=p->pre;

    L.sp=p;

  }

  elseif(p->data

  {

    while(p->datanext;

    L.sp=p;

  }

  returnp;

}//Search_DSList

分析:

本题的平均查找长度与上一题相同,也是n/3.

9.31

intlast=0,flag=1;

intIs_BSTree(BitreeT)//判断二叉树T是否二叉排序树,是则返回1,否则返回0

{

  if(T->lchild&&flag)Is_BSTree(T->lchild);

  if(T->data

  last=T->data;

  if(T->rchild&&flag)Is_BSTree(T->rchild);

  returnflag;

}//Is_BSTree

9.32

intlast=0;

voidMaxLT_MinGT(BiTreeT,intx)//找到二叉排序树T中小于x的最大元素和大于x的最小元素

{

  if(T->lchild)MaxLT_MinGT(T->lchild,x);//本算法仍是借助中序遍历来实现

  if(lastdata>=x)//找到了小于x的最大元素

    printf("a=%d\n",last);

  if(last<=x&&T->data>x)//找到了大于x的最小元素

    printf("b=%d\n",T->data);

  last=T->data;

  if(T->rchild)MaxLT_MinGT(T->rchild,x);

}//MaxLT_MinGT

9.33

voidPrint_NLT(BiTreeT,intx)//从大到小输出二叉排序树T中所有不小于x的元素

{

  if(T->rchild)Print_NLT(T->rchild,x);

  if(T->data

  printf("%d\n",T->data);

  if(T->lchild)Print_NLT(T->lchild,x);//先右后左的中序遍历

}//Print_NLT

9.34

voidDelete_NLT(BiTree&T,intx)//删除二叉排序树T中所有不小于x元素结点,并释放空间

{

  if(T->rchild)Delete_NLT(T->rchild,x);

  if(T->data

  q=T;

  T=T->lchild;

  free(q);//如果树根不小于x,则删除树根,并以左子树的根作为新的树根

  if(T)Delete_NLT(T,x);//继续在左子树中执行算法

}//Delete_NLT

9.35

voidPrint_Between(BiThrTreeT,inta,intb)//打印输出后继线索二叉排序树T中所有大于a且小于b的元素

{

  p=T;

  while(!

p->ltag)p=p->lchild;//找到最小元素

  while(p&&p->data

  {

    if(p->data>a)printf("%d\n",p->data);//输出符合条件的元素

    if(p->rtag)p=p->rtag;

    else

    {

      p=p->rchild;

      while(!

p->ltag)p=p->lchild;

    }//转到中序后继

  }//while

}//Print_Between

9.36

voidBSTree_Insert_Key(BiThrTree&T,intx)//在后继线索二叉排序树T中插入元素x

{

  if(T->data

  {

    if(T->rtag)//T没有右子树时,作为右孩子插入

    {

      p=T->rchild;

      q=(BiThrNode*)malloc(sizeof(BiThrNode));

      q->data=x;

      T->rchild=q;T->rtag=0;

      q->rtag=1;q->rchild=p;//修改原线索

    }

    elseBSTree_Insert_Key(T->rchild,x);//T有右子树时,插入右子树中

  }//if

  elseif(T->data>x)//插入到左子树中

  {

    if(!

T->lchild)//T没有左子树时,作为左孩子插入

    {

      q=(BiThrNode*)malloc(sizeof(BiThrNode));

      q->data=x;

      T->lchild=q;

      q->rtag=1;q->rchild=T;//修改自身的线索

    }

    elseBSTree_Insert_Key(T->lchild,x);//T有左子树时,插入左子树中

  }//if

}//BSTree_Insert_Key

9.37

StatusBSTree_Delete_key(BiThrTree&T,intx)//在后继线索二叉排序树T中删除元素x

{

  BTNode*pre,*ptr,*suc;//ptr为x所在结点,pre和suc分别指向ptr的前驱和后继

  p=T;last=NULL;//last始终指向当前结点p的前一个(前驱)

  while(!

p->ltag)p=p->lchild;//找到中序起始元素

  while(p)

  {

    if(p->data==x)//找到了元素x结点

    {

      pre=last;

      ptr=p;

    }

    elseif(last&&last->data==x)suc=p;//找到了x的后继

    if(p->rtag)p=p->rtag;

    else

    {

      p=p->rchild;

      while(!

p->ltag)p=p->lchild;

    }//转到中序后继

    last=p;

  }//while//借助中序遍历找到元素x及其前驱和后继结点

  if(!

ptr)returnERROR;//未找到待删结点

  Delete_BSTree(ptr);//删除x结点

  if(pre&&pre->rtag)

    pre->rchild=suc;//修改线索

  returnOK;

}//BSTree_Delete_key

voidDelete_BSTree(BiThrTree&T)//课本上给出的删除二叉排序树的子树T的算法,按照线索二叉树的结构作了一些改动

{

  q=T;

  if(!

T->ltag&&T->r

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

当前位置:首页 > 高中教育 > 数学

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

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