【数据结构01】线性表的相关习题和解答(附加注释)

数据结构部分习题答案,答案基本是网上的标准答案,注释是学习过程中本人的标注,可以直接复制使用

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
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值