数据结构例题剖析.docx

上传人:b****6 文档编号:7261789 上传时间:2023-01-22 格式:DOCX 页数:16 大小:23.79KB
下载 相关 举报
数据结构例题剖析.docx_第1页
第1页 / 共16页
数据结构例题剖析.docx_第2页
第2页 / 共16页
数据结构例题剖析.docx_第3页
第3页 / 共16页
数据结构例题剖析.docx_第4页
第4页 / 共16页
数据结构例题剖析.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

数据结构例题剖析.docx

《数据结构例题剖析.docx》由会员分享,可在线阅读,更多相关《数据结构例题剖析.docx(16页珍藏版)》请在冰豆网上搜索。

数据结构例题剖析.docx

数据结构例题剖析

!

!

对给定关键字序号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(i

while(i

if(i

}

returni;

}

voidFind_j(RecTypeA[],intn,intj)n为数组长度

{

i=partition(A,1,n);

while(i!

=j)

if(i

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(i

i++;

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);     //空二叉树深度为0

else

{

hl=Height(bt->lchild); //左子树的深度

hr=Height(bt->rchild); //右子树的深度

if(hl>hr)return(hl+1);//二叉树的深度

elsereturn(hr+1);

}

 }

以二叉链表作为存储结构,试编写求二叉树中叶子数的算法。

intLeafCount(BiTreeT)

{

if(!

T)return0;//空树没有叶子

else

if(!

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的元素仍保持非递减有序。

高效指最大限度的避免移动元素。

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--];

else

A.aList[k--]=B.aList[j--];

}

while(j>=0)

A.aList[k--]=B.aList[j--];

A.curLen=m+n;

}

已知长度为n的线性表A采用顺序存储结构,请写一时间复杂度为0(n)、空间复杂度为0

(1)的算法,该算法删除线性表中所有值为item的数据元素。

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指向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;}

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的后继结点暂存于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)

{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//单链表的元素类型为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个元素

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

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

当前位置:首页 > 表格模板 > 合同协议

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

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