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

来源:互联网 发布:杂志排版用什么软件 编辑:程序博客网 时间:2024/05/29 19:22

结点元素结构如下:

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上的结点指向链表1pNode2 = 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