前言
大二菜鸡面临越来越近的期末考试,瑟瑟发抖。为了应付一下可怕未知的数据结构机试,本人想练习一下编程,于是打开学校OJ,从头开始练习,拿这道链表去重练手,但也做了好长时间(泪)。虽然困难重重,但最后还是独立将题目实现,有一丢成就感,于是也想写一篇博客来加深体会。这也算我的第一篇博客,毕竟来CSDN白嫖一年了(笑)。
一、题目要求
给定一个键值为整数的单链表 L,将键值的绝对值有重复的结点删除:即对任意键值 K,只有键值或其绝对值等于 K 的第一个结点被保留在 L 中。例如,下面单链表 L 包含键值 21、-15、15、7、-15,如下图(a)所示;去重后的链表 L 包含键值 21、-15、7,如下图(b)所示。
输入说明:
输入的第一行包含两个整数,分别表示链表第一个结点的地址和结点个数 n(1≤n≤100)。结点地址是一个非负的 5 位整数,NULL 指针用-1 表示。
随后 n 行,每行含 3 个整数,按下列格式给出一个结点的信息:
Address Key Next
其中 Address 是结点的地址,Key 是绝对值不超过 10000 的整数,Next 是下一个结点的地址。
输出说明:
输出的第一行为去重后链表 L 的长度,换行;接下来按顺序输出 L 的所有结点,每个结点占一行,按照 Address Key Next 的格式输出,间隔 1 个空格。
测试样例:
输入样例 1
00100 5
99999 7 87654
23854 -15 00000
87654 -15 -1
00000 15 99999
00100 21 23854
输出样例 1
3
00100 21 23854
23854 -15 99999
99999 7 -1
二、思路
先用一个数组将输入结点存储,此时结点乱序,在数组中对结点排完序之后,再用链表将输入结点存储,之后比较、删除结点,最后打印结点内容。
三、代码
代码如下:
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
//定义结点结构体
typedef struct node
{
int self_adr;
int next_adr;
int key;
struct node *next = NULL;
}node;
//初始化
node *Init(){
node *head = (node *)malloc(sizeof(node));
head->next = NULL;
return head;
}
//寻找当前结点q的直接前驱
node *Search(node *head, node *q){
node *p = head->next;
while(p->next!=q){
p = p->next;
}
return p;
}
//求当前链表长度
int sum_length(node *head){
node *p = head->next;
int length, count = 0;
while(p){
count++;
p = p->next;
}
length = count;
return length;
}
int main(){
int n, first_adr;
int i,j,length;
node NodeList[MAX];
node temp;
node *head, *p, *q;
head = Init();
q = head;
scanf("%d%d",&first_adr,&n);
for (i = 0; i < n;i++){
scanf("%d%d%d",&NodeList[i].self_adr,&NodeList[i].key,&NodeList[i].next_adr);
}
//按照输入前后地址对结点排序
for (i = 0; i < n;i++){
for (j = i; j < n;j++){
if(NodeList[j].self_adr == first_adr){
temp = NodeList[i];
NodeList[i] = NodeList[j];
NodeList[j] = temp;
first_adr = NodeList[i].next_adr;
break;
}
}
}
//用链表将这些结点连接
for (i = 0; i < n;i++){
p = (node *)malloc(sizeof(node));
p = &NodeList[i];
p->next = NULL;
q->next = p;
q = q->next;
}
q = head;
p = q->next;
while(p){
q = p->next;
while (q){
if (q->key == p->key || q->key == -(p->key)){
if(q->next == NULL){//此时为链表最后一个结点
node *s = Search(head, q);
s->next_adr = -1;
s->next = NULL;
}
else{
node *s = Search(head, q);
s->next_adr = q->next->self_adr;
s->next = q->next;
}
}
q = q->next;
}
p = p->next;
}
q = head;
length = sum_length(q);
printf("%d\n",length);//打印结点个数
//打印结点
while(q->next){
p = q->next;
if(p->next_adr==-1)
printf("%05d %d %d\n",p->self_adr,p->key,p->next_adr);
else
printf("%05d %d %05d\n",p->self_adr,p->key,p->next_adr);
q = q->next;
}
return 0;
}
四、反思
中间对链表操作的地方在循环那里卡了好久,由于未对判定条件深思熟虑,在操作最后一个结点时导致循环无法跳出,此为代码片段:
if(q->next == NULL){//此时为链表最后一个结点
node *s = Search(head, q);
s->next_adr = -1;
s->next = NULL;
}
总结
虽然是个简简单单的编程题,但本人还是费了好大力气,但还是有收获的。另外,这个解法肯定不是最优的写法,但我想用通俗易懂的方式写出来。如果有大佬看到这篇文章,若有时间,请对程序进行指正。
谢谢浏览!