头歌实训:拆分单链表
文章目录
任务描述
本关任务:假设有一个带头结点的单链表L=(a1b1a2b2,…,an,bn)。设计一个算法将其拆分成两个带头结点的单链表L1和L2:L1=(a1,a2,…,an),L2=(bn,bn−1,…,b1)要求L1使用L的头结点。

相关知识
为了完成本关任务,你需要掌握:1.单链表的基本概念,2.如何创建、遍历单链表。
单链表的基本概念
单链表是线性表的链式存储结构实现。如下图所示:

单链表的头结点
为了操作方便,有时候会在单链表第一个元素结点的前面增加一个附加头结点,如下图所示:

单链表增加一个头结点的优点如下:
首结点的操作和表中其他结点的操作相一致,无需进行特殊处理;
无论链表是否为空,都有一个头结点,因此空表和非空表的处理也就统一了。
单链表结点类型定义
单链表中结点类型LinkNode的定义如下:
typedef struct LNode //定义单链表结点类型
{
ElemType data; //存储元素
struct LNode *next; //指向后继结点
} LinkNode;
单链表的特点
单链表的特点:当访问过一个结点 p 后,只能接着访问它的后继结点,而无法访问它的前驱结点。
单链表插入一个结点
插入操作:将值为x的新结点s插入到p结点之后。
特点:只需修改相关结点的指针域,不需要移动结点。
插入操作如下图所示:

单链表删除一个结点
删除操作:删除p结点之后的一个结点。
特点:只需修改相关结点的指针域,不需要移动结点。
删除操作如下图所示:

删除操作的语句如下:
p->next = p->next->next;
创建单链表
头插法建立单链表
从一个空表开始,创建一个头结点。
依次读取线性表中的元素,生成新结点s。
将新结点插入到当前链表的表头上,直到结束为止。
头插法建立单链表如下图所示:

建表语句如下:
void CreateListF(LinkNode *&L, ElemType a[], int n)
{
LinkNode *s;
L = (LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next = NULL;
for (int i = 0; i < n; i++)
{
s = (LinkNode *)malloc(sizeof(LinkNode)); //创建新结点s
s->data = a[i];
s->next = L->next; //将结点s插在原开始结点之前,头结点之后
L->next = s;
}
}
尾插法建立单链表
从一个空表开始,创建一个头结点。
依次读取线性表中的元素,生成新结点s
将新结点插入到当前链表的表尾上,直到结束为止。
尾插法建立单链表如下图所示:

建表语句如下:
void CreateListR(LinkNode *&L, ElemType a[], int n)
{
LinkNode *s, *r;
L = (LinkNode *)malloc(sizeof(LinkNode)); //创建头结点
L->next = NULL;
r = L; //r始终指向终端结点,开始时指向头结点
for (int i = 0; i < n; i++)
{
s = (LinkNode *)malloc(sizeof(LinkNode)); //创建新结点s
s->data = a[i];
r->next = s; /


313

被折叠的 条评论
为什么被折叠?



