你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

(C语言)数据结构-线性表之单链表操作(交集,并集,差集,排序,拼接,去重)

2021-11-27 21:46:36

1.头文件和数据类型的定义

#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;

2.定义单链表的结构体

//定义单链表的结构体 
typedef struct Node{
	ElemType data;		//数据域 存储该Node数据 
	struct Node *next;	//指针域 指向下一个Node 
}LinkList;

3.初始化单链表

//返回一个初始化的节点L 
LinkList* InitList(){
	LinkList* L;								//定义一个节点 
	L = (LinkList*)malloc(sizeof(LinkList));	//分配节点空间 
	L->next = NULL;								//节点指针域置空 
	return L;
}

4.在单链表尾部添加元素

//功能说明:在单链表的尾部添加元素,返回添加元素后的尾节点 
//参数1:LinkList *r 要添加元素的单链表的尾节点
//参数2:ElemType e 要添加的元素e 
//返回值:LinkList * r  新的尾节点 
//实现方式:
//1.定义一个临时的节点n  给临时节点开辟空间 
//2.元素e存入临时节点的数据域中 将临时节点n的next置空 
//3.将尾节点的next指向临时节点n 尾节点后移 返回新的尾节点 
LinkList *tailAddElemLinkList(LinkList *r,ElemType e) {
	//定义一个临时的节点n  给临时节点开辟空间 
	LinkList *n = (LinkList*)malloc(sizeof(LinkList));
	//元素e存入节点n中 
	n->data = e;
	//将临时节点n的next置空 
	n->next = NULL;
	//将新节点插入末尾 
	r->next = n;
	//尾指针后移一位 
	r = r->next;
	//返回新的尾节点 
	return r;
}

5.创建单链表

//功能说明:创建单链表,从键盘输入len个数插入到单链表L中 
//参数1: LinkList* L 要链接节点的头节点
//参数2:int len 要添加的节点个数
//实现方式:
//定义一个尾指针r 定义变量e用于存储每次输入的元素值
//使用循环每次输入一个元素值 将元素通过尾部添加到单链表 
void createList(LinkList* L,int len){
	//定义一个尾指针r并初始化为头指针 
	LinkList* r = L;
	//定义变量e用于存储每次输入的元素值 
	ElemType e;
	printf("请输入%d个单链表的元素:",len);
	int i;
	for(i = 0; i < len; i++){
		//获取输入的元素 
		scanf("%d",&e);
		r = tailAddElemLinkList(r,e);
	} 
}

6.输出单链表中的元素值

//功能说明:输出单链表中的节点值 
//参数: LinkList* L 要显示的单链表的头节点 
//实现方式:定义一个节点p指向第一个节点 循环判断节点p是否存在,存在则输出data,节点p向后移动一位 
void showLinkList(LinkList* L) {
	LinkList* p = L->next;
	while(p){
		printf("%d ",p->data);
		p = p->next; 
	}
}

7.单链表排序

//功能说明:单链表从小到大的排序 冒泡排序 (值交换)
//参数: LinkList* L 单链表的头节点 
// 实现方式: 从第一个元素节点开始逐一比较,将节点的值进行交换
void linkListSort(LinkList* L){
	LinkList* i = L->next;
	LinkList* j = L->next;
	//外层循环 
	while(i){
		//内层循环 
		while(j){
			//值交换 
			if(i->data > j->data){
				ElemType e = i->data;
				i->data = j->data;
				j->data = e;
			}
			j = j->next;
		}
		j = i->next;
		i = i->next;
	}
}

8.判断某个元素在单链表中是否存在

//功能说明:判断某个元素在单链表中是否存在 存在返回1 不存在返回-1 
//参数1: LinkList *L 单链表的头节点
//参数2:要查找的元素e
//实现方式:遍历单链表L,拿元素e和单链表L中的所有元素匹配 成功返回1 失败返回-1 
int searchElem(LinkList *L, ElemType e){
	LinkList *temp = L->next;
	while(temp){
		if(e == temp->data) return 1;
		temp = temp->next;
	}
	return -1;
}

9.单链表数据去重拼接

//功能说明:将单链表的数据存到另一个单链表的末尾 重复元素不存入 
//参数1: LinkList *L1 存取元素的单链表的头节点
//参数2: LinkList *L1_rear 存取元素的单链表的尾节点
//参数3:LinkList *L2_head 被存取的单链表的头节点
//实现方式:
// 遍历单链表L2,判断每一个元素在L1中是否存在
//不存在则存入该元素到L1,L1的尾节点后移,最后返回L1的尾节点 
LinkList *spliceLinkList(LinkList *L1,LinkList *L1_rear,LinkList *L2_head){
	LinkList *r = L1_rear;
	while(L2_head){
		//判断单链表a里面的元素在单链表L存不存在, 不存在则存入(数据去重) 
		if(searchElem(L1,L2_head->data) == -1){
			//将L2_head->data从尾节点r存入L1中 
			r = tailAddElemLinkList(r,L2_head->data);
		}
		L2_head = L2_head->next; 
	}
	return r;
} 

10.返回两个单链表的并集

//功能说明:返回两个单链表的并集 
//参数1:LinkList *a 单链表a的头节点
//参数1:LinkList *b 单链表b的头节点
//实现方式: 将两个单链表去重后存入一起,排序成一个有序链表 (使用上面封装的函数实现) 
LinkList *unionLinkList(LinkList *a,LinkList *b){
	//初始化一个单链表L用于存储 单链表a和单链表b的并集 
	LinkList *L = InitList();
	LinkList *r = L;
	LinkList *a_head = a->next;
	LinkList *b_head = b->next;
	r = spliceLinkList(L,r,a_head);
	r = spliceLinkList(L,r,b_head);
	//排序合并的并集结果 
	linkListSort(L);  
	return L; 
} 

11.返回单链表a-b的差集

//功能说明:返回单链表a-b的差集 
//参数1:LinkList *a 单链表a的头节点
//参数1:LinkList *b 单链表b的头节点
//实现方式: 
//遍历单链表b
//判断单链表b里面的每一个元素在单链表a中是否存在 
//不存在则存入新的单链表L 
LinkList *diffLinkList(LinkList *a,LinkList *b){
	//初始化一个单链表L用于存储 单链表a和单链表b的并集 
	LinkList *L = InitList();
	LinkList *r = L;
	LinkList *a_head = a->next;
	while(a_head){
		//判断单链表a里面的元素在单链表b存不存在,不存在则存入(数据去重) 
		if(searchElem(b,a_head->data) == -1 && searchElem(L,a_head->data) == -1){
			r = tailAddElemLinkList(r,a_head->data);
		}
		a_head = a_head->next; 
	}
	//排序合并的并集结果 
	linkListSort(L);
	return L; 
}

12.返回两个单链表的交集

//功能说明:返回单链表a和b的交集 (和上面的函数一模一样,判断里面改一下就行)
//参数1:LinkList *a 单链表a的头节点
//参数1:LinkList *b 单链表b的头节点
//实现方式: 
//遍历单链表b
//判断单链表b里面的每一个元素在单链表a中是否存在 
//存在则存入新的单链表L 
LinkList *intersectionLinkList(LinkList *a,LinkList *b) {
	//初始化一个单链表L用于存储 单链表a和单链表b的并集 
	LinkList *L = InitList();
	LinkList *r = L;
	LinkList *a_head = a->next;
	while(a_head){
		//判断单链表a里面的元素在单链表b存不存在, 不存在则存入(数据去重) 
		if(searchElem(b,a_head->data) == 1 && searchElem(L,a_head->data) == -1){
			r = tailAddElemLinkList(r,a_head->data);
		}
		a_head = a_head->next; 
	}
	//排序合并的并集结果 
	linkListSort(L);
	return L;
}

13.判断两个单链表是否相等

//功能说明:判断两个单链表是否完全相等
//参数1:LinkList *a 单链表a的头节点
//参数1:LinkList *b 单链表b的头节点
//返回值:相等返回 int 1 不相等返回 int 0
//单链表a和单链表b如果他们的差集都为空,则他们完全相等
int equalLinkList(LinkList *a,LinkList *b){
	//判断a-b和b-a的差集是否都为空  差集为空则相等 
	if(!diffLinkList(a,b)->next && !diffLinkList(b,a)->next){
		return 1;
	}
	return 0;
} 

14.main函数实现

int main(){
	//初始化一个节点作为头节点 
	LinkList* L1 = InitList();
	LinkList* L2 = InitList();
	int len;
	printf("请输入要创建的第一个单链表长度:"); 
	scanf("%d",&len);
	createList(L1,len);
	printf("第一个单链表的元素为:"); 
	showLinkList(L1);
	
	printf("\n请输入要创建的第二个单链表长度:"); 
	scanf("%d",&len);
	createList(L2,len);
	printf("第二个单链表的元素为:"); 
	showLinkList(L2);
	
	printf("\n两个单链表的并集:");
	showLinkList(unionLinkList(L1,L2));
	printf("\n单链表a-b的差集:");
	showLinkList(diffLinkList(L1,L2));
	printf("\n单链表b-a的差集:");
	showLinkList(diffLinkList(L2,L1));
	printf("\n单链表a和单链表b的交集:"); 
	showLinkList(intersectionLinkList(L2,L1));
	printf("\n单链表的数据是否相等:"); 
	if(equalLinkList(L2,L1)) 
		printf("相等");
	else 
		printf("不相等");
	return 0;
} 

样例输出1(两个相等的单链表):
在这里插入图片描述
样例输出2(两个不相等的单链表):
在这里插入图片描述