一、问题描述
编写程序实现两个有序表的交和差,令 L1=(x1, x2, x3, ..., xn),L2=(y1, y2, y3, ..., yn),它们是两个线性表,采用带头结 点的单链表存储,请先实现单链表存储两个链表,再完成如下功能: (1)sort:将单链表的所有结点按照数据域进行递增排序,构 造成有序单链表; (2)interSect:求两个有序单链表的交集,即C = A B,C 中 包含两个集合中重复出现的所有元素; (3)subs:求两个有序单链表的差集,即,C = A− BC 中包含所 有属于 A 但不属于 B 的元素。
二、问题解决
#include <stdio.h>
#include <cstdlib>
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LinkNode;
void CreateList(LinkNode *&L,ElemType a[],int n)
{
LinkNode *s,*r;
L=(LinkNode *)malloc(sizeof(LinkNode));
r=L;
for(int i=0;i<n;i++)
{
s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=a[i];
r->next=s;
r=s;
}
r->next=NULL;
}
LinkNode *InitList()
{
LinkNode *L=(LinkNode *)malloc(sizeof(LinkNode));
L->next=NULL;
return L;
}
void DestroyList(LinkNode **L)
{
LinkNode *pre=*L,*p=(*L)->next;
while(p!=NULL)
{ free(pre);
pre=p;
p=pre->next;
}
free(pre);
*L=NULL;
}
void DispList(LinkNode *L)
{
LinkNode *p=L->next;
while(p!=NULL)
{
printf("%d",p->data);
p=p->next;
}
printf("\n");
}
void sort(LinkNode *L)
{
LinkNode *p,*pre,*q;
p=L->next->next;
L->next->next=NULL;
while(p!=NULL)
{
q=p->next; //q 保持结点后继
结点的指针
pre=L;
while(pre->next!=NULL&&pre->next->data<p->data)
pre=pre->next;
p->next=pre->next;
pre->next=p;
p=q; //扫描单链表余下结
点
} printf("递增排序结果为:");
}
void InterSect(LinkNode *L1, LinkNode *L2, LinkNode *L3)
{
LNode *p1, *p2, *p3; //生成三个 LNode 类型的指针
p1, p2 ,p3
p1 = L1->next; //p1 指向 L1 的首元结点
p2 = L2->next; //p2 指向 L2 的首元结点
p3 = L3; //p3 指向 L3 的头结点 (p3 用
来存放交集部分)
p3->next = NULL; //p3 的 next 域置空, 当前还
没有存放数据
while (p1&& p2)
{
if (p1->data < p2->data) //两个链表当前结点的数据域进
行比较,数据小的结点,就继续向后移动,指向下一个结点
{
p1 = p1->next;
}
else if (p1->data > p2->data)
{
p2 = p2->next;
}
else
{ //两个结点的数据域相同时
p3->next = p2; //就将 p3 结点的 next 域指向 p2
p1 = p1->next; //p1,p2 结点指向下一结点
p2 = p2->next;
p3 = p3->next; //p3 指向下一结点
}
}
printf("链表交集为:");
}
void Subs(LinkNode *L1, LinkNode *L2)
{
LinkNode *p1, *p2 ,*pre;
p1 = L1->next; p2 = L2->next;
pre= L1;
while (p1!= NULL&&p2!= NULL)
{
if (p1->data < p2->data)
{
pre=p1;
p1 = p1->next;
}
else if (p1->data > p2->data)
{
p2=p2->next;
}
else if(p1->data == p2->data)
{
pre->next = p1->next;//若 p1 和 p2 指向的数据域的
值相同则删去 L1 中该数据
p1=p1->next;
p2=p2->next;
}
}
printf("链表差集为:");
}
int main()
{
int a[]={5,2,1,6,8,9};
int b[]={3,9,5,6,7,4};
LNode *L1=(LNode*)malloc(sizeof(LNode));
int n=sizeof(a)/sizeof(a[0]);
CreateList(L1,a,n);
printf("L1 原链表为:");
DispList(L1);
sort(L1);
DispList(L1);
LNode *L2=(LNode*)malloc(sizeof(LNode));
int m=sizeof(b)/sizeof(b[0]);
CreateList(L2,b,m); printf("L2 原链表为:");
DispList(L2);
sort(L2);
DispList(L2);
LNode *L3=(LNode*)malloc(sizeof(LNode));
InterSect(L1,L2,L3);
DispList(L3);
Subs(L1,L2);
DispList(L1);
return 0;
}
三、代码分析
1、将单链表的所有结点按照数据域进行递增排序,只需要将遍历 一遍链表,判断前一个结点的数据域的值是否大于后继结点的 数据域的值,是则交换两结点。
2、 两个有序单链表的交集,设置三个指针 p1、p2、p3 开始时分 别指向 L1、L2、L3 的开始结点。循环进行以下判断和操作: 如果 p1 所指结点的值小于 p2 所指结点的值,则 p 后移一 位; 如果 p2 所指结点的值小于 p1 所指结点的值,则 q 后移一位; 如果两者所指结点的值相同,则将 p1 或 p2 所指结点的值放在 L3 中,同时 p3 后移一位。 最后,p1 与 p2 任一指针为 NULL 时算法结束。
3、 求两个有序单链表的差集,设置两个指针 p1、p2 开始时分别 指向 L1 和 L2 的开始结点。循环进行以下判断和操作: 如果 p 所指结点的值小于 q 所指结点的值,则 p 后移一位; 如果 q 所指结点的值小于 p 所指结点的值,则 q 后移一位; 如果两者所指结点的值相同,则删除 p1 所指结点。 最后,p 与 q 任一指针为 NULL 时算法结束。
标签:p2,结点,p1,next,单链,应用,L1,数据结构,LinkNode From: https://blog.csdn.net/weixin_75253037/article/details/141256057