68.表长为n,每块大小取n时,平均查找长度取最小值n+1。若n=255,则每块长度为16。
69.表长2000,分成45块,每块的理想长度为45(最后一块长20)。若每块长25,则平均查找长度为ASL=(80+1)/2+(25+1)/2=53.5(顺序查找确定块),或ASL=19(折半查找确定块)。
70.将n个元素对称比较,即第一个元素与最后一个元素比较,第二个元素与倒数第二个元素比较,??,比较中的小者放前半部,大者放后半部,用了?n/2?次比较。再在前后两部分中分别简单选择最小和最大元素,各用?n/2?-1次比较。总共用了3*?n/2?-2次比较。 71.在有序表A[1..14]中,比较到A[4]时,已查找元素依次是A[7],A[3],A[5]。 72.(1)图中结点中的数字为元素在有序表中的下标
1/21/2
(2)插入排序中,用折半查找确定待插入元素位置,比直接插入排序减少了比较次数,但数据移动次数没有改变,排序的时间复杂度也未改变。
(3)折半查找的平均查找长度是((n+1)/n)log2(n+1)-1≈log(n+1)-1。本例ASL=79/21。 73.根据次优查找树的定义,首先取第i个记录(l≤i≤h)构造根结点,使
△Pj=|-| 取最小值。
关键字 black blue green purple red white yellow 权值 0.10 0.08 0.12 0.05 0.20 0.25 0.20 j 1 2 3 4 5 6 7 SWj 0.1 0.18 0.30 0.35 0.55 0.80 1.00 △Pj 0.9 0.72 0.52 0.35 0.10 0.35 0.80 (根) ↑i
△Pj 0.25 0.07 0.13 0.30 0.20 0.25 ↑i ↑i △Pj 0.05 0.12 ↑i
red blue black white green yellow white green black blue red yellow purple purple
73题(1)次优查找树 73题(2)调整后的次优查找树
查找成功的平均查找长度是=1*0.25+2*(0.12+0.20)+3*(0.1+0.08+0.20)+4*0.05=2.23
由于在构造次优查找树的过程中,没有考查单个关键字的相应权值,可能出现根的关键字的权值比之相邻的关键字的权值小,这时要作调整:选邻近的权值较大的关键字作次优查找树的根结点。调整后的次优查找树如图73(2)。 74.
75.这里失败结点是不存在的结点,在其双亲结点处查找失败,这时的比较次数为Li-1。
76.
(1) 顺序查找判定树
(2)ASL顺序成功 =(1p1 +2p2+3p3+4p4+5p5)=0.97 ASL折半成功 =(1p3+2(p1+p4)+3(p2+p5)=1.04 ASL折半失败 =(2q0+3q1+3q2+2q3+3q4+3q5)=1.30 ASL顺序失败 =(1q0+2q1+3q2+4q3+5q4+5q5)=1.07
(3)本题中顺序检索好。
77.时间复杂度是判断检索方法的一个重要指标,但不是唯一指标。使用什么检索方法要综合考虑。哈希检索时间O(1),查找速度最快,但需构建哈希函数,进行计算哈希地址,查找时要有解决冲突的方法;二分检索时间O(log2n),需要元素有序且顺序存储,排序操作的时间开销大;顺时检索时间最差为O(n),但对检索表无要求,数据有序无序均可,在数据量较小时使用方便。
五.算法设计题
1. 根据二叉排序树中序遍历所得结点值为增序的性质,在遍历中将当前遍历结点与其前驱
结点值比较,即可得出结论,为此设全局指针变量pre(初值为null)和全局变量flag,初值为true。若非二叉排序树,则置flag为false。 #define true 1 #define false 0
typedef struct node
{datatype data; struct node *llink,*rlink;} *BTree; void JudgeBST(BTree t,int flag)
// 判断二叉树是否是二叉排序树,本算法结束后,在调用程序中由flag得出结论。 { if(t!=null && flag)
{ Judgebst(t->llink,flag);// 中序遍历左子树
if(pre==null)pre=t;// 中序遍历的第一个结点不必判断
else if(pre->data
}//JudgeBST算法结束
本题的另一算法是照定义,二叉排序树的左右子树都是二叉排序树,根结点的值大于左子树中所有值而小于右子树中所有值,即根结点大于左子树的最大值而小于右子树的最小值。算法如下:
int JudgeBST(BTree t)
//判断二叉树t是否是二叉排序树,若是,返回true,否则,返回false {if(t==null)return true;
if(Judgebst(t->llink)&& Judgebst(t->rlink))//若左右子树均为二叉排序树
{m=max(t->llink);n=min(t->rlink);//左子树中最大值和右子树中最小值 return (t->data>m && t->data int max(BTree p)//求二叉树左子树的最大值 {if(p==null) return -maxint;//返回机器最小整数 else{while(p->rlink!=null)p=p->rlink; return p->data;} } int min(BTree p)//求二叉树右子树的最小值 {if(p==null) return maxint;//返回机器最大整数 else{while(p->llink!=null)p=p->llink; return p->data;} } 2.[题目分析]借助于分块查找思想,在建立数据顺序表的同时,建立一索引表。数据表中按k个集合分块(元素个数不一定相等),索引表中有两个域,一是各集合最后一个元素在数据表中的位置(一维数组中的下标),二是集合的个数(k)。实现数据运算时,根据给定的二元组(i,x),首先在索引表中找到集合i的位置,然后在数据表中查找x。如查到x ,则查找成功,返回x在数据表中的位置,否则查找失败。若要插入,则将数据表中的数据后移,插入x,同时修改索引表。 typedef struct {datatype data;}rectype; typedef struct {int a[];//a数组容量够大,存储各集合最后一个数据在数据表中的下标 int k; //集合个数 }index; int SetSearch_Insert(rectype R[],index id,datatype x,int i) //数据表R,查找第i个集合的元素x,若查找成功,返回其位置,否则将其插入第i个集合 {if(i<1 || i>id.k)printf(“无第%d个集合\\n”,i);exit(0);} if(i==1)first=0;else first=id.a[i-1]+1; //first指向第i个集合在数据表的首址 last= id.a[i];//last是第i个集合在数据表中的末址 for(j=first;j≤last;j++) if(R[j]==x)return (j);//查找成功 for(j=id.a[id.k];j>id.a[i];j--) //查找失败,将x插入数据表 R[j+1]=R[j];//元素后移 R[j+1]=x; //将x插入到原第i个集合最后一个元素之后。 for(j=i;j≤k;j++)id.a[j]++;//修改索引表中各集合最后一个元素的下标 }结束SetSearch_Insert 由于各集合元素个数不等,各块长度不等且块间无序,索引表中用数组表示,数组中元素值是各集合最后一个元素在数据表中的下标。按本算法插入(2,11.2)和(1,5.3),数据表前后状态如下: 插0 1 2 3 入10.前 2 插10.入2 后 1.7 1.7 4.8 4.8 16.2 16.2 4 1.7 5.3 5 8.4 1.7 6 0.5 8.4 7 4.8 0.5 8 9 10 11 2.7 4.2 5.1 3.6 12 3.9 2.7 13 14 5.1 3.9 4.2 3.6 11.2 4.8 插入前,索引表中a数组的内容是3,6,12,插入后修改为4,8,14。 3.(1)非递归建立二叉排序树,在二叉排序树上插入的结点都是叶子结点。 void Creat_BST(BiTree bst,datatype K[],int n) // 以存储在数组K中的n个关键字,建立一棵初始为空的二叉排序树。 {for(i=1;i≤n;i++) {p=bst;f=null;//在调用Creat_BST时,bst=null while(p!=null) if(p->data s=(BiTree)malloc(sizeof (BiNode));// 申请结点空间 s->data=K[i];s->LLINK=null;s->RLINK=null; if(f==null)bst=s; //根结点 else if(s->data else f->RLINK=s;//右子树根结点的值大于等于根结点的值 }//算法结束 (2)[题目分析]本题要求输出遍历二叉排序树的嵌套括号表示。其算法思想是,若二叉排序树非空,则输出根结点,再输出其左右子树。在输出其左右子树前,要输出左括号,在输出其右子树前要输出逗号,在输出其右子树后要输出右括号,在左右子树均空情况下,则不输出括号。 void Print(BiTree t) //以嵌套括号表示结构打印二叉排序树 {if(t!=null) {printf(t->data);//打印根结点值 if(t->LLINK || t->LLINK);//左子女和右子女中至少有一个不空 {printf(“(”); //输出左括号 Print(t->LLINK); //输出左子树的嵌套括号表示 if(t->RLINK)printf(“,”);//若右子树不空,输出逗号 Print(t->RLINK); //输出右子树的嵌套括号表示 printf(“)”); //输出右括号 }//if }}//Print 4. void Delete(BSTree t,p) // 在二叉排序树t中,删除f所指结点的右孩子(由p所指向)的算法 {if(p->lchild==null){f->rchild=p->rchild;free(p);} //p无左子女 else //用p左子树中的最大值代替p结点的值 {q=p->lchild;s=q; while(q->rchild){s=q;q=q->rchild ;}//查p左子树中序序列最右结点 if(s==p->lchild) //p左子树的根结点无右子女 {p->data=s->data;p->lchild=s->lchild;free(s);} else{p->data=q->data;s->rchild=q->lchild;free(q);} } }//Delete 5.[题目分析]上题用被删结点左子树中最大值结点代替被删结点,本题用被删结点右子树中最小值(中序遍历第一个)结点代替被删结点。 void Delete(BSTree bst,p,fp) //在二叉排序树bst上,删除fp所指结点的左子女(由p所指向)的算法。 {if(!p->lchild){fp->lchild=p->rchild;free(p);} //p无左子女 else if(!p->rchild){fp->lchild=p->lchild;free(p);} //p无右子女 else // p有左子女和右子女 {q=p->rchild;s=q;//用p右子树中的最小值代替p结点的值 while(q->lchild){s=q;q=q->lchild ;}//查p右子树中序序列最左结点 if(s==p->rchild) //p右子树的根结点无左子女 {p->data=s->data;p->rchild=s->rchild;free(s);} else{p->data=q->data;s->lchild=q->rchild;free(q);} }//Delete 6.[题目分析] 在二叉排序树上删除结点,首先要查找该结点。查找成功后,若该结点无左子树,则可直接将其右子树的根结点接到其双亲结点上;若该结点有左子树,则将其左子树中按中序遍历的最后一个结点代替该结点,从而不增加树的高度。 void Delete(BSTree bst, keytype X) //在二叉排序树bst上,删除其关键字为X的结点。 {BSTree f,p=bst; while (p && p->key!=X) //查找值为X的结点 if (p->key>X) {f=p; p=p->lchild;} else {f=p; p=p->rchild;} if (p==null) {printf(“无关键字为X的结点\\n”); exit(0);} if {p->lchild==null} //被删结点无左子树 if (f->lchild==p) f->lchild=p->rchild;//将被删结点的右子树接到其双亲上 else f->rchild=p->rchild; else {q=p; s=p->lchild; //被删结点有左子树 搜索“diyifanwen.net”或“第一范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,第一范文网,提供最新工程科技数据结构1800例题与答案之集合 (9)全文阅读和word下载服务。
相关推荐: