该问题比单向链表要更加复杂一些,必须考虑并更新前向节点的指向情况。
主要思路为:
typedef struct Node { //双链节点 定义
int data;
struct Node *prev, *next;
} DList;
void PrintList(DList *head) { // 打印链表,
DList *cur = head;
while(cur != NULL) { // 正向打印
printf("%d ", cur->data);
cur = cur->next;
if(cur) {
printf(" -> ");
}
}
printf(" || ");
cur = head;
while(cur->next != NULL) { // 寻找尾巴节点
cur = cur->next;
}
while(cur != NULL) { // 反向打印
printf("%d", cur->data);
cur = cur->prev;
if(cur) {
printf(" -> ");
}
}
}
void delSameDataNodes(DList **pHead1, DList **pHead2) { // 因会修改head 节点指向,所以必须使用二级指针
if(*pHead1 == NULL || *pHead2 == NULL) {
return;
}
DList* dummy1 = (DList *) malloc(sizeof(DList)); // 哨兵节点
DList* dummy2 = (DList *) malloc(sizeof(DList));
dummy1->next = *pHead1; // 哨兵节点添加到头节点前面
dummy2->next = *pHead2;
dummy1->prev = NULL; // 哨兵节点初始化
dummy2->prev = NULL;
dummy1->data = 0;
dummy2->data = 0;
DList* pc1 = *pHead1; // 为每个链表定义前节点,当前节点,后续节点指针
DList* pf1 = dummy1;
DList* pn1 = pc1->next;
DList* pc2 = *pHead2;
DList* pf2 = dummy2;
DList* pn2 = pc2->next;
int dup = 0; // 是否重复指示标志位
while(pc1 != NULL) { // 链表A开始循环,逐一元素访问
pf2 = dummy2; // 每当链表A访问新元素时, 链表B的3个指针必须从链表头重新开始指向,因pHead2有可能被移除,因此只能用哨兵节点
pc2 = pf2->next;
pn2 = pc2->next;
while(pc2 != NULL) {
if(pc1->data != pc2->data) { // 两个链表元素不等时,链表2继续向后检索,知道链表末端,注意更新3个指针
pf2 = pc2;
pc2 = pn2;
pn2 = (pn2 == NULL)?NULL:pn2->next; // 如果pn2 为空时,不能对其赋值
} else { // 两个链表元素相等时 ,需要设置标志位,跳过当前节点 pc2
dup = 1; // 设置标志位
if(pn2) { // 如果pn2 非空时,跳过当前节点,并更新指针,因跳出当前循环,所以此处pc2可以不用设置
pf2->next = pn2;
pn2->prev = pf2;
} else {
pf2->next = NULL;
}
break;
}
}
if(dup == 1) {
dup = 0;
if(pn1) {
pf1->next = pn1;
pn1->prev = pf1;
pc1 = pn1; // 此处pc1 必须设置
pn1 = pn1->next;
} else {
pf1->next = NULL;
}
} else {
pf1=pc1;
pc1=pn1;
pn1 = (pn1 == NULL)?NULL:pn1->next;
}
}
*pHead1 = dummy1->next;
*pHead2 = dummy2->next;
(*pHead1)->prev = NULL;
(*pHead2)->prev = NULL;
free(dummy1);
dummy1 = NULL;
free(dummy2);
dummy2 = NULL;
}
void add2Tail(DList **head, int data) {
DList *node = (DList*) malloc(sizeof(DList));
node->data = data;
node->next = NULL;
node->prev = NULL;
if(*head == NULL) {
*head = node;
} else {
DList *cur =*head;
while(cur->next!=NULL) {
cur = cur->next;
}
cur->next = node;
node->prev = cur;
}
}
void testList(void){
DList *head1 = NULL;
DList *head2 = NULL;
add2Tail(&head1, 1);
add2Tail(&head1, 2);
add2Tail(&head1, 3);
add2Tail(&head1, 4);
add2Tail(&head1, 8);
add2Tail(&head1, 9);
printf("original list 1: ");
PrintList(head1);
printf("\n");
add2Tail(&head2, 1);
add2Tail(&head2, 2);
add2Tail(&head2, 4);
add2Tail(&head2, 5);
add2Tail(&head2, 6);
add2Tail(&head2, 7);
add2Tail(&head2, 9);
printf("original list 2: ");
PrintList(head2);
printf("\n---------------\n");
delSameDataNodes(&head1, &head2);
printf("remove duplicate list1: ");
PrintList(head1);
printf("\n");
printf("remove duplicate list2: ");
PrintList(head2);
printf("\n");
}