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的头节点
//实现方式:
//遍历单链表a
//判断单链表a里面的每一个元素在单链表b中是否存在
//不存在则存入新的单链表L
LinkList *diffLinkList(LinkList *a,LinkList *b){
//初始化一个单链表L用于存储 单链表a和单链表b的并集
LinkList *L = InitList();
LinkList *r = L;
LinkList *a_head = a->next;
while(a_head){
//判断单链表b里面的元素在单链表a存不存在,不存在则存入(数据去重)
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的头节点
//实现方式:
//遍历单链表a
//判断单链表a里面的每一个元素在单链表b中是否存在
//存在则存入新的单链表L
LinkList *intersectionLinkList(LinkList *a,LinkList *b) {
//初始化一个单链表L用于存储 单链表a和单链表b的并集
LinkList *L = InitList();
LinkList *r = L;
LinkList *a_head = a->next;
while(a_head){
//判断单链表b里面的元素在单链表a存不存在, 存在则存入(数据去重)
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(两个不相等的单链表):