一、集合求差集
题目:已知集合A和B的元素分别用不含头结点的单链表存储,函数difference()用于求解集合A与B的差集,并将结果保存在集合A的单链表中。
例如,若集合A = { 5,10,20,15,25,30 },集合B = { 5,15,35,25 },完成计算后A = { 10,20,30 }。
链表结点的结构类型定义如下:
struct node
{
int elem;
node* next;
};
请完成函数void difference(node** LA, node* LB);
如图所示,题目要求求出差集,即是把相同元素去掉,结果保存在A单链表内即可。
方法:
我们选择用两个while循环遍历这两个单链表,用prev和del存储相应的保存删除后节点能连接起来的结点(防止删除结点后找不到它下一个结点)和待删除的结点,pA和pB分别用来遍历这两个单链表,所以根据思路我们写下如下代码。
代码如下:
void difference(node** LA, node* LB)
{
if (NULL == LB&&NULL == LA&&*LA == NULL)
return;
node* pA = *LA;
node* pB = LB;
node* prev = NULL;
node* del = NULL;
while (pA)
{
pB = LB;
while (pB&&pA->elem != pB->elem)
pB = pB->next;
if (pB)//pB->elem==pA->elem
{
if (!prev)
*LA = pA->next;
else//第一个结点一定相等,程序走的是上面步骤,此时prev==NULL
prev->next = pA->next;
del = pA;
pA = pA->next;
delete del;
}
else//pB为空或者不相等
{
prev = pA;
pA = pA->next;
}
}
}
测试代码与运行结果:
void My_Printf(node* L)
{
cout << "链表为:";
node*cur = L;
while (cur)
{
cout << cur->elem << ",";
cur = cur->next;
}
cout << endl;
}
int main()
{
node*n1 = new node(5);
node*n2 = new node(10);
node*n3 = new node(20);
node*n4 = new node(15);
node*n5 = new node(25);
node*n6 = new node(30);
node*m1 = new node(5);
node*m2 = new node(15);
node*m3 = new node(35);
node*m4 = new node(25);
n1->next = n2;
n2->next = n3;
n3->next = n4;
n4->next = n5;
n5->next = n6;
My_Printf(n1);
m1->next = m2;
m2->next = m3;
m3->next = m4;
My_Printf(m1);
difference(&n1, m1);
My_Printf(n1);
return 0;
}
二、集合求并集
根据以上代码我们便想到本题的一个变形,两个集合用链表存储,求出这两个集合的并集。
方法既是用一个node存储需要插入的结点再用两个循环遍历即可。
但要保证两个链表有序,为了简便,我在测试的时候直接用有序的方法插入结点,没有写排序函数。
代码如下:
void same(node** LA, node* LB)
{
if (*LA == NULL)
{
*LA = LB;
return;
}
if (LB == NULL)
{
return;
}
//进行插入节点
node dummy(-1);
node* pre = &dummy;
node* pA = *LA;
node* pB = LB;
while (pA&&pB)
{
while (pA->elem == pB->elem)
{
pre = pA;
pA = pA->next;
pB = pB->next;
}
if (pA&&pB&&pA->elem < pB->elem)
{
pre = pA;
pA = pA->next;
}
else if (pA&&pB)
{
//插入操作
node * temp = new node(pB->elem);
temp->next = pA;
pre->next = temp;
pB = pB->next;
}
}
if (pA == NULL)
{
pre->next = pB;
}
//死循环,这样写有问题
//if (*LA == NULL&&LB == NULL&&LA == NULL)
// return;
//node* pA = *LA;
//node* pB = LB;
//node* prev = new node(0);
//while (pA)
//{
// while (pB->elem == pA->elem&&pB)
// pB = pB->next;
// if (pB)//pB存在,不相等
// {
// prev = pB;
// prev->next = NULL;
// prev->next = pA->next;
// pA->next = prev;
// //prev = pA->next;
// //prev->next = NULL;
// //pB->next = prev;
// }
// pB = LB;
// pA = pA->next;
//}
}
测试代码及运行结果
#include <iostream>
using namespace std;
struct node
{
int elem;
node* next;
node(int data)
:elem(data)
,next(NULL)
{};
};
void My_Printf(node* L)
{
cout << "链表为:";
node*cur = L;
while (cur)
{
cout << cur->elem << ",";
cur = cur->next;
}
cout << endl;
}
int main()
{
node*n1 = new node(5);
node*n2 = new node(10);
node*n3 = new node(15);
node*n4 = new node(20);
node*n5 = new node(25);
node*n6 = new node(30);
node*m1 = new node(5);
node*m2 = new node(15);
node*m3 = new node(25);
node*m4 = new node(35);
n1->next = n2;
n2->next = n3;
n3->next = n4;
n4->next = n5;
n5->next = n6;
My_Printf(n1);
m1->next = m2;
m2->next = m3;
m3->next = m4;
My_Printf(m1);
same(&n1, m1);
My_Printf(n1);
return 0;
}