结点元素结构如下:
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;
}
}
为了简化,采用的如下解法:
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;
}