4.集合的操作

问题描述 :
输入A、B、C、D四个集合(集合中无重复元素,且元素值都大于0),分别存储在不带头结点的链表中。

本程序先将四个集合执行以下操作:
1.对A、B、C、D分别进行升序排序;(该功能已实现,见函数sort)。

2.做A=A+B操作:先执行两个有序链表A和B的合并,并仍然保持有序,结果存储在A中,然后删除重复元素;(该功能已实现,见函数merge和purge)。

3.做A=A-C操作:将C中出现的元素从A中删除;(该功能已实现,见函数subtract)。

4.对D中出现的元素,逐一到A中查询:

如果在A中存在,则从A中删除
如果在A中不存在,则将元素添加到A中,并保持链表A有序。

请编写函数fun的函数体实现本功能。

5.输出集合A中的元素。(该功能已实现,见函数displayLink)。

需要编写的函数的原型如下:

struct student* fun(struct student* L1, struct student* L2)

形参:

L1:传入的第一个集合,程序中将传入A集合的链表头指针

L2:传入的第二个集合,程序中将传入D集合的链表头指针

扫描二维码关注公众号,回复: 11666905 查看本文章

返回值:

返回第一个集合的链表的头指针

程序部分代码如下:

#include <iostream>
using namespace std;
struct student
{
    
    
 	int  num;
 	student  *next;
};
//从键盘读入数据创建链表,新结点插入到尾部
student *createByTail()
{
    
    
	 student *head;
	 student *p1,*p2;
	 int n;
	 n=0;
	 p1 = new student;
	 //p2 = new student;
	 cin>>p1->num;
	 head=NULL;  //首先置链表为空链表
	 while(p1->num!=-1)    //num为-1,意味着用户输入结束
	 {
    
    
	  	n=n+1;
	  	if(n==1)            //创建第一个结点
	   		head=p1;
	  	else
	   		p2->next=p1;
	  		p2=p1;            //p2始终指向最后一个结点(即尾指针)
	  	p1 = new student;;//p1指向新结点
	    cin>>p1->num;
	 }
	 p2->next=NULL;  //最后一个结点的next赋值为NULL
	 return head;
}

//输出链表中的信息(num)
void  displayLink(struct student *head)
{
    
    
	 student *p;
	    p=head;
	 cout<<"head-->";
	 while(p!= NULL)
	 {
    
    
	  cout<<p->num<<"-->";
	  p=p->next;
	 }
	 cout<<"tail"<<endl;
}

//将一个节点插入链表中并使链表仍然有序
student *insertNodeInOrder(student *head,student *stu) {
    
    
	student *p0,*p1,*p2;
	p1 = head;
	p0 = stu;
	//空链表
	if(head == NULL) {
    
    
		p0->next = head;
		head = p0;
	}
	else {
    
    
		//查找插入位置,p2指向p1的前驱
		while(p0->num > p1->num && p1->next != NULL) {
    
    
			p2 = p1;
			p1 = p1->next;	
		}
		//如果上面的while循环是因第一个条件退出的,则将p0插到p2后面
		if(p0->num <= p1->num) {
    
    
			if(p1 == head) {
    
    
				head = p0;
			}
			else {
    
    
				p2->next = p0;
			}
			p0->next = p1;
		}
		//while循环是因p1->next == NULL结束的,说明p0->num比当前链表所有链表节点的值都要大
		else {
    
    
			p1->next = p0;
			p0->next = NULL;
		}
	}
	return head;
}

//对链表进行升序排序
student *sort(student *head) {
    
    
	student *p = head,*node;
	head = NULL;	//将链表置为空
	while(p) {
    
    
		node = p;
		p = p->next;
		head = insertNodeInOrder(head,s);
	}
	return head;
}

//合并两个有序链表,使之任然有序
student *merge(student *La,student *Lb) {
    
    
	student *pb,*node;
	pb = Lb;
	while(pb) {
    
    
		node = pb;
		pb = pb->next;
		La = insertNodeInOrder(La,node);
	}
	return La;
}

//删除一个有序链表中重复值的节点
void purge(student *head) {
    
    
	student *p,*q;
	//空链表或者只有一个节点的链表直接返回
	if(head == NULL || head->next == NULL) {
    
    
		return;
	}
	
	p = head;
	while(p->next) {
    
    
		//相邻两个节点的值相等,删除后一个节点
		if(p->num == p->next->num) {
    
    
			q = p->next;
			p->next = q->next;
			delete q;
		}
		else {
    
    
			p = p->next;
		}
	}
}

//做A=A-C操作:将C中出现的元素从A中删除
student *subtract(student *La,student *Lb) {
    
    
	student *pa,*pb = Lb;
	student *pre = NUll;	//pre指向pa的前驱
	while(pb) {
    
    
		pa = La;
		while(pa != NULL && pa->num != pb->num) {
    
    
			pre = pa;
			pa = pa->next;
		} 
		if(pa != NULL) {
    
    	//在A中找到了与当前B中相等的元素
				
			if(pa == La) {
    
    	//要删除的是头节点
				La = La->next;
				delete pa;
			}
			else {
    
    
				pre->next = pa->next;
				delete pa;
			}
		}
		pb = pb->next;
	}
	return La;
}
/*
	对D中出现的元素,逐一到A中查询:
	如果在A中存在,则从A中删除
	如果在A中不存在,则将元素添加到A中,并保持链表A有序。
*/
student *fun(student *L1,student *L2) {
    
    
	struct student *p1,*p2 = L2;
	struct student *pre = NULL;	//pre为p1的前驱	
	while(p2) {
    
    
		p1 = L1;
		while(p1 != NULL && p1->num != p2->num) {
    
    
			pre = p1;
			p1 = p1->next;
		}
		if(p1 == NULL) {
    
    	//L1中没有这个元素
			student *node = new student;
			node->num = p2->num;
			L1 = insertNodeInOrder(L1,node);
			
		}
		else {
    
    
			if(p1 == L1) {
    
    	//要删除的元素为L1的头节点
				L1 = L1->next;			
			}
			else {
    
    
				pre->next = p1->next;
			}
			delete p1;
		}
		p2 = p2->next;
	}
	return L1;
}

int main()
{
    
    
    struct student *headA, *headB, *headC, *headD;
    int i=0,n;
    cin>>n;
	while( i<n)
    {
    
    
        headA=createByTail();//创建链表A
        headB=createByTail();//创建链表B
        headC=createByTail();//创建链表C
        headD=createByTail();//创建链表D
        headA = sort(headA);//链表A排序
        headB = sort(headB);//链表B排序
        headC = sort(headC);//链表C排序
        headD = sort(headD);//链表D排序

        headA = merge(headA, headB);//将链表B合并到链表A中
        purge(headA);//删除链表A中重复元素
        headA = subtract(headA, headC);//从链表A中减去链表C中元素
        headA=fun(headA, headD);//对链表A和链表D调用fun函数
        displayLink(headA);//输出链表A中的元素
        i++;
    }
    return 0;
}

输入说明 :
首先输入一行,包含一个整数N,表示共测试N组数据。
后面接着输入4*N行,每行为一个集合的元素。
每组数据的第1行为集合A的元素,第2行为集合B的元素,第3行为集合C的元素,第4行为集合D的元素。
每个集合的元素值都为大于0的整数,输入时,-1表示结束。

输出说明 :
输出的信息以head开头,以tail结尾,以“–>”分隔。如果是空链表,则直接输出“head–>tail”。具体见输出范例。

输入范例 :
2
3 5 8 10 15 9 -1
2 5 8 11 14 -1
2 5 10 -1
3 1 9 -1
3 5 8 10 15 9 -1
2 5 8 11 14 -1
2 5 10 -1
2 3 8 -1

输出范例 :
head–>1–>8–>11–>14–>15–>tail
head–>2–>9–>11–>14–>15–>tail

猜你喜欢

转载自blog.csdn.net/qq_37924213/article/details/108478419