R6-4
参考答案:
void SplitList( LinkList a , LinkList *b , LinkList *c )
{
PNode pre = a;
PNode cur = a->next;
PNode b_tail = *b;//链表b尾指针
PNode c_tail = *c;//链表c尾指针
while(cur)
{
if (cur->data == 0)
{
pre = pre->next;//双双后移
cur = cur->next;
continue;//继续循环,而不跳出
}
pre->next = cur->next;
cur->next = NULL;//摘下链点
if (cur->data < 0)
{
b_tail->next = cur;//尾插法,挂在尾部
b_tail = cur;//交接一下尾部所在,交接棒赋值,等于后移尾指针
}
else if (cur->data > 0)
{
c_tail->next = cur;
c_tail = cur;
}
cur = pre->next;//重新回到A链表,继续循环
}
}
在一个带头结点的单链表A中,头指针为a,设计算法SplitList ( )将A分解为两个具有相同结构的链表B、C,其中B表的结点为A表中值为负数的结点,而C表的结点为A表中值为正数的结点(链表A的元素类型为整型,要求B、C表除了头结点可以新开辟空间外,其余结点均利用A表的结点,不得申请新的结点空间)最后要求遍历B,C链表。
带头结点的单链表结点定义如下:
typedef int DataType;
typedef struct Node
{
DataType data; // data域用于存储数据元素
struct Node *next; // next域用于存放指向其后继的指针
}LNode, *PNode, *LinkList; // LinkList为头指针
函数接口定义:
函数接口如下:
void SplitList( LinkList a , LinkList *b , LinkList *c );
其中 a
,*b
, *c
都是用户传入的参数。 a
是原始链表A的头指针,*b
和*c
是新链表B和C的头指针。
裁判测试程序样例:
#include<stdio.h>
#include<stdlib.h>
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* next;
}LNode, * PNode, * LinkList;
int InitLinkList(LinkList* head)
{ // 初始化单链表,开辟头结点
*head = (LinkList)malloc(sizeof(LNode));
if (!head)
{
printf("初始化链表错误!\n");
return 0;
}
(*head)->next = NULL;
return 1;
}
PNode LinkListInsert(LinkList h, int pos, DataType x)
{ // 在单链表h的第pos个位置插入x值的元素
PNode p = h, q;
int i = 0;
while (p && i < pos - 1)
{
p = p->next;
i++;
}
if (!p || i > pos - 1)
{
printf("插入位置不合法!\n");
return NULL;
}
q = (PNode)malloc(sizeof(LNode));
if (!q)
{
printf("不能生成新结点\n");
return NULL;
}
q->data = x;
q->next = p->next;
p->next = q;
return q;
}
void DestroyLinkList(LinkList h)
{ // 销毁单链表
PNode p = h->next;
while (h)
{
p = h;
h = h->next;
free(p);
}
}
void TraverseLinkList(LinkList h)
{ // 遍历单链表
PNode p = h->next;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int BnotinA(LinkList a, LinkList b)
{ // 判链表B的链点是否来自链表A
PNode pb = b->next;
PNode pa = a->next;
if (!pa)
{
return 1;
}
if (!pb)
{
return 1;
}
while (pa)
{
if ((DataType)pb != pa->data)
{
pa = pa->next;
continue;
}
return 0;
}
return 1;
}
// 本题要求函数
void SplitList(LinkList a, LinkList* b, LinkList* c);
int main()
{
LinkList aa, aa1, bb, cc;
DataType x;
char ch;
int pos = 1;
PNode pa = NULL;
InitLinkList(&aa);
InitLinkList(&aa1);
InitLinkList(&bb);
InitLinkList(&cc);
do
{
scanf("%d", &x); // 某些编译器要求此处改为scanf_s
pa = LinkListInsert(aa, pos, x);
if (pa != NULL)
{
LinkListInsert(aa1, pos, (DataType)pa);
}
pos++;
} while ((ch = getchar()) != '\n');
SplitList(aa, &bb, &cc);
if ((bb->next == NULL && BnotinA(aa1, cc) != 1) || (cc->next == NULL && BnotinA(aa1, bb) != 1))
{
printf("单链表B和C的链点来自于单链表A\n");
}
else if ((BnotinA(aa1, bb) != 1) && (BnotinA(aa1, cc) != 1))
{
printf("单链表B和C的链点来自于单链表A\n");
}
printf("单链表B是\n");
TraverseLinkList(bb);
printf("单链表C是\n");
TraverseLinkList(cc);
DestroyLinkList(aa);
DestroyLinkList(bb);
DestroyLinkList(cc);
return 0;
}
/* 你的代码写在此处 */
输入样例:
12 -9 45 87 -32 64 28 49 34 -42
输出样例:
单链表B和C的链点来自于单链表A
单链表B是
-9 -32 -42
单链表C是
12 45 87 64 28 49 34