《数据结构与算法》课后习题答案Word版文档格式.docx
《《数据结构与算法》课后习题答案Word版文档格式.docx》由会员分享,可在线阅读,更多相关《《数据结构与算法》课后习题答案Word版文档格式.docx(53页珍藏版)》请在冰豆网上搜索。
while(i>
=0&
&
A[i]>
x)/*边找位置边移动*/
{A[i+1]=A[i];
i--;
}
A[i+1]=x;
/*找到的位置是插入位的下一位*/
(*elenum)++;
return1;
/*插入成功*/
}
时间复杂度为O(n)。
2.已知一顺序表A,其元素值非递减有序排列,编写一个算法删除顺序表中多余的值相同的元素。
【提示】对顺序表A,从第一个元素开始,查找其后与之值相同的所有元素,将它们删除;
再对第二个元素做同样处理,依此类推。
voiddelete(Seqlist*A)
{i=0;
while(i<
A->
last)/*将第i个元素以后与其值相同的元素删除*/
{k=i+1;
while(k<
=A->
last&
data[i]==A->
data[k])
k++;
/*使k指向第一个与A[i]不同的元素*/
n=k-i-1;
/*n表示要删除元素的个数*/
for(j=k;
j<
last;
j++)
A->
data[j-n]=A->
data[j];
/*删除多余元素*/
A->
last=A->
last-n;
i++;
}
3.写一个算法,从一个给定的顺序表A中删除值在x~y(x<
=y)之间的所有元素,要求以较高的效率来实现。
【提示】对顺序表A,从前向后依次判断当前元素A->
data[i]是否介于x和y之间,若是,并不立即删除,而是用n记录删除时应前移元素的位移量;
若不是,则将A->
data[i]向前移动n位。
n用来记录当前已删除元素的个数。
voiddelete(Seqlist*A,intx,inty)
n=0;
while(i<
last)
{if(A->
data[i]>
=x&
A->
data[i]<
=y)n++;
/*若A->
data[i]介于x和y之间,n自增*/
elseA->
data[i-n]=A->
data[i];
/*否则向前移动A->
data[i]*/
last-=n;
}
4.线性表中有n个元素,每个元素是一个字符,现存于向量R[n]中,试写一算法,使R中的字符按字母字符、数字字符和其它字符的顺序排列。
要求利用原来的存储空间,元素移动次数最小。
【提示】对线性表进行两次扫描,第一次将所有的字母放在前面,第二次将所有的数字放在字母之后,其它字符之前。
intfch(charc)/*判断c是否字母*/
{if(c>
='
a'
c<
z'
||c>
A'
Z'
)return
(1);
elsereturn(0);
intfnum(charc)/*判断c是否数字*/
0'
9'
)return
(1);
elsereturn(0);
voidprocess(charR[n])
{low=0;
high=n-1;
while(low<
high)/*将字母放在前面*/
{while(low<
high&
fch(R[low]))low++;
!
fch(R[high]))high--;
if(low<
high)
{k=R[low];
R[low]=R[high];
R[high]=k;
low=low+1;
high)/*将数字放在字母后面,其它字符前面*/
fnum(R[low]))low++;
while(low<
fnum(R[high]))high--;
if(low<
{k=R[low];
}
5.线性表用顺序存储,设计一个算法,用尽可能少的辅助存储空间将顺序表中前m个元素和后n个元素进行整体互换。
即将线性表:
(a1,a2,…,am,b1,b2,…,bn)改变为:
(b1,b2,…,bn,a1,a2,…,am)。
【提示】比较m和n的大小,若m<
n,则将表中元素依次前移m次;
否则,将表中元素依次后移n次。
voidprocess(Seqlist*L,intm,intn)
{if(m<
=n)
for(i=1;
i<
=m;
i++)
{x=L->
data[0];
for(k=1;
k<
=L->
k++)
L->
data[k-1]=L->
data[k];
data[L->
last]=x;
}
elsefor(i=1;
=n;
last];
for(k=L->
last-1;
k>
=0;
k--)
data[k+1]=L->
data[0]=x;
6.已知带头结点的单链表L中的结点是按整数值递增排列的,试写一算法,将值为x的结点插入到表L中,使得L仍然递增有序,并且分析算法的时间复杂度。
LinkListinsert(LinkListL,intx)
{p=L;
while(p->
next&
x>
p->
next->
data)
p=p->
next;
/*寻找插入位置*/
s=(LNode*)malloc(sizeof(LNode));
/*申请结点空间*/
s->
data=x;
/*填装结点*/
s->
next=p->
p->
next=s;
/*将结点插入到链表中*/
return(L);
}
7.假设有两个已排序(递增)的单链表A和B,编写算法将它们合并成一个链表C而不改变其排序性。
LinkListCombine(LinkListA,LinkListB)
{C=A;
rc=C;
pa=A->
/*pa指向表A的第一个结点*/
pb=B->
/*pb指向表B的第一个结点*/
free(B);
/*释放B的头结点*/
while(pa&
pb)/*将pa、pb所指向结点中,值较小的一个插入到链表C的表尾*/
if(pa->
data<
pb->
data)
{rc->
next=pa;
rc=pa;
pa=pa->
else
next=pb;
rc=pb;
pb=pb->
if(pa)rc->
elserc->
/*将链表A或B中剩余的部分链接到链表C的表尾*/
return(C);
8.假设长度大于1的循环单链表中,既无头结点也无头指针,p为指向该链表中某一结点的指针,编写算法删除该结点的前驱结点。
【提示】利用循环单链表的特点,通过s指针可循环找到其前驱结点p及p的前驱结点q,然后可删除结点*p。
vioddelepre(LNode*s)
{LNode*p,*q;
p=s;
while(p->
next!
=s)
{q=p;
p=p->
q->
free(p);
9.已知两个单链表A和B分别表示两个集合,其元素递增排列,编写算法求出A和B的交集C,要求C同样以元素递增的单链表形式存储。
【提示】交集指的是两个单链表的元素值相同的结点的集合,为了操作方便,先让单链表C带有一个头结点,最后将其删除掉。
算法中指针p用来指向A中的当前结点,指针q用来指向B中的当前结点,将其值进行比较,两者相等时,属于交集中的一个元素,两者不等时,将其较小者跳过,继续后面的比较。
LinkListIntersect(LinkListA,LinkListB)
{LNode*q,*p,*r,*s;
LinkListC;
C=(LNode*)malloc(sizeof(LNode));
C->
next=NULL;
r=C;
p=A;
q=B;
while(p&
q)
if(p->
data)p=p->
elseif(p->
data==q->
{s=(LNode*)malloc(sizeof(LNode));
data=p->
data;
r->
r=s;
p=p->
q=q->
elseq=q->
r->
C=C->
returnC;
10.设有一个双向链表,每个结点中除有prior、data和next域外,还有一个访问频度freq域,在链表被起用之前,该域的值初始化为零。
每当在链表进行一次Locata(L,x)运算后,令值为x的结点中的freq域增1,并调整表中结点的次序,使其按访问频度的非递增