有两个双向链表,空白头结点为:ListA和ListB,要求删除这两个链表中关键字相同的结点, C语言实现,结点结构如下:
- struct node // 双向链表结点
- {
- int key;
- struct node *front, *next;
-
};
完整代码:
/* 功能:删除两个双向链表(都带空白头结点)中值(key)相同的结点,规定header.front始终指向尾结点 名词定义: 空白头结点:该结点不作为真正保存值的结点;其front成员规定指向尾结点, next指向第一个非空白结点;当该链表无结点时,规定其front和next都为NULL. 头结点: 链表的第一个非空白头结点(第一个元素) 尾结点: 链表的最后一个非空白结点 */ #include <stdio.h> #include <stdlib.h> #include <string.h> struct node // 双向链表结点 { int key; struct node *front, *next; }; /* 功能: 创建双向链表(尾插法:新创建的结点放在链表尾部) 返回值:1-创建成功,0-创建失败 header: 创建的双向链表的头指针 n: 待创建的结点个数 */ int createLinklist(struct node *header, int n) { int v; struct node *p = NULL; printf("请输入%d个整数:\n", n); while(n-- > 0) { scanf("%d", &v); p = malloc(sizeof(struct node)); if(p) { if(header->next == NULL) header->next = p; // 设置链表头指针 else { header->front->next = p; p->front = header->front; } p->key = v; p->next = header->next; // 新结点的next指向第一个结点 header->next->front = p; // 结点的front指向新结点(作为最后一个结点) header->front = p; // header->front始终指向最后一个结点 } else return 0; // 创建链表失败 } return 1; // 创建链表成功 } // 输出双向链表中的值 void displayLinklist(struct node *header) { struct node *p = header->next; printf("header.front = 0x%X, header.next = 0x%X\n", header->front, header->next); if(NULL != p) { do { printf("[p = 0x%X]\tdata = %d, front = 0x%X, next = 0x%X\n", p, p->key, p->front, p->next); p = p->next; }while(p != header->next); printf("\n"); } } // 删除双向链表中所有结点并释放空间(头删法) void FreeLinklist(struct node *header) { struct node *p; while(header->next) { p = header->next; // p指向待删结点 if(p == header->front) // 待删除的是尾结点 { header->front = header->next = NULL; } else { header->front->next = p->next; p->next->front = header->front; header->next = p->next; } free(p); } } /* 功能: 删除双向链表(头指针pHeader)中值与key相同的结点,从结点*pStart开始向后搜索 返回值: 如果从双向链表中删除了值为指定key的结点,返回1,否则返回0 pHeader: 双向链表空白头指针 pStart: 从*pStart开始向后搜索,删除值与key相同的结点,直到遇到pHeader->next key: 待删结点关键字 注意: 调用此函数时,输入参数pHeader==*pStart,程序将会出错 */ int removeNode(struct node *pHeader, struct node **pStart, int key) { struct node *p, *temp; int del = 0; p = *pStart; *pStart = NULL; while(p) { if(p->key == key) { del = 1; temp = p; // temp指向待删结点 if(pHeader->next == p) // 删除头结点 { if(pHeader->front == pHeader->next) // 待删结点是链表的唯一结点 pHeader->front = pHeader->next = NULL; else { pHeader->front->next = p->next; p->next->front = pHeader->front; // 尾结点的next指向新的头结点 pHeader->next = p->next; } p = pHeader->next; // p指向新的头结点 } else { p->front->next = p->next; p->next->front = p->front; if(p == pHeader->front) // 待删除的是尾结点 pHeader->front = p->front; // pHeader->front指向新的尾结点 p = p->next; // p指向被删除结点的后继结点 } free(temp); } else { if(*pStart == NULL) *pStart = p; p = p->next; } if(*pStart && p == pHeader->next) break; } return del; } // 删除两个链表中值相同的结点 void removeEqualNodes(struct node *pHeadA, struct node *pHeadB) { struct node *p1, *p2; int del = 0; p1 = pHeadA->next; while(p1) { p2 = pHeadB->next; if((del = removeNode(pHeadB, &p2, p1->key)) == 1) { removeNode(pHeadA, &p1, p1->key); } else p1 = p1->next; if(pHeadB->next == NULL || pHeadA->next == NULL || (del == 0 && p1 == pHeadA->next)) break; } } int main(int argc, char *argv[]) { struct node listA, listB; // 定义两个双向链表的空白头结点 int n1, n2; // 保存待创建的链表结点个数 if(argc < 3) { printf("Usage: %s <n1> <n2>\n", argv[0]); return 1; } n1 = atoi(argv[1]); n2 = atoi(argv[2]); listA.front = listA.next = NULL; listB.front = listB.next = NULL; createLinklist(&listA, n1); // 创建双向链表 createLinklist(&listB, n2); printf("Before remove:\n"); displayLinklist(&listA); // 显示双向链表内容 displayLinklist(&listB); removeEqualNodes(&listA, &listB); // 删除两个链表中值相同的结点 printf("\nAfter remove:\n"); displayLinklist(&listA); displayLinklist(&listB); FreeLinklist(&listA); // 释放空间 FreeLinklist(&listB); return 0; }
运行结果:
E:\Program\VC\del\Debug>del.exe 2 4 请输入2个整数: 14 25 请输入4个整数: 14 25 63 66 Before remove: header.front = 0x3807E0, header.next = 0x3807A8 [p = 0x3807A8] data = 14, front = 0x3807E0, next = 0x3807E0 [p = 0x3807E0] data = 25, front = 0x3807A8, next = 0x3807A8 header.front = 0x3808C0, header.next = 0x380818 [p = 0x380818] data = 14, front = 0x3808C0, next = 0x380850 [p = 0x380850] data = 25, front = 0x380818, next = 0x380888 [p = 0x380888] data = 63, front = 0x380850, next = 0x3808C0 [p = 0x3808C0] data = 66, front = 0x380888, next = 0x380818 After remove: header.front = 0x0, header.next = 0x0 header.front = 0x3808C0, header.next = 0x380888 [p = 0x380888] data = 63, front = 0x3808C0, next = 0x3808C0 [p = 0x3808C0] data = 66, front = 0x380888, next = 0x380888 E:\Program\VC\del\Debug>del.exe 2 4 请输入2个整数: 14 25 请输入4个整数: 12 23 21 54 Before remove: header.front = 0x3807E0, header.next = 0x3807A8 [p = 0x3807A8] data = 14, front = 0x3807E0, next = 0x3807E0 [p = 0x3807E0] data = 25, front = 0x3807A8, next = 0x3807A8 header.front = 0x3808C0, header.next = 0x380818 [p = 0x380818] data = 12, front = 0x3808C0, next = 0x380850 [p = 0x380850] data = 23, front = 0x380818, next = 0x380888 [p = 0x380888] data = 21, front = 0x380850, next = 0x3808C0 [p = 0x3808C0] data = 54, front = 0x380888, next = 0x380818 After remove: header.front = 0x3807E0, header.next = 0x3807A8 [p = 0x3807A8] data = 14, front = 0x3807E0, next = 0x3807E0 [p = 0x3807E0] data = 25, front = 0x3807A8, next = 0x3807A8 header.front = 0x3808C0, header.next = 0x380818 [p = 0x380818] data = 12, front = 0x3808C0, next = 0x380850 [p = 0x380850] data = 23, front = 0x380818, next = 0x380888 [p = 0x380888] data = 21, front = 0x380850, next = 0x3808C0 [p = 0x3808C0] data = 54, front = 0x380888, next = 0x380818 E:\Program\VC\del\Debug>del.exe 0 0 请输入0个整数: 请输入0个整数: Before remove: header.front = 0x0, header.next = 0x0 header.front = 0x0, header.next = 0x0 After remove: header.front = 0x0, header.next = 0x0 header.front = 0x0, header.next = 0x0 E:\Program\VC\del\Debug>del.exe 0 2 请输入0个整数: 请输入2个整数: 12 54 Before remove: header.front = 0x0, header.next = 0x0 header.front = 0x3807E0, header.next = 0x3807A8 [p = 0x3807A8] data = 12, front = 0x3807E0, next = 0x3807E0 [p = 0x3807E0] data = 54, front = 0x3807A8, next = 0x3807A8 After remove: header.front = 0x0, header.next = 0x0 header.front = 0x3807E0, header.next = 0x3807A8 [p = 0x3807A8] data = 12, front = 0x3807E0, next = 0x3807E0 [p = 0x3807E0] data = 54, front = 0x3807A8, next = 0x3807A8 E:\Program\VC\del\Debug>del.exe 2 0 请输入2个整数: 14 25 请输入0个整数: Before remove: header.front = 0x3807E0, header.next = 0x3807A8 [p = 0x3807A8] data = 14, front = 0x3807E0, next = 0x3807E0 [p = 0x3807E0] data = 25, front = 0x3807A8, next = 0x3807A8 header.front = 0x0, header.next = 0x0 After remove: header.front = 0x3807E0, header.next = 0x3807A8 [p = 0x3807A8] data = 14, front = 0x3807E0, next = 0x3807E0 [p = 0x3807E0] data = 25, front = 0x3807A8, next = 0x3807A8 header.front = 0x0, header.next = 0x0 E:\Program\VC\del\Debug>del.exe 1 1 请输入1个整数: 25 25 请输入1个整数: Before remove: header.front = 0x3807A8, header.next = 0x3807A8 [p = 0x3807A8] data = 25, front = 0x3807A8, next = 0x3807A8 header.front = 0x3807E0, header.next = 0x3807E0 [p = 0x3807E0] data = 25, front = 0x3807E0, next = 0x3807E0 After remove: header.front = 0x0, header.next = 0x0 header.front = 0x0, header.next = 0x0 E:\Program\VC\del\Debug>del.exe 5 6 请输入5个整数: 14 25 63 47 58 14 请输入6个整数: 25 36 47 55 25 Before remove: header.front = 0x380888, header.next = 0x3807A8 [p = 0x3807A8] data = 14, front = 0x380888, next = 0x3807E0 [p = 0x3807E0] data = 25, front = 0x3807A8, next = 0x380818 [p = 0x380818] data = 63, front = 0x3807E0, next = 0x380850 [p = 0x380850] data = 47, front = 0x380818, next = 0x380888 [p = 0x380888] data = 58, front = 0x380850, next = 0x3807A8 header.front = 0x3809D8, header.next = 0x3808C0 [p = 0x3808C0] data = 14, front = 0x3809D8, next = 0x3808F8 [p = 0x3808F8] data = 25, front = 0x3808C0, next = 0x380930 [p = 0x380930] data = 36, front = 0x3808F8, next = 0x380968 [p = 0x380968] data = 47, front = 0x380930, next = 0x3809A0 [p = 0x3809A0] data = 55, front = 0x380968, next = 0x3809D8 [p = 0x3809D8] data = 25, front = 0x3809A0, next = 0x3808C0 After remove: header.front = 0x380888, header.next = 0x380818 [p = 0x380818] data = 63, front = 0x380888, next = 0x380888 [p = 0x380888] data = 58, front = 0x380818, next = 0x380818 header.front = 0x3809A0, header.next = 0x380930 [p = 0x380930] data = 36, front = 0x3809A0, next = 0x3809A0 [p = 0x3809A0] data = 55, front = 0x380930, next = 0x380930 E:\Program\VC\del\Debug>