数据结构部分习题答案,答案基本是网上的标准答案,注释是学习过程中本人的标注,可以直接复制使用
2.11
设顺序表va中的数据元素递增有序。试写一算法,将x插入到顺序表的适当位置上,以保持该表的有序性。
Status Listinsert_order(SqList& va, Elemtype x) {
if (va.length == va.listsize) return (OVERFLOW);//先判断一下能否将x插入
else {
i = va.length - 1; //记录i可以移动的次数,例如线性表长度为5,那么i可以往前移四个
while (i >= 0 && x < va.elem[i]) i--; //同时满足这两个条件便确定了x要插入哪里
for (j = va.length - 1; j >= i + 1; j--) a.elem[j + 1] = a.elem[j];//将x后面的元素全部右移一位
a.elem[i + 1] = x//将x插入
a.length++//表的长度随之加一
return OK;
}
}//2.11
2.12
设和均为顺序表,和分别为和中除去最大共同前缀后的子表。若空表,则;若=空表,而空表,或者两者均不为空表,且的首元小于的首元,则;否则。试写一个比较,大小的算法。
Status Comparation_AB(SqList& A, SqList& B) {//就像是注意中说的那样,它给介绍前缀是没有意义的,因为去掉相同的部分还是不去掉对AB两个表的比较是没有区别的
int i, j, k//i用于循环比较,j用于确定循环次数,k用于返回结果
j = (A.length > B.length) ? A.length : B.length;//用于遍历每一个元素
for (i = 0; i < j; i++) {
if (A.elem[i] > B.elem[i]) k = 1;
if (A.elem[i] < B.elem[i]) k = -1;
}
if (A.length == B.length) k = 0;
return k;// 1说明A比B大,-1说明A比B小,0说明AB相等 另外我没有搜到,假如B的长度为5时,B.elem[6]等于0吗,还请老师解惑!
}//2.12
2.14
试写一算法在带头结点的单链表结构上实现线性表操作Length(L)。
int LENGTH(LinkList L) {
int k;//k用于记录长度
for (k = 0, p = L; p->next; p = p->next) k++;//只要p->next不为空,继续循环
return k;//返回链表长度
}//2.14
2.19
已知线性表中的元素以值递增有序排列,并以单链表作存储结构。试写一高效的算法,删除表中所有值大于mink且小于maxk的元素(若表中存在这样的元素),同时释放被删结点空间,并分析你的算法的时间复杂度(注意,mink和maxk是给定的两个参变量,它们的值可以和表中的元素相同,也可以不同)。
Status Delete_List(LinkList& L, ElemType mink, ElemType maxk) {
LinkList p, q, pp = NULL;//pp作为p的前驱
if (mink > maxk) return ERROR;//在这个范围内删除元素的先决条件应该是满足左值大于右值
p = L;
pp = p;
p = p->next;//pp指向头结点,pp的next指向p
while (p && p->data < mark) //因为表是以值递增排序的,思路是在p指到比mark还大的元素之后或指到链表末尾时将循环结束 ,在这之前进行删除
{
if (p->data <= mink) {//还没遍历到该删除的范围,指针后移继续比较,且删除的区间是一个开区间,所以等于依然向后移动
pp = p;
p = p->next;
}
else {//遍历到了要删除的范围,将元素删除
pp->next = p->next;
q = p;
p = p->next;//用于删除 p所指的元素
free(q);//最后释放存储空间
}
}
return OK; //时间复杂度为O(n^2)
}//2.19
2.21
试写一算法,实现顺序表的就地逆置,即利用原表的存储空间将线性表逆置为。
Status ListOppose(SqList& L) {
ElemType temp;//交换元素时使用的一个中间变量
for (int i = 0; i < L.length / 2; i++) {//边界分析知,i <= L.length也可以
x = L.elem[i];
L.elem[i] = L.elem[L.length - 1 - i];
L.elem[L.length - 1 - i] = x; //将中点两端对应位置的元素逆置,注意与i对称的元素是length-i-1
}
return OK;
}//2.21
2.22
试写一算法,对单链表实现就地逆置。
Status LinkListOppose(Linklist& L) {
Linklist p, q, r;
p = L->next;
q = p->next;
r = q->next; //q为p的后继,r为q的后继,这样便于指针向下运行以及节点插入
p->next = NULL;//先把第一个元素断开,构成一个新表
while (r->next) {
q->next = p;
p = q;
q = r;
r = r->next;//从头结点开始,依次把元素插入到新表的表头
}
q->next = p;
s->next = q;
L->next = r;
} //2.22
2.24
假设有两个按元素值递增有序排列的线性表A和B,均以单链表作存储结构,请编写算法将A表和B表归并成一个按元素值递减有序(即非递增有序,允许表中含有值相同的元素)排列的线性表C,并要求利用原表(即A表和B表)的结点空间构造C表。
Status ListMixOppose(Linklist& A, Linklist& B, Linklist& C) {
Linklist pa, qa, pb, qb;
pa = A; pb = B;
qa = pa; qb = pb;
pa = pa->next; pb = pb->next;//将qa,qb分别作为pa,pb的前驱
qa->next = NULL;
C = A;//因为题目要求要利用原表,这里利用A表,即用A的头结点代替操作C,A->next即用在C表进行元素的插入
while (pa && pb) {//同时对AB进行遍历
if (pa->data < pb->data) {//因为是按值递减存放的,所以如果A中的值小于B中的值,则取A中的元素
qa = pa;
pa = pa->next;
qa->next = A->next;
A->next = qa;
}
else {//如果A中的值大于B中的值,则取B中的元素,等于取谁都行,这里取B
qb = pb;
pb = pb->next;
qb->next = A->next;
A->next = qb; //将元素接到A->next上,即为C上
}
}
while (pa) {
qa = pa;
pa = pa->next;
qa->next = A->next;
A->next = qa;//如果A还有元素,把A所有元素接到C上
}
while (qb) {
qb = pb;
pb = pb->next;
qb->next = A->next;
A->next = qb;//如果B还有元素,把B所有元素接到C上
}
pb = B; free(pb);//将没用的B表头释放,这里新的A表即为所要的C表
return OK;
} //2.24
2.25
假设以两个元素依值递增有序排列的线性表A和B分别表示两个集合(即同一表中的元素值各不相同),现要求另辟空间构成一个线性表C,其元素为A和B中元素的交集,且表C中的元素有依值递增有序排列。试对顺序表编写求C的算法。
Status ListCross_Sq(SqList& A, SqList& B, Sqlist& C) {
int i = 0, j = 0;
while (i < A.length && j < B.length) {//这样的判断条件与上题不同,这样就可以充分遍历两个表,而上一题只能遍历其中一个
if (A.elem[i] < B.elem[j]) i++;
else if (A.elem[i] > B.elem[j]) j++;//AB哪个小就向后移一位
else {//AB相等了,就取这个元素到C中
ListInsert_sq(C, K, A.elem[i]);
i++; j++; //别忘了还得继续向下移一位
}
}
return OK;
}//2.25
2.26
要求同2.25题。试对单链表编写求C的算法。
Status ListCross_L(LinkList& A, LinkList& B, LinkList& C)
{
LinkList pa, pb, qa, qb, pc, pt;//其中pt是ptemp的简写,目的是完成元素的替换
pa = A;
pb = B;
qa = pa;
qb = pb;//qa,qb分别保存pa,pb的前驱指针
pa = pa->next;
pb = pb->next;//以上操作都与2.24一致,但由于要另辟空间开新表,所以单独建立一个指针指向C的表头
pc = C;
while (pa && pb) {//目的为遍历A或B
if (pa->data < pb->data) {//如果A中的元素比B小,那么A向后移一位
pt = pa;
pa = pa->next;
qa->next = pa;
free(pt);//因为AB中的元素都是递增有序排列的,所以一旦A的值比B的值小,那么以后也不会出现和这个值相等的元素了,故直接释放这个空间即可
}
else
if (pa->data > pb->data) {//如果A中的元素比B大,那么B向后移一位
pt = pb;
pb = pb->next;
qb->next = pb;
free(pt);//道理与上一个if类死
}
else {//如果相等,就把这个元素拿出来放到C中
qa = pa;//pa值先赋给qa
pa = pa->next;
pb = pb->next;//AB都向下一位
qa->next = pc->next;//将qa的next指向pc的next
pc->next = qa;//pc的next指回qa将元素接上
pc = pc->next;//pc向下移一位以用于后续连接
}
}
while (pa) {//当A表还有内容的时候,因为B表已经被遍历完,所以两表中不可能再有元素相等了,故直接释放即可
pt = pa;
pa = pa->next;
qa->next = pa;
free(pt);
}
while (pb) {//B中还有内容,就把B剩下的内容删除
pt = pb;
pb = pb->next;
qb->next = pb;
free(pt);
}
pa = A;
free(pa);
pb = B;
free(pb);//最后把AB空间全部释放,仅保留C
return OK;
}//2.26
2.31
假设某个单向循环链表的长度大于1,且表中既无头结点也无头指针。已知s为指向链表中某个结点的指针,试编写算法在链表中删除指针s所指结点的前驱结点。
Status ListDelete_Advanced(LinkList& s)
{
LinkList p, q;
if (s == s->next) return ERROR;//如果这个单向循环链表的长度为1,那么不符合题意
q = s;
p = s->next;//q是p的前驱
while (p->next != s) {
q = p;
p = p->next;//依次向下移一位,直到p->next指的正好是s(相当于指针走了一圈)
}
q->next = p->next;//没想明白为什么不直接释放p,也没有搜到,上课还要询问老师
free(p);//将前驱节点释放
return OK;
}//2.31
2.33
已知由一个线性链表表示的线性表中含有三类字符的数据元素(如:字母字符、数字字符和其他字符),试编写算法将该线性表分割为三个循环链表,其中每个循环链表表示的线性表中均只含一类字符。
Status ListDivideInto3CL(LinkList& L, LinkList& s1, LinkList& s2, LinkList& s3)//L为要处理的表,把三种类型的元素放到s1,s2,s3中
{
LinkList p, q, pt1, pt2, pt3;
p = L->next;
pt1 = s1;
pt2 = s2;
pt3 = s3; //pt1,pt2,pt3分别指s1,s2,s3
while (p) {//采用一个大的while循环将L全部遍历
if (p->data >= '0' && p->data <= '9') {//先把数字挑出来
q = p;
p = p->next;
q->next = pt1->next;
pt1->next = q;
pt1 = pt1->next;//以上操作与2.26操作一致,都是取出原表中某个元素插入到新链表
}
else
if ((p->data >= 'A' && p->data <= 'Z') ||
(p->data >= 'a' && p->data <= 'z')) {//再把字母挑出来
q = p;
p = p->next;
q->next = pt2->next;
pt2->next = q;
pt2 = pt2->next;//同样的插入新链表操作
}
else {//剩下的其他字符
q = p;
p = p->next;
q->next = pt3->next;
pt3->next = q;
pt3 = pt3->next;
}
}
q = L;
free(q);//最后把遍历完的L释放
return OK;
}//2.33
2.41
试以循环链表作稀疏多项式的存储结构,编写求其导函数的方法,要求利用原多项式中的结点空间存放其导函数多项式,同时释放所有无用结点。
Status PolyDifferential(LinkedPoly& L)
{
LinkedPoly p, q, pt;
q = L;
p = L->next;//q是p的前驱
while (p != L) {//这个大while循环遍历了L元素
if (p->data.exp == 0) {//目的是清除释放无用节点
pt = p;//pt先指向p
p = p->next;
q->next = p;//向后移一位
free(pt);//再释放这个节点
}
else {//对有用的节点进行操作
p->data.coef = p->data.coef * p->data.exp;//系数等于原系数乘指数
p->data.exp--;//将指数减一
q = p;
p = p->next;//向后移一位
}
}
return OK;
}//2.41