软考程序员2021年C语言链表案例题解答
设有头指针为 head 且不含有头结点的单链表,用来存储一个非递减有序的元素序列,如图4-1所示。
函数insertList(LinkList head, ElemType x)的功能是为元素x创建结点并将其插入到头指针为 head且不含头结点的单链表中,并保持表中元素非递减有序排列的特点,最后返回头指针。
【C代码】
typedef struct LNode * PtrToNode;typedef int ElemType;struct LNode {ElemType elem;/*结点数据*/PtrToNode next;/*指向后继结点的指针*/}typedef PtrToNode LinkList;LinkList insertList (LinkList head, ElemTy pe x){PtrToNode s;s =(PtrToNode ) malloc((1));if(!s) return head;//结点创建失败s->elem= x;
s->next =NULL;
if(! head){ //插入x之前单链表为空
(2)
return head;
}
if(x<head->elem){
//x小于单链表中的最小元素
(3)_;
head=s;
return head;
}
PtrToNode pre, p;
pre = head; p = head->next;while (p &&x>p->elem){
(4);
(5):
}
s->next =p;
表中
//将新结点插入单链
pre->next= (6) ;
return head;}参考答案:
(1)sizeof(struct LNode)
(2) head=s
(3) s->next = head 或(*s).next = head (4)pre=p
(5)p=p->next
(6)s
所属知识点:
C程序设计>C程序设计
解析:
本题考查C程序中的指针应用及运算。若单链表(head为头指针)不含头结点,则表为空时头指针用空指针表示。
根据结点类型的定义,若指针 p指向表中某结点,则p->elem表示结点中的数据域(p->elem是一个变量),p->next表示结点中的指针域,其实质是一个指针变量。
空(1)所在语句申请新元素的结点空间,每个结点所需的内存空间大小在运行时由系统分配,由于需考虑对齐因素,同时考虑可移植性,应该用sizeof进行计算而不是由程序员直接指定,因此空(1)处应填入"sizeof (struct LNode)"。
当单链表为空时插入新结点s,就需要修改头指针的值,因此应将头指针head设置为指向新结点,即空(2)处应填入"head = s"。若单链表不为空且新插入的结点要放在第一个结点之前,如图4-2所示,则需将新结点链接到链表中,即空(3)处应填入"s->next = head"(将s所指结点链接到链表中),然后更新头指针head 的指向。

下面代码的功能是在链表中查找待插入结点的位置,其中p所指结点称为当前结点,将其与新插入元素进行比较,循环条件为"p&& x>p->elem"表示p所指结点存在(即p是下面代码的功能是在链表中查找待插入结点的位置,其中p所指结点称为当前结点,将其与新插入元素进行比较,循环条件为"p&& x>p->elem"表示p所指结点存在(即p是非空指针),并且x大于当前元素,那么就要继续查找。pre的作用是记下p所指结点的前驱结点,一旦找到插入位置,此时x<=p->el em或p所指结点不存在,都需要修改pre的指针域,以将新结点接入链表。在查找过程中通过运算"p= p->next"修改变量p,使其能实现对链表中元素的遍历。
在循环中修改p之前,应该更新pre的值,使得两者保持前驱和后继关系,因此空(4)应填入"pre =p",空(5)应填入"p-p->nex t"。
找到新结点的插入位置后,需要修改指针将新结点接入链表中,操作"s->next=p"已经实现了第一步操作,如图4-3所示。显然在将x接入ej之后,需要的操作为"pre->next =s;",即空(6)处应该填入"s"。

