- 内容:如果以单链表表示集合,假设集合A用单链表LA表示,集合B用单链表LB表示,设计算法求两集合的差,即A-B。用C语言实现程序解决问题。
-
算法分析:由集合运算的规则可知,集合的差A-B中包含所有属于集合A而不属于集合B的元素。具体做法是,对于集合A中的每一个元素,在集合B的链表LB中进行查找,若存在与A中元素相同的元素,则在LA中将其删除。
首先需要定义链表结点的结构类型,然后选择使用两个while循环遍历这两个单链表,用pre和q存储相应的结点和待删除的节点,pa和pb分别用来遍历这两个单链表。
编写测试代码,假设A集合为{1,2,3,4,5,6},B集合为{1,2,3,4},则A-B集合为{5,6}。
-
概要设计:使用C语言,其中设置了以下函数
-
程序运行流程图如下:
-
测试(设计测试用例或测试代码的设计与实现,测试结果截屏)测试案例如图
- 测试结果如图所示:
测试结果显示输入字母求差集存在问题,故进行调试代码。测试代码时,当输入字母形式的集合时,会出现错误,显示“a was not declared in this scope”,主要原因在于定义data的数据类型时,定义的是int型,当输入字符型常量时,程序就会报错,因此将int data;改为char data;这时当输入字母集合时,程序正常运行,输出的是字母的ASCII码值,调试成功如图所示
源代码如下:
#include#include using namespace std; //定义链表结点的结构类型 struct Node { int elem; Node*next; Node(char data) :elem(data) , next(NULL) {} }; //利用函数完成集合的差运算 void Different(Node**LA, Node*LB) { Node*pa = *LA; //遍历A链表 //Node*pb = LB;//遍历B链表 Node *pre = NULL;//用来保存删除后结点能连接起来 Node*q;//待删除的结点 while (pa) { Node*pb = LB; while (pb&&pa->elem != pb->elem) pb = pb->next;// if (pb)//两个结点的值相等 { if (!pre) { *LA = pa->next;//指向下一个结点 } else//第一个结点相等 { pre->next = pa->next;//指向相等结点的后一个 } q = pa;//释放结点 pa = pa->next; free(q); } //链表B已遍历完 else { //更新结点的位置 pre = pa; pa = pa->next; } } } void Printf(Node*L) { Node*cur = L; while(cur) { cout << cur->elem << " "; cur = cur->next; } cout << endl; } //测试代码 void Test() { Node*n1 = new Node('a'); Node*n2 = new Node('b'); Node*n3 = new Node('c'); Node*n4 = new Node('d'); Node*n5 = new Node('e'); Node*n6 = new Node('f'); n1->next = n2; n2->next = n3; n3->next = n4; n4->next = n5; n5->next = n6; cout << "链表A" << endl; Printf(n1); Node*m1 = new Node('a'); Node*m2 = new Node('e'); Node*m3 = new Node('f'); Node*m4 = new Node('g'); m1->next = m2; m2->next = m3; m3->next = m4; cout << "链表B" << endl; Printf(m1); cout << "链表的差集" << endl; Different(&n1, m1); Printf(n1); } int main() { Test(); system("pause"); return 0; }



