00-04数据结构大题答案
六、(15分)设有n个大小不等的数据组(n个数据组中数据的总数为 m),顺序存放在空间区D内,每个数据占一个存储单元。数据组的 首地址由数组S给出(如下图所示),试编写将新数据x插入到第i个 数据组的末尾且属于第i个数据组的算法,插入后,空间区D和数组S 的相互关系仍保持正确。 解:void lnsert_x(sqlist ﹠L, int I, ElemType x ) { // 将数据x插入到D区,插入后D和S关系不变 if( i>=I &&i<=L.length) { for(j=0 , p=L. elem[ 0 ],j<=m; j+ +) p+ +; // 求D区空闲空间首地址 if(i==L.lingth) *p=x; else { // 不插入第n个数组 for(q=L.elem[ i ]; p>=q;--p) *(p+l)=*p; //后移 *p=x; //插入x
if(count==G.vexnum) printf (G.ver[ v ].data); } //for } //DfsTraverse void DFS(ALGraph G,int v) { //从第v个顶点出发递归地深度优先遍历图G visited[ v ]=1; count+ +; for(p=G.vertices[ v ].firstarc; p; p=p→nextarc) { w=p→adjvex; if(!visited[ w ]) } //for } // DFS
pre=la; la →next=NULL; . // q指最小元素 while(p&&p→data<x) { //比x小的数递减
r =p→next; p→next=La →next;
La →next=p; p=r ; //置逆
} // while
q→next=p; pre=q; //重新链接 while(p→data=x) { // 考察等于x的情况 pre=p; p=p→next; } // while while(p) { // k为计数器 k+ +; x=p→data; //避免重复计算 if(x%2==0) { //删除偶数 while (p→data==x) { // 考察等于x的情况 u=p ; p=p→next; free(u); } / /while pre→next=p; } // if else // 处理奇数 while(p→data==x) { pre →next=p; pre=p; p=p→next; } // while } // while(p) } // exam
三、(15分) 设T是一棵满二叉树,编写一个将T的先序遍历序列转换为后 序遍历序列的递归算法。 解:对于满二叉树,已知任一遍历序列可唯一确定一棵二叉树,即可 将任一遍历序列转换为另一遍历序列。 void pretopost(ElemType pre [ ],ElemType post [ ],int L1,int H1, int L2,int H2) { H1为主段,L1为序列位置 if (H1>L1) { post[ H2]=pre[L1]; // 根结点 half=(H1-L1)/2; pretopost(pre ,post, L1+1, L1+half, L2+half-1); pretopost(pre, post, L1+half+1 ,H1, L2+half, H2-1) } //if } // preropost
k=Locatevex(G,v2); // 确定v1,v2在G中位置
p=(ArcNode)malloc(sizeof(ArcNode) ); p →adjvex=k; p→next=G.ver[ j ].firstarc; G.ver[ j ]. Firstarc=p; } //for } //CreatALG
for(q=&L.elem[ i ],p=&L.elem[ L.length-I];p>=q;q++)
(*q)++; m++; } //Insert_x
二、(17分)设有一个正整数序列组成的有序单链表(按递 增次序有序,且允许有相等的整数存在),试编写能实现 下列功能的算法:(要求用最少的时间和最小的空间) (1) 确定在序列中比正整数x大的数有几个(相同的数只计 算一次,如序列(20,20,17,16,15,15,11,10,8, 7,7,5,4)中比10大的数有5个); (2) 在单链表中将比正整数x小的数按递减次序排列; (3) 在单链表中将比正整数x大的偶数从单链表中删除; 解:void exam(Linklist,La,int,x) { p=La→next; q=p; k=0; // p为工作指针
if(H[ j ]==Null)
exist(1);
else if(j=i) exist(1); else if(H[ j ]==key) { e=H[ j ]; H[ j ]=EMPTY; } //if } //else } //HSDelete
1.
如果用一个循环数组q[0..m-1]表示队列时,该队列只有一个队列头 指针front,不设队列尾指针rear,而改置计数器count用以记录队列中 结点的个数。 (1)编写实现队列的三个基本运算:判空、入队、出队(3分) (2)队列中能容纳元素的最多个数是多少?(1分) 解:TYPE qu=ARRAY[0..m-1] of elemtp (1) FUNC empty(VAR q:qu; VAR fornt,count:integer):bollean; if count=0 then empry:=true else empty: =false ENDF; FUNC enqueue(VAR q: qu; VAR fornt,count:integer;VAR x:elemtp):boolean; if count=m then RETURN (false) {队列已满} else [count=count=1]; i:=(front=count) MOD m;
五、(15分)在有向图G中,如果r到G的每个结点都有路径可达, 则称结点r为G的根结点,编写一个算法完成下列功能: (1)、建立有向图G的邻接表存储结构: (2)、判断有向图G是否有根,若有,则打印出所有根结点的值。
解:1、void CreatALG(ALGraph &G) { // 建立有向图的邻界表存储结构 int I, ArcNode *p; scanf(&G →vexnum, &G →arcnum); for(i=0;i<G→ vexnum;i+ + ) { scanf ((&G →ver[ i ].data); G→ver[ i ].firstarc=Null; } //for for(i=0; i<G→arcnum; i+ +) { scanf(&v1, &v2); j=、(15分)写出删除二叉排序树bt中值为x的结点的算法(二叉排 序树以二叉链表形式存储,删除后仍保持二叉排序性质)。 解: Status delete(BiTree ﹠t ,ElemType x) { // 删除二叉排序树中的x接点 if(x<p→data { q=p; p=p→lchild; } // if else { q=p; p=p→rchild; } // else if(!p) return false; // 来找到 else if(!p→rchild) { //被删结点无右子权 q=p; p=p→lchild; // 重接 free(q); } // if
六、(18分)对下面的关键字集(30,15,21,40,25,26,36,37),若 查找表的装填因子为0.8,采用线性探测再散列解决冲突,做: (4)将删除后的空间置标记为‘EMPTY’ Void HSDelete(HashTable &H,KeyType key) { // 删除哈希素中等于key的关键字,用线性探测再散列解决冲突 i=H(key ); // 取得哈希地址 if(H[ i ]==Null) exit(1); if (H[ i ]==key) { e=H [ i ] ; H[ i ]=EMPTY; } //if else{ di=1; j=(H(key)+di )%m; // m 为表长 while(H[ j ]&&j!=i) { di=di+1; j=((H(key)+di)%m; } //while
2、void DfsTraverse(ALGraph G) { //利用深度优先搜索,判断有向图G是否有根结点。 int visited[maxsige],count; //count为记录结构的顶点数。 for(v=0;v<G.vexnum ; v+ +) { for(v=0;v<G.vexnum ; v+ +) visited[ v ]=0; count=0; DFS(G,v) ;
四、(15分) 2、写出后序线索二叉树的非递归遍历算法。 解:根据后序线索二叉树的特点,利用前驱线索逆向先序遍历 void PreorderTraverse_Thr(BiThrTree T) { // T指向头结点,T的左链指向根结点. p=T→lchild; while(p!=T) { printf‘(p→data); if(p→rtag==0) p=p→rchild; else p=p→lchild; } // while } //PreorderTraverse_Thr
3、(12分)假设一个有向图g已经以十字链表形式存储在 内存中,试写一个判断该有向图中是否有环(回路)的算法。 解:对十字链表储存结构的有向图采用拓扑排序 Status toposort (OLGraph G) ﹛ findindegree (G, indegree); //对各项点求入度 InitQueue (Q); //队列初始化 Count=0; //计数器初始化 for(i=0;i<G.Vernum;i++) if(G.Ver[ i ].indegree==0) Enqueue(Q,i); //入度为零的顶点入队 While(!QueueEmpty (Q) ) ﹛ Dequeue(Q,i); //队头出队 Count++; P=G. ver [ i ].firstout; //取邻接点 while(p) ﹛ //处理邻接点的入度 j=p→ headvex; G.ver [ j ].indegree--; if(G.ver [ j ].indegree==0) Enqueue (Q,j); //顶点j入队 p=p→tlink;//指针后移 }//while }//while if ( (count<G.vernum) //有环 return ERROR; else return OK; } // toposort