链表操作————合并两个链表,并同时删除两链表中的公共元素结点

结点元素结构如下:

typedef int DataType;

typedef struct Node
{
	DataType data;
	struct Node * pNext;
}Node;


先看来普通的合并,没有删除操作的函数:(这里默认是按从小到大的顺序排列)

Node * MergLinkList(Node *pNode1, Node *pNode2)
{
	if (pNode1 == NULL)			//无需合并
		return pNode2;
	else if (pNode2 == NULL)
		return NULL;
	else
	{
		Node * pHead = pNode1;
		Node *p1;
		Node *p2;
		while (pNode1->pNext && pNode2)				//这里没有指针指向比较结点的前一个结点,
		{											//所以结束条件为pNode1->pNext来处理后续结点
			p1 = pNode1->pNext;
			p2 = pNode2->pNext;
			if (pNode1->data > pNode2->data)		//链表1的结点数据大于链表2的结点话 就交换其数据,然后合并
			{
				pNode1->data ^= pNode2->data;		//交换两个结点的数据域
				pNode2->data ^= pNode1->data;
				pNode1->data ^= pNode2->data;
			}
			pNode1->pNext = pNode2;		//开始合并  
			pNode2->pNext = p1;		//链表2上的结点指向链表1
			pNode2 = p2;			//指向链表2上下一次需要比较的结点
			pNode1 = pNode1->pNext;		//指向链表1上
		}
		if (pNode1->pNext == NULL && pNode2)	//处理后续结点
		{
			if (pNode1->data > pNode2->data)//如果链表1中的最后一个结点大于链表2中的第一个结点则交换数据域
			{				//当链表2中含有多个结点,且元素的值都小于链1中最后一个结点时,
							//就不能正常的操作,所以还得对后续结点进一步处理
				pNode1->data ^= pNode2->data;
				pNode2->data ^= pNode1->data;
				pNode1->data ^= pNode2 -> data;
			}
			pNode1->pNext = pNode2;				//链接
		}
		return pHead;
	}
}


对于上面的问题,只要在处理尾部结点的时候进行一次排序就可以接续大小顺序问题,(将链表1中的最后一个结点取下,插入到相应位置即可!)

为了简化,采用的如下解法:

Node *MergLinkListAndDeleteCommon(Node* pNode1, Node* pNode2)
{
	if (pNode1 == NULL)
		return pNode2;
	else if (pNode2 == NULL)
		return NULL;
	else
	{
		//由于不含头结点,所以对首结点进行单独处理
		Node *p1, *p2;
		Node *pHead;	//新链表的头指针
		if (pNode1->data == pNode2->data)	//结点数据相,删除一个
		{
			pHead = p1 = pNode1;
			p2 = pNode2->pNext;
			free(pNode2);
			pNode2 = p2;
		}
		else if (pNode1->data > pNode2->data)	//取小者作为首结点
		{
			pHead = p1 = pNode2;
			pNode2 = pNode2->pNext;
			pHead->pNext = pNode1;
		}
		else
		{
			pHead = p1 = pNode1;
		}
		while (pNode1 && pNode2)			//至少有一个链表已经扫描到末尾
		{
			if (pNode1->data == pNode2->data)
			{
				p2 = pNode2;
				pNode2 = pNode2->pNext;
				free(p2);
			}
			else if (pNode1->data > pNode2->data)	//取链表2的结点链接到链表以
			{
				p1->pNext = pNode2;				//链接到链表2上结点
				pNode2 = pNode2->pNext;				//指向链表2中下一个结点
				p1 = p1->pNext;					//跳到下一个结点上
				p1->pNext = pNode1;				//链接到链表1上
			}
			else
			{
				p1 = pNode1;
				pNode1 = pNode1->pNext;				//指向链表1中 下一次比较的结点
				p2 = pNode2;
				pNode2 = pNode2->pNext;				//指向链表2中 下一次比较的结点
				p1->pNext = p2;					//链接上结点
				p1 = p1->pNext;
				p1->pNext = pNode1;				//断开链表2  链接上链表1
			}
		}
		if (pNode1 == NULL)	//链表已扫描完
			p1->pNext = pNode2;
		//如果是链表2扫描完,则不予处理即可
		return pHead;			//返回首结点指针
	}
}

这样就解决了上面顺序的问题,而上面的原因是:结束条件(pNode->pNext == NULL时),从而导致最后留下了一个结点,顺序上还要作处理。

对与后面这种情况,就解决了这个问题,该函数的功能是合并两个链表,并且对链表1中有的元素不进行合并。

当然,如果要时合并过后的链表中没有重复的元素,这是远远不够的,只需在合并前,对每个链表作预处理,

删除相同的元素即可,具体情况具体分析。


删除链表的中相同元素结点的函数如下:


Node *Sort(Node *pNode)//对链表排序,从小到大
{
	if (pNode == NULL || pNode->pNext == NULL)	//元素个数少于2个
		return pNode;
	for (Node *p = pNode; p->pNext; p = p->pNext)
	{
		for (Node *q = p->pNext; q; q = q->pNext)
		{
			if (p->data > q->data)
			{
				p->data ^= q->data;
				q->data ^= p->data;
				p->data ^= q->data;
			}
		}
	}
	return pNode;
}

Node* DeleteCommentElement(Node *pNode)//删除有序链表中的相同元素(前提:链表有序)
{
	Node *pHead, *p;
	if (pNode == NULL || pNode->pNext == NULL)
		return;
	pHead = pNode;
	p = pNode->pNext;
	while (p)
	{
		if (pNode->data == p->data)
		{
			pNode->pNext = p->pNext;
			free(p);
			p = pNode->pNext;
		}
		else
		{
			pNode = p;
			p = p->pNext;
		}
	}
	return pHead;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值