数据结构--例题
![数据结构--例题](https://img.360docs.net/img49/18lpac68hx5zdztg3kzl36ez99pxvfzy-91.webp)
![数据结构--例题](https://img.360docs.net/img49/18lpac68hx5zdztg3kzl36ez99pxvfzy-a2.webp)
!!对给定关键字序号j(1 例如:给定无序关键字{7,5,1,6,2,8,9,3},当j=4时,找到的关键字应是5。 int partition(RecType A[], int 1, int n) { int i=1,j=n;x=A[i].key; i=1; while(i { while(i if(i while(i if(i } return i; } void Find_j(RecType A[],int n,int j) n为数组长度 { i=partition (A,1,n); while(i!=j) if(i 因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下: 散列地址0 1 2 3 4 5 6 7 8 9 关键字 7 14 8 11 30 18 9 比较次数 1 2 1 1 1 3 3 答:ASL成功=1/7*(1*4+2*1+3*2)=12/7,失败=1/7*(3+2+1+2+1+5+4)=18/7 设图的顶点只是编号1――n,边的信息是有(用1表示)或无(用0表示),这时可用邻接矩阵表示图的存储结构。请编写算法建立无向图的邻接矩阵的存储结构void creatgraph(int M[][],int n,int e) //设有n个顶点e条边 { int i,j; for (i=1;i<=n;i++) for(j=1;j<=n;j++) M[i][j]=0; for (i=1;i<=e;i++) { cin>>i>>j; M[i][j]=1; M[j][i]=1; } } 在根指针t所指二叉排序树中递归查找某关键字等于k的数据元素BSTree SearchBST1(BSTree t,keyType k) { if(!t||k==t->key) return(t); else if(k else return(SearchBST1(t->rchild,k)); } 写出快速排序中一趟划分的算法。 int partition(int R[],int s,int t) //s和t是数组的低下标和高下标{ int i=s,j=t,x=R[i].key; while(i { while(i j--; R[i]=R[j]; while(i i++; R[j]=R[i]; } r[i]=x; return i; } 要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下: void QueueOut(CycQueue cq); { if(cq.tag==0) cout<<"队列为空\n"; else { cq.front=( cq.front+1) % m; if(cq.front== cq.rear) cq.tag=0; //空队列 } } !!设n是非负整数,下面程序片段的时间复杂度是(O(log2n) )。 x=2; while(x 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法int Height(BiTree bt) { int hl,hr; if(bt==null) return(0); //空二叉树深度为0 else { hl=Height(bt->lchild); //左子树的深度 hr=Height(bt->rchild); //右子树的深度 if(hl>hr) return(hl+1); //二叉树的深度 else return(hr+1); } } 以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。 int LeafCount(BiTree T) { if(!T) return 0; //空树没有叶子 else if(!T->lchild && !T->rchild) return 1; //叶子结点 else return LeafCount(T->lchild)+LeafCount(T->rchild); } 设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。 void QkSort(rectype r[ ],int n) //需要两个标识符,2的开始与3的开始{ int i=0, j=0, k=n-1; while(j<=k) { if( r[j]==1) //当前元素是红色 {r[i]交换r[j]; i++; j++; } else if( r[j]==2) j++; //当前元素是白色 else //(r[j]==3) 当前元素是兰色 {r[j]交换r[k]; k--; } } 把十进制n转换为八进制 void Convert(int n ) { if(n!=0) { Convert(n/8); cout<< n%8 ; } } 顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。 template void Union(arrList int m=A.curLen; int n=B.curLen; //m,n分别为线性表A和B的长度。 int k=m+n-1; //k为结果线性表的工作指针(下标) int i=m-1; int j=n-1; //i,j分别为线性表A和B的工作指针(下标)while (i>=0 && j>=0) { if (A.aList[i]>=B.aList[j]) A.aList[k--]=A.aList[i--]; else A.aList[k--]= B.aList[j--]; } while (j>=0) A.aList[k--]= B.aList[j--]; A.curLen=m+n; } 已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为0(n)、空间复杂度为0(1)的算法,该算法删除线性表中所有值为item的数据元素。 void arrList { int i=0,j=curLen-1; //设置数组低、高端指针(下标) while(i<=j) { while(i<=j && aList[i]!=item) i++; while(i<=j && aList[j]==item) j--; if(i } curLen=i; } PS:若题目要求元素间相对顺序不变,可用如下语句段: void arrList { i=0;j=0; while(j { if(aList[j]==item) j++; else A[i++]=A[j++]; } } //最后线性表中的元素个数是i。 将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间 lnkList { Link lnkList lc=la; //lc利用la空间,将lb合并进来 pa=(la->head)->next; (la->head)->next=NULL; pb=(lb->head)->next; (lb->head)->next=NULL; pc=lc->head; while(pa && pb) //la和lb均非空 { if(pa->data<=pb->data) //la中元素插入lc { pc->next=pa; pc=pa; pa=pa->next; } else //lb中元素插入lc { pc->next=pb; pc=pb; pb=pb->next; } } if(pa) { pc->next=pa; //若pa未到尾,将pc指向pa while(pa->next) pa=pa->next; lc->tail=pa; //修改尾指针 } else if(pb) { pc->next=pb; //若pb未到尾,将pc指向pb while(pb->next) pb=pb->next; lc->tail=pb; //修改尾指针 } delete lb; return(lc); } 假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。 void SToDouble(LinkedList la) { while(la->next->pre==null) { la->next->pre=la; la=la->next; } } 请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号 的结点,L2包含原链表的偶数序号的结点。 Link { int i=0; Link L2->next=NULL; ∥以L2为头指针的空链表 p=L1->next; tail=L1; while(p) { i++; if(i%2) { tail->next=p; tail=p; p=p->next;} else { s=p->next; p->next=L2->next; //s储存p的下一个结点 L2->next=p; p=s; //采用头插法逆置偶数序号的结点 } } tail->next=NULL; ∥置L1表尾 } 已知p是指向单向循环链表最后一个结点的指针,试编写只包含一个循环的算法,将线性表(a1,,…,an)改造为(a1,…,an-1,an, an-1,…,a1) Link { q=p->next; //q指向a1结点,工作指针 t=new Link t->data=q->data; t->next=p->next; r=t; //r记住a1结点的指针 p->next=t; q=q->next; while(q!=p) { t=new Link t->data=q->data; t->next=p->next; p->next=t; q=q->next; } p=r; return p; } 设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。 Link { pa=ha->next; pb=hb->next; ha->next=null; //ha作结果链表的头指针,先将结果链表初始化为空 while(pa && pb) { while(pa->next && pa->data==pa->next->data) { u=pa->next;pa->next=u->next;delete u;} while(pb->next && pb->data==pb->next->data) { u=pb->next; pb->next=u->next; delete u;} if(pa->data pa->next=ha->next; ha->next=pa; pa=r; //恢复pa为当前待比较结点 } else if(pb->data { r=pb->next; //将pb 的后继结点暂存于r pb->next=ha->next; ha->next=pb; pb=r; //恢复pb为当前待比较结点 } else //删除链表pb和pa中的重复元素 { u=pb; pb=pb->next; delete u; } } if(pa) pb=pa; //避免再对pa写下面的while语句 while(pb) { while(pb->next && pb->data==pb->next->data) { u=pb->next; pb->next=u->next; delete u; } r=pb->next; pb->next=ha->next; ha->next=pb; pb=r; } //将尚未到尾的表逆置到结果表中,注意也要删除重复元素 return ha; } 以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。 void change(BiTree T) { if(T!=NULL) { change(T->lchild); change(T->rchild); t=T->lchild; T->lchild=T->rchild; T->rchild=t; } } 以二叉链表作为存储结构,设计算法拷贝二叉树。 BiTree copy(BiTree T) { BiTree T1; if(T==null) T1=null; else { T1=(BiTree)malloc(sizeof(BiNode)); //申请结点 T1->data=T->data; T1->lchild=copy(T->lchild); T1->rchild=copy(T->rchild); } return T1; } !!单链表的逆置 template void lnkList {//逆置单链表 Link head->next=NULL; //保留第一个元素的指针后,将头结点的指针域置空 tail=p; while(p!=NULL) //将原链表的元素按头插法插入 { r=p->next; //暂存p的后继 p->next=head->next; //逆置(头插法插入) head->next=p; //头结点的指针域指向新插入的结点 p=r; //恢复待处理结点 } } !!已知一个带有表头结点的单链表,结点结构为(data,link),假设该链表只给出了头指针list。在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数),若查找成功,算法输出该结点的data域的值,并返回1;否则,只返回0, int SearchInvK(const int k) { //在单链表la上查找倒数第k个结点 p=list->link; //p指向当前待处理元素 q=list; //若成功,q指向倒数第k个元素 i=1; while(p && i if(p==null) {cout<<“不存在\n”; return 0; } while(p) { q=q->link; p=p->link; } cout<<“倒数第k个元素的data域:”< return 1; }//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是 B的子集,返回TRUE,否则返回FALSE。 BOOL judge( node* A, node* B) { P= A->next; Q= B->next; num= 0; while ((P!=NULL) && (Q!=NULL)) switch { case P->data P= P->next; num= num+1; break; case P->data>Q->data: Q= Q->next; break; case P->data==Q->data: P= P->next; Q= Q->next ; break; } while (P!=NULL) { num= num+1; P= P->next; } judge = num==0; if (num!=0 ) cout<<”Number of elements that is in A but not in B =” < !!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。 #define MAXSIZE 100 ∥队列可能达到的最大长度 typedef struct {ElemType data[MAXSIZE]; ∥数据的存储区 int rear,length; ∥队尾指针和队列长度 }CyQueue; ∥循环队列 ElemType QueueOut(SeQueue cq)出队算法 ∥ cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素 { if(cq.length==0) return(0); ∥队空 else { int front=(cq.rear-cq.length+1+m) % m; ∥出队元素位置 cq.length--; ∥修改队列长度 return (cq.Q[front]); ∥返回对头元素} } (3) 入队 SeQueue QueueIn(SeQueue cq,ElemType x) ∥cq是以如上定义的循环队列,本算法将元素x入队 { if(cq.length==m) return(0); ∥队满 else {cq.rear=(cq.rear+1) % m; ∥计算插入元素位置 cq.Q[cq.rear]=x; ∥将元素x入队列 cq.length++; ∥修改队列长度 } return (cq); } !!!设将n(n>1)个整数存放到一维数组R中。试设计一个在时间和空间两方面都尽可能高效的算法,将R中保存的序列循环左移P(0 (2)根据设计思想,采用C 或C++或JAVA 语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。 (1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分 别逆置,最后的结果即为所求。 (2) void leftshift(int R[], int p, int n) { elemtype t; //t和数组R中的元素具有相同类型 for(i=0;i {t=R[i]; R[i]=R[p-1-i]; R[p-1-i]=t;} For(i=p;i<(n+p)/2;i++) //逆置p..n-1段 {t=R[i]; R[i]=R[n-1-i+p];R[n-1-i+p]=t;}