第一题
问题
有一个递增非空单链表,设计一个算法删除值域重复的结点。比如{1,1,2,3,3,3,4,4,7,7,7,9,9,9经过删除后变成{1,2,3,4,7,9}。
解答
解法一:定义指针p指向起始结点。将p所指当前结点值域和其直接后继结点值域比较。如果当前结点值域等于后继结点值域,删除后继结点;否则p指向后继结点,重复以上过程,直到p的后继结点为空。
本题代码如下:
void delsl1(LNode *&L) { //L是指针且要改变因此用引用指针型
LNode *p = L->next,*q;
while(p->next! = NULL){
if(p->data == p->next->data) { //找到重复结点删除之
q = p->next;
p->next = q->next;
free(q);
}
else
p=p->next;
}
}
解法二:依次将原序列中每个连续相等子序列的第一个元素移动到表的前端,将剩余的
元素删除即可,即下图所示过程。
令p指向起始将结点。q从p的后继结点开始扫描,q每来到一个新结点的时候进行检测:当q->data等于p->data的时候,什么也不做,q继续往后走;当两者不相等的时候,p往后走一个位置,然后用q->data取代p->data。之后q继续往后扫描,重复以上过程。当q为空的时候,释放从p之后的所有结点空间。
void delsl2(LNode *&L) {
LNode *p = L->next,*q = L->next->next,*r;
while(q != NULL){
while(q != NULL&&q->data == p->data)
q = q->next;
if(q! = NULL) {
p = p->next;
p->data = q->data;
}
}
q = p->next;
p->next = NULL;
while(q != NULL) {
r = q;
q = q->next;
}
}
free(r);
}
第二题
问题
设计一个算法删除单链表L(有头结点)中的一个最小值结点。
解答
用p从头至尾扫描链表,pre指向*p结点的前驱,用minp保存值最小的结点指针,minpre指向minp的前驱。一边扫描,一边比较,将最小值结点放到minp中。
代码如下:
void delminnode(LNode *&L){
LNode *pre = L, *p = pre->next, *minp = p, *minpre = pre;
while(p != NULL) { //查找最小值结点minp以及前驱结点minpre
if(p->data < minp->data){
minp = p;
minpre = pre;
}
pre = p;
p = p->next;
}
minpre->next = minp->next; //删除*minp结点。
free(minp);
}
第三题
问题
有一个线性表,采用带头结点的单链表L来存储。设计一个算法将其逆置。要求不能建立新结点,只能通过表中已有结点的重新组合来完成。
解答
在前边讲过的算法基础中,提到过关与逆序的问题,那就是链表建立的头插法。头插法完成后,链表中的元素顺序和原数组中元素的顺序相反。这里我们可以将L中的元素作为逆转后L的元素来源,即将L->next设置为空,然后将头结点后的一串结点用头插法逐个插入L中,这样新的L中的元素顺序正好是逆序的。
代码如下:
void Reversel(LNode *&L) {
LNode *p = L->next,*q;
L->next = NULL;
while(p != NULL) { //p结点始终指向旧的链表的开始结点。
q = p->next; //q结点作为辅助结点来记录p的直接后继结点的位置。
p->next = L->next; //将p所指结点插入新的链表中。
L->next = p;
p = q;
//因为后继结点已经存入q中,因此p仍然可以找到后继
(即此时的新开始结点)。
}
}
第四题
问题
设计一个算法将一个头结点为A的单链表(其数据域为整数)分解成两个单链表A
解答
用指针p从头至尾扫描A链表,当发现结点data域为偶数的结点则取下,插入链表B中。要用头插法是用尾插法呢,因为题目要求保持原来数据元素的相对顺序,所以要用尾插法来建立B链表。
代码如下:
void split2(LNode *&A,LNode *&B) {
LNode *p, *q, *r;
B = (LNode*)malloc(sizeof(LNode)); //申请链表B的头结点
B->next = NULL;
//每申请一个新结点的时候,将其指针域next设置为NULL是个好习惯,这样可以避免很多因链表的终端结点忘记置NULL而产生的错误。
r = B;
p = A;
while(p->next != NULL) {
//p始终指向当前被判断结点的前驱结点,这和删除结点类似,因为取下一个结点,就是删除一个结点,只是不释放这个结点的内存空间而已。
if(p->next->data%2 == 0) { //判断结点的data域是否为偶数,是则从链表中取下
q = p->next; //q指向要从链表中取下的结点
p->next = q->next; //从链表中取下这个结点
q->next = NULL;
r->next = q;
r = q;
}
p = p->next; //p后移一个位置,即开始检查下一个结点。
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。