算法笔记练习 题解合集
题目
题目描述
根据一个递增的整数序列构造有序单链表,删除其中的重复元素
输入
输入包括多组测试数据,每组测试数据占一行,第一个为大于等于0的整数n,表示该单链表的长度,后面跟着n个整数,表示链表的每一个元素。整数之间用空格隔开
输出
针对每组测试数据,输出包括两行,分别是删除前和删除后的链表元素,用空格隔开
如果链表为空,则只输出一行,list is empty
样例输入
5 1 2 3 4 5
5 1 1 2 2 3
0
样例输出
1 2 3 4 5
1 2 3 4 5
1 1 2 2 3
1 2 3
list is empty
思路
重点讲一下deleteTheSame
这个函数,即怎么给链表去重:
- 用指针
p
遍历头结点为head
的链表; - 用指针
last
指向最后一个有效的结点(有效的意思是该结点应该被保留,例如对于链表42 -> 42 -> 100
,只有第一个42
结点和100
结点是有效的结点,第二个42
应该被删除); - 首先保证该函数的链表非空,将
p
初始化为head->next
; - 当
p != nullptr
时,先令last = p
记录下当前的有效结点,然后令p
不断向链表末端方向试探,只要满足p != nullptr
且p->data == last->data
,就让p
向前移动。同时在这个过程中删除无效的节点(避免内存泄漏)。
于是最后p
要么是空指针,要么指向下一个有效节点,令last->next = p;
,继续下一轮迭代。
代码
#include <iostream>
struct Lnode {
int data;
Lnode *next;
};
void initLinklist(Lnode *&head, int n) {
Lnode *tail = head;
while (n--) {
Lnode *p = new Lnode;
scanf("%d", &(p->data));
tail->next = p;
p->next = nullptr;
tail = p;
}
}
void deleteTheSame(Lnode *&head) {
Lnode *p = head->next, *last;
while (p) {
last = p;
while (p && p->data == last->data) {
Lnode *temp = p;
p = p->next;
if (temp != last)
free(temp);
}
last->next = p;
}
}
void showLinklist(Lnode *&head) {
Lnode *p = head->next;
if (p) {
while (p) {
if (p != head->next)
putchar(' ');
printf("%d", p->data);
p = p->next;
}
putchar('\n');
}
}
int main() {
int n;
while (scanf("%d", &n) != EOF) {
if (n == 0) {
puts("list is empty");
continue;
}
Lnode *head = new Lnode;
head->next = nullptr;
initLinklist(head, n);
showLinklist(head);
deleteTheSame(head);
showLinklist(head);
}
return 0;
}