数据结构—习题2.4 求两个递增链表的差集

1.问题描述

  • 已知两个链表L1和L2分别表示两个集合,其元素递增排列。请设计算法求出两个集合L1和L2的差集(即仅由在L1中出现而不在L2中出现的元素所构成的集合),并以同样的形式存储,同时返回该集合的元素个数。

2.题目分析

  • 求两个集合A和B的差集是指在A中删除A和B中共有的元素,即删除链表中的相应结点,所以要保存待删除结点的前驱,使用指针pre指向前驱结点。p1和p2分别是链表L1和L2的工作指针,初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表L1和L2均为到达表尾结点时,如果L1表中的元素小于L2表中的元素,pre置为L1表的工作指针p1,此表中当前结点指针后移,n++(n表示差集集合中元素的个数);如果L2表中的元素小于L1表中的元素,L2工作指针后移。相等时,删除L1共同的节点。(这里L1存放差集结果)
// 链表差集
void Difference(LinkList &L1, LinkList &L2, int &n)  // 差集的结果存储于单链表L1中,n是结果集合中元素个数,调用时为0
{
	LNode *p1, *p2, *pre, *u;
	p1 = L1->next;
	p2 = L2->next;  // p1和p2分别是链表L1和L2的工作指针,初始化为相应链表的第一个结点
	pre = L1;     // pre为L1中pa所指结点的前驱结点的指针

	while (p1&&p2)
	{
		if (p1->data < p2->data)
		{
			pre = p1;
			p1 = p1->next;
			n++;    // A链表中当前结点指针后移
		}        
		else if (p1->data > p2->data)
			p2 = p2->next;
		else
		{
			pre->next = p1->next;     // 处理A,B中元素值相同的结点,应删除
			u = p1;
			p1 = p1->next;
			delete u;     // 删除结点
		}
	}
}

​​​​​​3.代码实现

  • main.cpp
#include <iostream>

using namespace std;

typedef struct LNode
{
	int data;
	struct LNode *next;
}LNode, *LinkList;

int InitList(LinkList &L)
{
	L = new LNode;
	L->next = NULL;
	return 1;
}

void TraveList(LinkList L)
{
	LNode *p;
	p = L->next;

	while (p)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("\n");
}

// 尾插法建立链表
void CreateList(LinkList &L, int n)
{
	L = new LNode;
	L->next = NULL;
	LNode *r;
	r = L;
	for (int i = 0; i < n; i++)
	{
		printf("请输入链表第%d个元素的值:", i + 1);
		LNode *s;
		s = new LNode;
		scanf("%d", &s->data);
		s->next = NULL;
		r->next = s;
		r = s;
	}
}

// 链表差集
void Difference(LinkList &L1, LinkList &L2, int &n)  // 差集的结果存储于单链表L1中,n是结果集合中元素个数,调用时为0
{
	LNode *p1, *p2, *pre, *u;
	p1 = L1->next;
	p2 = L2->next;  // p1和p2分别是链表L1和L2的工作指针,初始化为相应链表的第一个结点
	pre = L1;     // pre为L1中pa所指结点的前驱结点的指针

	while (p1&&p2)
	{
		if (p1->data < p2->data)
		{
			pre = p1;
			p1 = p1->next;
			n++;    // A链表中当前结点指针后移
		}        
		else if (p1->data > p2->data)
			p2 = p2->next;
		else
		{
			pre->next = p1->next;     // 处理A,B中元素值相同的结点,应删除
			u = p1;
			p1 = p1->next;
			delete u;     // 删除结点
		}
	}
}
	
int main()
{
	LinkList L1, L2;

	if (InitList(L1))
	{
		printf("L1初始化成功!\n");
	}
	else
	{
		printf("L1初始化失败!\n");
	}

	if (InitList(L2))
	{
		printf("L2初始化成功!\n");
	}
	else
	{
		printf("L2初始化失败!\n");
	}

	printf("请输入L1的长度:");
	int n1;
	scanf("%d", &n1);
	CreateList(L1, n1);
	TraveList(L1);

	printf("请输入L2的长度:");
	int n2;
	scanf("%d", &n2);
	CreateList(L2, n2);
	TraveList(L2);

	int n = 0;
	Difference(L1, L2, n);
	printf("链表差集:\n");
	TraveList(L1);
	printf("链表中元素个数为:%d\n", n);

	system("pause");

	return 0;
}
  • 运行结果

猜你喜欢

转载自blog.csdn.net/qq_22847457/article/details/94163450