2-5 链表去重
分数 5
作者 陈越
单位 浙江大学
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
输入格式:
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1 来表示。
随后 N 行,每行按以下格式描述一个结点:
其中地址是该结点的地址,键值是绝对值不超过104的整数,下一个结点是下个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。
输入样例:
00100 5 99999 -7 87654 23854 -15 00000 87654 15 -1 00000 -15 99999 00100 21 23854
|
输出样例:
00100 21 23854 23854 -15 99999 99999 -7 -1 00000 -15 87654 87654 15 -1
|
解析(还没搞懂)
#include <stdio.h> #include <stdlib.h> #include <math.h>
#define MAXN 100000
typedef struct Node { int addr; int key; struct Node* next; } ListNode;
ListNode* createNode(int addr, int key) { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->addr = addr; newNode->key = key; newNode->next = NULL; return newNode; }
int main() { int head_addr, n; scanf("%d%d", &head_addr, &n); int keys[MAXN] = {0}; int nexts[MAXN] = {0}; for (int i = 0; i < n; i++) { int addr, key, next; scanf("%d%d%d", &addr, &key, &next); keys[addr] = key; nexts[addr] = next; } ListNode* kept_head = NULL; ListNode* kept_tail = NULL; ListNode* removed_head = NULL; ListNode* removed_tail = NULL; int appeared[10001] = {0}; int current_addr = head_addr; while (current_addr != -1) { int key = keys[current_addr]; int abs_key = abs(key); ListNode* newNode = createNode(current_addr, key); if (!appeared[abs_key]) { appeared[abs_key] = 1; if (kept_head == NULL) { kept_head = kept_tail = newNode; } else { kept_tail->next = newNode; kept_tail = newNode; } } else { if (removed_head == NULL) { removed_head = removed_tail = newNode; } else { removed_tail->next = newNode; removed_tail = newNode; } } current_addr = nexts[current_addr]; } ListNode* current = kept_head; while (current != NULL) { if (current->next != NULL) { printf("%05d %d %05d\n", current->addr, current->key, current->next->addr); } else { printf("%05d %d -1\n", current->addr, current->key); } current = current->next; } current = removed_head; while (current != NULL) { if (current->next != NULL) { printf("%05d %d %05d\n", current->addr, current->key, current->next->addr); } else { printf("%05d %d -1\n", current->addr, current->key); } current = current->next; } current = kept_head; while (current != NULL) { ListNode* temp = current; current = current->next; free(temp); } current = removed_head; while (current != NULL) { ListNode* temp = current; current = current->next; free(temp); } return 0; }
|
2-6 两个有序链表合并(新表不含重复元素)
分数 4
作者 陈晓梅
单位 广东外语外贸大学
已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。
要求S3中没有重复元素。
输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:
在一行中输出合并后新的非降序链表,要求链表中没有重复元素。数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。
输入样例:
在这里给出一组输入。例如:
1 3 3 5 8 -1 2 3 4 6 8 10 -1
|
输出样例:
在这里给出相应的输出。例如:
解析
#include <stdio.h> #include <stdlib.h>
typedef int ElemType; typedef struct LNode { ElemType data; struct LNode *next; } LNode, *LinkList;
int main() { LNode *L1_head = (LNode*)malloc(sizeof(LNode)); LNode *L2_head = (LNode*)malloc(sizeof(LNode)); L1_head->next = NULL; L2_head->next = NULL; LNode *L1_tail = L1_head; LNode *L2_tail = L2_head;
int n = 0;
while (scanf("%d", &n) == 1 && n != -1) { LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->next = NULL; newNode->data = n; L1_tail->next = newNode; L1_tail = newNode; }
while (scanf("%d", &n) == 1 && n != -1) { LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->next = NULL; newNode->data = n; L2_tail->next = newNode; L2_tail = newNode; }
LNode *L3_head = (LNode*)malloc(sizeof(LNode)); L3_head->next = NULL; LNode *L3_tail = L3_head;
LNode *p1 = L1_head->next; LNode *p2 = L2_head->next;
while (p1 != NULL && p2 != NULL) { if (p1->data == p2->data) { LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->data = p1->data; newNode->next = NULL; L3_tail->next = newNode; L3_tail = newNode;
while (p1 != NULL && p1->data == newNode->data) { p1 = p1->next; } while (p2 != NULL && p2->data == newNode->data) { p2 = p2->next; } } else if (p1->data < p2->data) { LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->data = p1->data; newNode->next = NULL; L3_tail->next = newNode; L3_tail = newNode;
while (p1 != NULL && p1->data == newNode->data) { p1 = p1->next; } } else { LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->data = p2->data; newNode->next = NULL; L3_tail->next = newNode; L3_tail = newNode;
while (p2 != NULL && p2->data == newNode->data) { p2 = p2->next; } } }
while (p1 != NULL) { LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->data = p1->data; newNode->next = NULL; L3_tail->next = newNode; L3_tail = newNode;
while (p1 != NULL && p1->data == newNode->data) { p1 = p1->next; } } while (p2 != NULL) { LNode *newNode = (LNode*)malloc(sizeof(LNode)); newNode->data = p2->data; newNode->next = NULL; L3_tail->next = newNode; L3_tail = newNode;
while (p2 != NULL && p2->data == newNode->data) { p2 = p2->next; } }
LNode *p3 = L3_head->next; int flag = 1; if (p3 == NULL) { printf("NULL"); } else { while (p3 != NULL) { if (flag == 1) { printf("%d", p3->data); flag = 0; } else { printf(" %d", p3->data); } p3 = p3->next; } } return 0; }
|
注意
1.题中说新链表不能有重复的,所以在插入新链表时要注意跳过重复的。
while (p1 != NULL && p1->data == newNode->data) { p1 = p1->next; }
|
2.尾插法要一个tail指针,不能用头指针,不然会失去头指针的地址。