您的位置:首页 > 其它

PTA 链表删除结点的题目测试

2016-03-31 17:53 537 查看

链表删除结点

题目描述

输入一个正整数repeat(0


输入格式

见输入样例


输出格式

见输出样例


输入样例

3
5
1 2 4 3 7
4
5
2 1 5 7 5
5
3
1 2 4
100


输出样例

size=4:1 2 3 7
size=4:2 1 5 7
size=3:1 2 4


思路

创建一条单向链表,因为题目要找出并删除最后一个与x相同的数,所以反转链表,删除第一个与x相同的数,这样就不用做标记,删除后再反转一次,最后输出。

#include<stdio.h>
#include<stdlib.h>
int flag;
struct Node{
int num;
struct Node *next;
};

struct Node *Create(int n)   //创建链表
{
struct Node *current,*prev;
struct Node *head = NULL;
int cnt = 0;

while (cnt != n)
{
current = (struct Node *)malloc(sizeof(struct Node));

scanf("%d",¤t->num);

if (head == NULL)
head = current;
else
prev->next = current;
prev = current;
cnt++;
}
prev->next = NULL;
return head;
}

void Print(struct Node *head)  //打印链表
{
struct Node * current;
current = head;

printf("%d",current->num);
current = current->next;
while (current != NULL)
{
printf(" %d",current->num);
current = current->next;
}
printf("\n");
}

struct Node *Reverse(struct Node *head)  //反转链表
{
struct Node *current,*prev,*tmp;

current = head;
prev= current->next;
while (prev != NULL)
{
tmp = prev->next;
prev->next = current;
current = prev;
prev = tmp;
}
head->next = NULL;
head = current;
return head;
}

struct Node *Delete(struct Node *head,int num)  //删除特定结点
{
struct Node *current;
struct Node *prev;

current = head;

while (current->num != num && current->next != NULL)
{
prev = current;
current = current->next;
}

if (current->num == num)
{
if (head == current)
{
head = current->next;
}
else
{
prev->next = current->next;
}
}
else
{
flag = 0;
}

return head;
}

int main()
{
int N,repeat,x;
struct Node *head;

scanf("%d",&repeat);

while (repeat--)
{
flag = 1;
scanf("%d",&N);
head = Create(N);
scanf("%d",&x);
head = Reverse(head);
head = Delete(head,x);
head = Reverse(head);
if (flag)
printf("size=%d:",N-1);
else
printf("size=%d:",N);
Print(head);
}

return 0;
}


后来在和同学讨论的时候发现自己忘了释放内存,之后就补了Free函数

void Free(struct Node *head)
{
struct Node *current;

current = head;

while (current != NULL)
{
free(current);
current = current->next;
}
}


但是在添加Free函数调用它的时候主函数中只repeat了一次,没有再次进入while(repeat–)中,回看代码看了很久都没发现错误,除Free函数各模块代码都没有错,因为之前没有Free函数时都可以正常的输出。之后调试了一下程序,发现程序一直停止在

Free(head);


这个语句。问了下学姐,提醒我打出current地址,尝试打印了一下Free函数里面current变量的地址值



地址五个一次循环,难怪一直没有第二次进入while循环。但是在Free函数里面也没发现错误。最后求助了学长,学长说在Free函数里面,free掉current后又用到了current的值导致出错。然后我就尝试着修改了一下

while (current != NULL)
{
tmp = current;
free(current);
current = tmp->next;
}


运行之后还是老样子,想了很久没发现逻辑上的问题,学长学姐提点了一下,tmp和current指向同一个内存区,然后又free掉了,所以tmp最后也指向了不明内存区,跟第一次犯的错误根源上一样。现在也慢慢发现对于指针的内涵还是不是很懂。最后改成如此

void Free(struct Node *head)
{
struct Node *current,*tmp;

current = head;

while (current != NULL)
{
tmp = current->next;
free(current);
current = tmp;
}
}


附上某大神本题另一种解法:

#include <cstdio>
using namespace std;
struct Node{
int val;
Node *next;
}   tab[10086];
Node *p[10086];

int  n,repeat;
int  i,j,k,x;

int main()
{

scanf("%d",&repeat);

for(j=0; j<repeat; j++)
{
scanf("%d",&n);

for (i=0; i<=20; i++) p[i]=&tab[i];
//--1 read
for (i=1; i<=n; i++)
{
scanf("%d",&p[i]->val);
p[i-1]->next=p[i];
}
p
->next=NULL;

//--2 search x
scanf("%d",&x);
Node *tmp=NULL;
for (Node *tai=p[0]->next; tai!=NULL; tai=tai->next)
if (tai->val==x) tmp=tai;

//--3 delete tmp
for (Node *tai=p[0]; tai!=NULL; tai=tai->next)
if (tai->next!=NULL)
if (tai->next==tmp)
{
tai->next=tai->next->next;
n-=1;
}

//--4 Print
printf("size=%d:",n);
for (Node *tai=p[0]->next; tai!=NULL; tai=tai->next)
{
printf("%d",tai->val);
n-=1;
if(n>0) printf(" ");
}

if (j<repeat-1) printf("\n");
}
return 0;
}


总结

虽然在线提交的时候,数据点测试通过,但是没有考虑指针,通过简单的一个Free函数,折腾了好久,也错了很多次,但也因此更了解指针

指针的理解与应用仍需加强啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: