#include <stdio.h>
#include <malloc.h>
typedef char ElemType;
typedef struct LNode {
ElemType data; //数据域
struct LNode *next; //指向后继结点
}LinkNode; // 声明单链表结点类型
/*------------------------尾插法建立单链表---------------------------*/
static void create_list_rear(LinkNode *&L, ElemType a[], int n) // 指针的引用
{
LinkNode *s, *r;
int i;
L = (LinkNode *)malloc(sizeof(LinkNode)); // 创建头结点
L->next = NULL;
r = L; // r始终指向尾结点,开始时指向头结点
for(i = 0; i < n; i++)
{
// 创建新结点s
s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = a[i];
r->next = s; // 将结点s插入r结点之后
r = s;
}
// 尾结点next域置为NULL
r->next = NULL;
}
/*------------------------输出线性表---------------------------*/
static void display_list(LinkNode *L)
{
LinkNode *p = L->next;
while(p != NULL)
{
printf("%c ", p->data);// p不为NULL,输出p结点的数据域
p = p->next; // p移向下一个结点
}
printf("\n");
}
/*------------------------销毁线性表---------------------------*/
static void destroy_list(LinkNode *&L)
{
LinkNode *pre = L, *p = pre->next;
while(p != NULL)
{
free(pre);
pre = p;
p = pre->next; // pre、p同步后移一个结点
}
free(pre); // 此时p为NULL,pre指向尾结点,释放它
}
/*------------------------单链表元素递增排序---------------------------*/
static void sort_list(LinkNode *&L) // 指针的引用
{
LinkNode *p;
LinkNode *pre;
LinkNode *q;
// p指向L的第2个数据结点
p = L->next->next;
// 构造只含有一个数据结点的有序表
L->next->next = NULL;
while(p != NULL)
{
// q保存p结点的后继结点
q = p->next;
// 从有序表开头进行比较,pre指向插入结点p的前驱结点
pre = L;
while(pre->next != NULL && pre->next->data < p->data)
pre = pre->next; //在有序表中查找pre结点
// 在结点pre之后插入p结点
p->next = pre->next;
pre->next = p;
// 扫描原单链表余下的结点
p = q;
}
}
/*------------------------求两个有序集合的并---------------------------*/
// 算法设计采用二路归并+尾插法建表思路
static void union_list(LinkNode *ha, LinkNode *hb, LinkNode *&hc)// 指针的引用
{
LinkNode *pa = ha->next;
LinkNode *pb = hb->next;
LinkNode *s, *tc;
// 创建头结点hc
hc = (LinkNode *)malloc(sizeof(LinkNode)); // 分配内存空间
tc = hc; // tc指向新创建的头结点hc
while(pa != NULL && pb != NULL)
{
if(pa->data < pb->data)
{
// 复制结点
s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = pa->data;
// 将s结点插入到头结点tc之后
tc->next = s;
tc = s;
// pa后移一个结点
pa = pa->next;
}
else if(pa->data > pb->data)
{
// 复制结点
s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = pb->data;
// 将s结点插入到头结点tc之后
tc->next = s;
tc = s;
// pb后移一个结点
pb = pb->next;
}
else
{
// 复制结点
s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = pa->data;
// 将s结点插入到头结点之后
tc->next = s;
tc = s;
// 重复的元素只复制一个结点
pa = pa->next;
pb = pb->next;
}
}
// 复制余下的结点
if(pb != NULL)
pa = pb;
while(pa != NULL)
{
// 复制结点
s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = pa->data;
// 将s结点插入到tc之后
tc->next = s;
tc = s;
// pa后移一个结点
pa = pa->next;
}
tc->next = NULL;
}
/*------------------------求两个有序集合的交---------------------------*/
// 算法设计采用二路归并+尾插法建表思路
static void inter_sect(LinkNode *ha, LinkNode *hb, LinkNode *&hc)// 指针的引用
{
LinkNode *pa = ha->next; // pa指向第一个集合中的第一个数据结点
LinkNode *pb;
LinkNode *s;
LinkNode *tc;
// 创建头结点hc
hc = (LinkNode *)malloc(sizeof(LinkNode)); // 分配内存空间
tc = hc; // tc指向新创建的头结点hc
while(pa != NULL)
{
pb = hb->next;
while(pb != NULL && pb->data < pa->data)
pb = pb->next;
// 若pa结点值在B中
if(pb != NULL && pb->data == pa->data)
{
// 复制结点
s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = pa->data;
// 将s结点插入到tc之后
tc->next = s;
tc = s;
}
pa = pa->next;
}
tc->next = NULL;
}
/*------------------------求两个有序集合的差---------------------------*/
// 算法设计采用二路归并+尾插法建表思路,C = A - B, C中含有所有属于集合A而不属于集合B的元素
static void subs(LinkNode *ha, LinkNode *hb, LinkNode *&hc)
{
LinkNode *pa = ha->next;
LinkNode *pb;
LinkNode *s;
LinkNode *tc;
// 创建头结点hc
hc = (LinkNode *)malloc(sizeof(LinkNode)); // 分配内存空间
tc = hc; // tc指向新创建的头结点hc
while(pa != NULL)
{
pb = hb->next;
while(pb != NULL && pb->data < pa->data)
{
pb = pb->next;
}
// 若pa结点值不在B中
if(!(pb != NULL && pb->data == pa->data))
{
// 复制结点
s = (LinkNode *)malloc(sizeof(LinkNode));
s->data = pa->data;
// 将s结点插入到tc结点之后
tc->next = s;
tc = s;
}
pa = pa->next;
}
tc->next = NULL;
}
int main(int argc, char **argv)
{
LinkNode *ha;
LinkNode *hb;
LinkNode *hc;
int n;
ElemType a[] = {'c', 'a', 'e', 'h'};
ElemType b[] = {'f', 'h', 'b', 'g', 'd', 'a'};
printf("集合的运算如下:\n");
n = 4;
create_list_rear(ha, a, n);
n = 6;
create_list_rear(hb, b, n);
printf("原集合A:");
display_list(ha);
printf("原集合B:");
display_list(hb);
sort_list(ha);
sort_list(hb);
printf("有序集合A:");
display_list(ha);
printf("有序集合B:");
display_list(hb);
union_list(ha, hb, hc);
printf("集合的并C:");
display_list(hc);
inter_sect(ha, hb, hc);
printf("集合的交C:");
display_list(hc);
#if 1
subs(ha, hb, hc);
printf("集合的差C:");
display_list(hc);
#endif
destroy_list(ha);
destroy_list(hb);
destroy_list(hc);
return 0;
}
测试结果:
集合的运算如下:
原集合A:c a e h
原集合B:f h b g d a
有序集合A:a c e h
有序集合B:a b d f g h
集合的并C:a b c d e f g h
集合的交C:a h
集合的差C:c e