用带哨兵的双向循环链表,实现O(1)时间的UNION操作

问题描述:

动态集合操作UNION以两个不相交的集合S1,和S2作为输入,并返回集合S1=S1US2包含S1S2的所有元素。该操作通常会破坏集合S1和S2试说明如何选用一种合适的表类数据结构,来支持0(1)时间的UNION操作。

问题分析:

分析题目的要求,首先S1和S2是不相交的,并且在进行合并的时候是可以破坏S1和S2的,所以我们可以想到链表。题目的要求是要在O(1)时间内完成Union操作,那么普通的单向链表是完成不了的,因为将两条链表相连,需要将第一条链表的最后一个节点与第二条链表的第一个节点相连,查找单向链表的最后一个节点需要O(n)时间。因此,我们这里选择的数据结构是带哨兵的双向循环链表。执行UNION操作的时候,将两条链表首尾相接即可。

链表的定义如下:

#include<stdio.h>
#include<stdlib.h>
struct Node {
	int n;
	struct Node* next;
	struct Node* pre;
};
struct List {
	struct Node* nil;
};

Union函数定义如下:

void list_union(struct List* l1, struct List* l2) {
	l1->nil->pre->next = l2->nil->next;
	l2->nil->next->pre = l1->nil->pre;
	l1->nil->pre = l2->nil->pre;
	l2->nil->pre->next = l1->nil;
}

将从链表中插入节点的操作定义为函数:

void insert(struct List* l, struct Node* n) {
	n->next = l->nil->next;
	l->nil->next->pre = n;
	l->nil->next = n;
	n->pre = l->nil;

}

测试代码如下:

int main() {
	struct List* l1 = (struct List*)malloc(sizeof(struct List));
	struct List* l2 = (struct List*)malloc(sizeof(struct List));
	l1->nil = (struct Node*)malloc(sizeof(struct Node));
	l1->nil->next = l1->nil;
	l1->nil->pre = l1->nil;

	l2->nil = (struct Node*)malloc(sizeof(struct Node));
	l2->nil->next = l2->nil;
	l2->nil->pre = l2->nil;
	for (int i = 0;i < 3;i++) {
		struct Node* node = (struct Node*)malloc(sizeof(struct Node));
		node->n = i;
		insert(l1, node);
	}
	for (int i = 4;i < 7;i++) {
		struct Node* node = (struct Node*)malloc(sizeof(struct Node));
		node->n = i;
		insert(l2, node);
	}
	list_union(l1, l2);
	struct Node* p = l1->nil->next;
	while (p != l1->nil) {
		printf("%d\n", p->n);
		p = p->next;
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值