数据结构例题剖析.docx
《数据结构例题剖析.docx》由会员分享,可在线阅读,更多相关《数据结构例题剖析.docx(16页珍藏版)》请在冰豆网上搜索。
数据结构例题剖析
!
对给定关键字序号j(1(要求用最少的时间和最少的空间)例如:给定无序关键字{7,5,1,6,2,8,9,3},当j=4时,找到的关键字应是5。intpartition(RecTypeA[],int1,intn){inti=1,j=n;x=A[i].key;i=1;while(i{while(i=x)j--;if(iwhile(iif(i}returni;}voidFind_j(RecTypeA[],intn,intj)n为数组长度{i=partition(A,1,n);while(i!=j)if(ielsei=partition(A,1,i-1);∥在前半部分继续进行划分}因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下:散列地址0123456789关键字71481130189比较次数1211133答: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表示),这时可用邻接矩阵表示图的存储结构。请编写算法建立无向图的邻接矩阵的存储结构voidcreatgraph(intM[][],intn,inte)//设有n个顶点e条边{inti,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的数据元素BSTreeSearchBST1(BSTreet,keyTypek) {if(!t||k==t->key)return(t); elseif(kkey)return(SearchBST1(t->lchild,k)); elsereturn(SearchBST1(t->rchild,k)); } 写出快速排序中一趟划分的算法。intpartition(intR[],ints,intt)//s和t是数组的低下标和高下标{inti=s,j=t,x=R[i].key;while(i{while(i=x)j--;R[i]=R[j];while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
(要求用最少的时间和最少的空间)
例如:
给定无序关键字{7,5,1,6,2,8,9,3},当j=4时,找到的关键字应是5。
intpartition(RecTypeA[],int1,intn)
{
inti=1,j=n;x=A[i].key;
i=1;
while(i{while(i=x)j--;if(iwhile(iif(i}returni;}voidFind_j(RecTypeA[],intn,intj)n为数组长度{i=partition(A,1,n);while(i!=j)if(ielsei=partition(A,1,i-1);∥在前半部分继续进行划分}因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下:散列地址0123456789关键字71481130189比较次数1211133答: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表示),这时可用邻接矩阵表示图的存储结构。请编写算法建立无向图的邻接矩阵的存储结构voidcreatgraph(intM[][],intn,inte)//设有n个顶点e条边{inti,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的数据元素BSTreeSearchBST1(BSTreet,keyTypek) {if(!t||k==t->key)return(t); elseif(kkey)return(SearchBST1(t->lchild,k)); elsereturn(SearchBST1(t->rchild,k)); } 写出快速排序中一趟划分的算法。intpartition(intR[],ints,intt)//s和t是数组的低下标和高下标{inti=s,j=t,x=R[i].key;while(i{while(i=x)j--;R[i]=R[j];while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
while(i=x)j--;
if(iwhile(iif(i}returni;}voidFind_j(RecTypeA[],intn,intj)n为数组长度{i=partition(A,1,n);while(i!=j)if(ielsei=partition(A,1,i-1);∥在前半部分继续进行划分}因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下:散列地址0123456789关键字71481130189比较次数1211133答: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表示),这时可用邻接矩阵表示图的存储结构。请编写算法建立无向图的邻接矩阵的存储结构voidcreatgraph(intM[][],intn,inte)//设有n个顶点e条边{inti,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的数据元素BSTreeSearchBST1(BSTreet,keyTypek) {if(!t||k==t->key)return(t); elseif(kkey)return(SearchBST1(t->lchild,k)); elsereturn(SearchBST1(t->rchild,k)); } 写出快速排序中一趟划分的算法。intpartition(intR[],ints,intt)//s和t是数组的低下标和高下标{inti=s,j=t,x=R[i].key;while(i{while(i=x)j--;R[i]=R[j];while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
while(iif(i}returni;}voidFind_j(RecTypeA[],intn,intj)n为数组长度{i=partition(A,1,n);while(i!=j)if(ielsei=partition(A,1,i-1);∥在前半部分继续进行划分}因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下:散列地址0123456789关键字71481130189比较次数1211133答: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表示),这时可用邻接矩阵表示图的存储结构。请编写算法建立无向图的邻接矩阵的存储结构voidcreatgraph(intM[][],intn,inte)//设有n个顶点e条边{inti,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的数据元素BSTreeSearchBST1(BSTreet,keyTypek) {if(!t||k==t->key)return(t); elseif(kkey)return(SearchBST1(t->lchild,k)); elsereturn(SearchBST1(t->rchild,k)); } 写出快速排序中一趟划分的算法。intpartition(intR[],ints,intt)//s和t是数组的低下标和高下标{inti=s,j=t,x=R[i].key;while(i{while(i=x)j--;R[i]=R[j];while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
if(i}returni;}voidFind_j(RecTypeA[],intn,intj)n为数组长度{i=partition(A,1,n);while(i!=j)if(ielsei=partition(A,1,i-1);∥在前半部分继续进行划分}因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下:散列地址0123456789关键字71481130189比较次数1211133答: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表示),这时可用邻接矩阵表示图的存储结构。请编写算法建立无向图的邻接矩阵的存储结构voidcreatgraph(intM[][],intn,inte)//设有n个顶点e条边{inti,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的数据元素BSTreeSearchBST1(BSTreet,keyTypek) {if(!t||k==t->key)return(t); elseif(kkey)return(SearchBST1(t->lchild,k)); elsereturn(SearchBST1(t->rchild,k)); } 写出快速排序中一趟划分的算法。intpartition(intR[],ints,intt)//s和t是数组的低下标和高下标{inti=s,j=t,x=R[i].key;while(i{while(i=x)j--;R[i]=R[j];while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
}
returni;
voidFind_j(RecTypeA[],intn,intj)n为数组长度
i=partition(A,1,n);
while(i!
=j)
if(ielsei=partition(A,1,i-1);∥在前半部分继续进行划分}因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下:散列地址0123456789关键字71481130189比较次数1211133答: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表示),这时可用邻接矩阵表示图的存储结构。请编写算法建立无向图的邻接矩阵的存储结构voidcreatgraph(intM[][],intn,inte)//设有n个顶点e条边{inti,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的数据元素BSTreeSearchBST1(BSTreet,keyTypek) {if(!t||k==t->key)return(t); elseif(kkey)return(SearchBST1(t->lchild,k)); elsereturn(SearchBST1(t->rchild,k)); } 写出快速排序中一趟划分的算法。intpartition(intR[],ints,intt)//s和t是数组的低下标和高下标{inti=s,j=t,x=R[i].key;while(i{while(i=x)j--;R[i]=R[j];while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
elsei=partition(A,1,i-1);∥在前半部分继续进行划分
因装填因子为0.7,有7个元素,故哈希表长m=7/0.7=10构造的哈希表如下:
散列地址0123456789
关键字71481130189
比较次数1211133
答:
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表示),这时可用邻接矩阵表示图的存储结构。
请编写算法建立无向图的邻接矩阵的存储结构
voidcreatgraph(intM[][],intn,inte)//设有n个顶点e条边
inti,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的数据元素
BSTreeSearchBST1(BSTreet,keyTypek)
if(!
t||k==t->key)return(t);
elseif(kkey)return(SearchBST1(t->lchild,k));
elsereturn(SearchBST1(t->rchild,k));
写出快速排序中一趟划分的算法。
intpartition(intR[],ints,intt)//s和t是数组的低下标和高下标
inti=s,j=t,x=R[i].key;
while(i{while(i=x)j--;R[i]=R[j];while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
while(i=x)
j--;
R[i]=R[j];
while(ii++;R[j]=R[i];}r[i]=x;returni;}要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。相关类型定义如下:void QueueOut(CycQueuecq);{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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
i++;
R[j]=R[i];
r[i]=x;
要求完全利用循环队列中的元素空间,设置一个标志域tag,并以tag的值是0或1来区分尾指针和头指针相同时的队列状态是“空”还是“不空”请编写与此结构相对应的出队算法。
相关类型定义如下:
void QueueOut(CycQueuecq);
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 已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法intHeight(BiTreebt){inthl,hr;if(bt==null)return(0); //空二叉树深度为0else{hl=Height(bt->lchild); //左子树的深度hr=Height(bt->rchild); //右子树的深度if(hl>hr)return(hl+1);//二叉树的深度elsereturn(hr+1);} }以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。intLeafCount(BiTreeT){if(!T)return0;//空树没有叶子elseif(!T->lchild&&!T->rchild)return1;//叶子结点elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);}设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始{inti=0,j=0,k=n-1;while(j<=k){if(r[j]==1)//当前元素是红色{r[i]交换r[j];i++;j++;}elseif(r[j]==2)j++;//当前元素是白色else//(r[j]==3)当前元素是兰色{r[j]交换r[k];k--;}}把十进制n转换为八进制voidConvert(intn){if(n!=0){Convert(n/8);cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
已知二叉树的二叉链表存储表示如下,试编写求二叉树深度的算法
intHeight(BiTreebt)
inthl,hr;
if(bt==null)return(0); //空二叉树深度为0
hl=Height(bt->lchild); //左子树的深度
hr=Height(bt->rchild); //右子树的深度
if(hl>hr)return(hl+1);//二叉树的深度
elsereturn(hr+1);
以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。
intLeafCount(BiTreeT)
T)return0;//空树没有叶子
T->lchild&&!
T->rchild)return1;//叶子结点
elsereturnLeafCount(T->lchild)+LeafCount(T->rchild);
设有顺序放置的n个桶,每个桶中装有一粒砾石,每粒砾石的颜色是红、白、蓝之一。
要求重新安排,使得红色砾石在前,白色砾石居中,蓝色砾石居后。
对每粒砾石的颜色只能察看一次,且只允许交换操作来调整砾石的位置。
voidQkSort(rectyper[],intn)//需要两个标识符,2的开始与3的开始
inti=0,j=0,k=n-1;
while(j<=k)
if(r[j]==1)//当前元素是红色
{r[i]交换r[j];i++;j++;}
elseif(r[j]==2)j++;//当前元素是白色
else//(r[j]==3)当前元素是兰色
{r[j]交换r[k];k--;}
把十进制n转换为八进制
voidConvert(intn)
{if(n!
=0)
{Convert(n/8);
cout<}}顺序结构线性表A与B的结点关键字为整数。A与B的元素按非递减有序,线性表空间足够大。试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。高效指最大限度的避免移动元素。templatevoidUnion(arrList&A,arrList&B)//union是类arrList的友元{intm=A.curLen;intn=B.curLen;//m,n分别为线性表A和B的长度。intk=m+n-1;//k为结果线性表的工作指针(下标)inti=m-1;intj=n-1;//i,j分别为线性表A和B的工作指针(下标)while(i>=0&&j>=0){if(A.aList[i]>=B.aList[j])A.aList[k--]=A.aList[i--];elseA.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的数据元素。voidarrList::DelAll(Titem){inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
}}
顺序结构线性表A与B的结点关键字为整数。
A与B的元素按非递减有序,线性表空间足够大。
试给出一种高效算法,将B中元素合到A中,使新的A的元素仍保持非递减有序。
高效指最大限度的避免移动元素。
template
voidUnion(arrList&A,arrList&B)//union是类arrList的友元
intm=A.curLen;
intn=B.curLen;//m,n分别为线性表A和B的长度。
intk=m+n-1;//k为结果线性表的工作指针(下标)
inti=m-1;
intj=n-1;//i,j分别为线性表A和B的工作指针(下标)
while(i>=0&&j>=0)
if(A.aList[i]>=B.aList[j])
A.aList[k--]=A.aList[i--];
A.aList[k--]=B.aList[j--];
while(j>=0)
A.curLen=m+n;
已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为0(n)、空间复杂度为0
(1)的算法,该算法删除线性表中所有值为item的数据元素。
voidarrList:
:
DelAll(Titem)
{inti=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:若题目要求元素间相对顺序不变,可用如下语句段:voidarrList::DelAll(Titem){i=0;j=0;while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
curLen=i;
PS:
若题目要求元素间相对顺序不变,可用如下语句段:
i=0;j=0;
while(j{if(aList[j]==item)j++;elseA[i++]=A[j++];}}//最后线性表中的元素个数是i。将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间lnkList*Union(lnkList*la,lnkList*lb)//友元函数{Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针lnkList*lc;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指向pawhile(pa->next)pa=pa->next;lc->tail=pa;//修改尾指针}elseif(pb){pc->next=pb;//若pb未到尾,将pc指向pbwhile(pb->next)pb=pb->next;lc->tail=pb;//修改尾指针}deletelb;return(lc);}假设一个单循环链表,其结点含有三个域pre、data、next。其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。请设计算法,将此表改成双向循环链表。voidSToDouble(LinkedListla){while(la->next->pre==null){la->next->pre=la;la=la->next;}}请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。Link*DisUnion(Link*L1,Link*L2){inti=0;Link*p,*s,*tail,*L2=newLink(NULL);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*CyclInsert(Link*p){q=p->next;//q指向a1结点,工作指针t=newLink(NULL);t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针p->next=t;q=q->next;while(q!=p){t=newLink(NULL);t->data=q->data;t->next=p->next;p->next=t;q=q->next;}p=r;returnp;}设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。要求使用原链表空间,表中无重复数据。Link*Union(Link*ha,Link*hb){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;deleteu;}while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}if(pa->datadata)//头插法,逆序建新表{r=pa->next;//将pa的后继结点暂存于rpa->next=ha->next;ha->next=pa;pa=r;//恢复pa为当前待比较结点}elseif(pb->datadata){r=pb->next;//将pb的后继结点暂存于rpb->next=ha->next;ha->next=pb;pb=r;//恢复pb为当前待比较结点}else//删除链表pb和pa中的重复元素{u=pb;pb=pb->next;deleteu;}}if(pa)pb=pa;//避免再对pa写下面的while语句while(pb){while(pb->next&&pb->data==pb->next->data){u=pb->next;pb->next=u->next;deleteu;}r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素returnha;}以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。voidchange(BiTreeT){if(T!=NULL){change(T->lchild);change(T->rchild);t=T->lchild;T->lchild=T->rchild;T->rchild=t;}}以二叉链表作为存储结构,设计算法拷贝二叉树。BiTreecopy(BiTreeT){BiTreeT1;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);}returnT1;}!!单链表的逆置template//单链表的元素类型为TvoidlnkList::invert(){//逆置单链表Link*p=head->next,*r;//p为工作指针,指向第一个元素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,intSearchInvK(constintk){//在单链表la上查找倒数第k个结点p=list->link;//p指向当前待处理元素q=list;//若成功,q指向倒数第k个元素i=1;while(p&&ilink;}if(p==null){cout<<“不存在\n”;return0;}while(p){q=q->link;p=p->link;}cout<<“倒数第k个元素的data域:”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
if(aList[j]==item)j++;
elseA[i++]=A[j++];
}//最后线性表中的元素个数是i。
将非递减有序的单链表la和lb合并成新的非递减有序单链表lc,并要求利用原表空间
lnkList*Union(lnkList*la,lnkList*lb)//友元函数
Link*pa,*pb,*pc;//分别是是链表la、lb、lc的工作指针
lnkList*lc;
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;//修改尾指针
elseif(pb)
{pc->next=pb;//若pb未到尾,将pc指向pb
while(pb->next)
pb=pb->next;
lc->tail=pb;//修改尾指针
deletelb;
return(lc);
假设一个单循环链表,其结点含有三个域pre、data、next。
其中data为数据域;pre为指针域,它的值为空指针(null);next为指针域,它指向后继结点。
请设计算法,将此表改成双向循环链表。
voidSToDouble(LinkedListla)
{while(la->next->pre==null)
{la->next->pre=la;
la=la->next;
请编写算法将单链表L1拆成二个链表,其中以L1为头的链表保持原来向后的链接,另一个链表的表头为L2,其链接方向与L1相反,L1包含原链表的奇数序号的结点,L2包含原链表的偶数序号的结点。
Link*DisUnion(Link*L1,Link*L2)
{inti=0;
Link*p,*s,*tail,*L2=newLink(NULL);
L2->next=NULL;∥以L2为头指针的空链表
p=L1->next;tail=L1;
while(p)
{i++;
if(i%2)
{tail->next=p;tail=p;p=p->next;}
{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*CyclInsert(Link*p)
{q=p->next;//q指向a1结点,工作指针
t=newLink(NULL);
t->data=q->data;t->next=p->next;r=t;//r记住a1结点的指针
p->next=t;q=q->next;
while(q!
=p)
{t=newLink(NULL);
t->data=q->data;t->next=p->next;
p=r;returnp;
设ha和hb分别是两个带头结点的非递减有序单链表的头指针,将这两个有序链表合并成一个非递增有序的单链表。
要求使用原链表空间,表中无重复数据。
Link*Union(Link*ha,Link*hb)
{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;deleteu;}while(pb->next&&pb->data==pb->next->data)
{u=pb->next;pb->next=u->next;deleteu;}
if(pa->datadata)//头插法,逆序建新表
{r=pa->next;//将pa的后继结点暂存于r
pa->next=ha->next;
ha->next=pa;
pa=r;//恢复pa为当前待比较结点
elseif(pb->datadata)
{r=pb->next;//将pb的后继结点暂存于r
pb->next=ha->next;
ha->next=pb;
pb=r;//恢复pb为当前待比较结点
else//删除链表pb和pa中的重复元素
{u=pb;pb=pb->next;deleteu;}
if(pa)pb=pa;//避免再对pa写下面的while语句
while(pb)
{while(pb->next&&pb->data==pb->next->data)
r=pb->next;pb->next=ha->next;ha->next=pb;pb=r;
}//将尚未到尾的表逆置到结果表中,注意也要删除重复元素
returnha;
以二叉链表作为存储结构,设计算法交换二叉树中所有结点的左、右子树。
voidchange(BiTreeT)
{if(T!
=NULL)
{change(T->lchild);
change(T->rchild);
t=T->lchild;
T->lchild=T->rchild;
T->rchild=t;
以二叉链表作为存储结构,设计算法拷贝二叉树。
BiTreecopy(BiTreeT)
{BiTreeT1;
if(T==null)T1=null;
{T1=(BiTree)malloc(sizeof(BiNode));//申请结点
T1->data=T->data;
T1->lchild=copy(T->lchild);
T1->rchild=copy(T->rchild);
returnT1;
单链表的逆置
template//单链表的元素类型为T
voidlnkList:
invert()
{//逆置单链表
Link*p=head->next,*r;//p为工作指针,指向第一个元素
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,
intSearchInvK(constintk)
{//在单链表la上查找倒数第k个结点
p=list->link;//p指向当前待处理元素
q=list;//若成功,q指向倒数第k个元素
while(p&&ilink;}
if(p==null){cout<<“不存在\n”;return0;}
while(p){q=q->link;p=p->link;}
cout<<“倒数第k个元素的data域:
”<data<return1;}//SearchInvK !!已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。若A是B的子集,返回TRUE,否则返回FALSE。BOOLjudge(node*A,node*B){P=A->next;Q=B->next;num=0;while((P!=NULL)&&(Q!=NULL))switch{caseP->datadata:P=P->next;num=num+1;break;caseP->data>Q->data:Q=Q->next;break;caseP->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<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
return1;
}//SearchInvK
已知递增有序的带头结点的单链表表示一类集合,设计算法以判断集合A是否是B的子集。
若A是B的子集,返回TRUE,否则返回FALSE。
BOOLjudge(node*A,node*B)
P=A->next;Q=B->next;num=0;
while((P!
=NULL)&&(Q!
=NULL))
switch
{caseP->datadata:
P=P->next;num=num+1;break;
caseP->data>Q->data:
Q=Q->next;break;
caseP->data==Q->data:
P=P->next;Q=Q->next;break;
while(P!
=NULL){num=num+1;P=P->next;}
judge=num==0;
if(num!
cout<<”NumberofelementsthatisinAbutnotinB=”<}!!假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。#defineMAXSIZE100∥队列可能达到的最大长度typedefstruct{ElemTypedata[MAXSIZE];∥数据的存储区intrear,length;∥队尾指针和队列长度}CyQueue;∥循环队列ElemTypeQueueOut(SeQueuecq)出队算法∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素{if(cq.length==0)return(0);∥队空else{intfront=(cq.rear-cq.length+1+m)%m;∥出队元素位置cq.length--;∥修改队列长度 return(cq.Q[front]);∥返回对头元素}}(3)入队SeQueueQueueIn(SeQueuecq,ElemTypex)∥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(1)给出算法的基本设计思想。(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。(3)说明你所设计算法的时间复杂度和空间复杂度。(1)算法设计思想:按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。(2)voidleftshift(intR[],intp,intn){elemtypet;//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;}for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
假设用变量rear和length分别指示循环队列中队尾元素的位置和队列中元素的个数。
请按下面给出的循环队列的定义,写出相应出队(QueueOut)算法。
#defineMAXSIZE100∥队列可能达到的最大长度
typedefstruct
{ElemTypedata[MAXSIZE];∥数据的存储区
intrear,length;∥队尾指针和队列长度
}CyQueue;∥循环队列
ElemTypeQueueOut(SeQueuecq)出队算法
∥cq是以如上定义的循环队列,本算法是出队算法,且返回出队元素
{if(cq.length==0)return(0);∥队空
{intfront=(cq.rear-cq.length+1+m)%m;
∥出队元素位置
cq.length--;∥修改队列长度
return(cq.Q[front]);∥返回对头元素
(3)入队
SeQueueQueueIn(SeQueuecq,ElemTypex)
∥cq是以如上定义的循环队列,本算法将元素x入队
{if(cq.length==m)return(0);∥队满
{cq.rear=(cq.rear+1)%m;∥计算插入元素位置
cq.Q[cq.rear]=x;∥将元素x入队列
cq.length++;∥修改队列长度
return(cq);
设将n(n>1)个整数存放到一维数组R中。
试设计一个在时间和空间两方面都尽可能高效的算法,将R中保存的序列循环左移P(0
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++或JAVA语言描述算法,关键之处给出注释。
(3)说明你所设计算法的时间复杂度和空间复杂度。
(1)算法设计思想:
按照下标0到p-1、p到n-1、0到n-1的顺序,将这三段分别逆置,最后的结果即为所求。
(2)voidleftshift(intR[],intp,intn)
elemtypet;//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;}
for(i=0;i{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}}(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O(1)。讨论:若采用直接左移p位,空间复杂度仍为O(1),但时间复杂度为O(np)。!!!在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。Dlink*ListLocate(Dlink*La,Tx){Dlink*p=La->next,*q=La;while(p&&p->data!=x){q=p;p=p->next;}if(!p){printf(“不存在所查结点,现插入之\n”);s=newLink;s->data=x;s->freq=0;∥插入值为x的结点s->next=p;s->prior=q;q->next=s;p=s;∥返回p结点;}else{p->freq++;∥令元素值为x的结点的freq域加1
{t=R[i];R[i]=R[n-1-i];R[n-1-i]=t;}
(3)算法执行了两趟逆置,时间复杂度为O(n);用了一个辅助变量空间,空间复杂度为O
(1)。
讨论:
若采用直接左移p位,空间复杂度仍为O
(1),但时间复杂度为O(np)。
在一个设la是带头结点的双向链表的指针,其结点中除有prior,data和next外,还有一访问频度域freq,其值在链表初始使用时为0。
当在链表中进行ListLocate(la,x)运算时,若查找失败,则在表尾插入值为x的结点;若查找成功,值为x的结点的freq值增1,并要求链表按freq域值非增(递减)的顺序排列,且最近访问的结点排在频度相同的结点的后面,使频繁访问的结点总是靠近表头。
试编写符合上述要求的ListLocate(la,x)运算的算法,返回找到结点的指针。
Dlink*ListLocate(Dlink*La,Tx)
{Dlink*p=La->next,*q=La;while(p&&p->data!
=x){q=p;p=p->next;}if(!
p){printf(“不存在所查结点,现插入之\n”);
s=newLink;
s->data=x;s->freq=0;∥插入值为x的结点
s->next=p;s->prior=q;
q->next=s;p=s;∥返回p结点;
else{p->freq++;∥令元素值为x的结点的freq域加1
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1