PTA 链表删除结点的题目测试
链表删除结点
题目描述
输入一个正整数repeat(0 < repeat < 10),做repeat次下列运算:
输入一个正整数n(0 < n < 10)和一组( n 个 )整数,建立一个单向链表
再输入一个整数x,将链表中最后一个与x相等的整数删除。
输入格式
见输入样例
输出格式
见输出样例
输入样例
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[n]->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函数,折腾了好久,也错了很多次,但也因此更了解指针
指针的理解与应用仍需加强啊
PTA 链表删除结点的题目测试的更多相关文章
- pta 奇数值结点链表&&单链表结点删除
本题要求实现两个函数,分别将读入的数据存储为单链表.将链表中奇数值的结点重新组成一个新的链表.链表结点定义如下: struct ListNode { int data; ListNode *next; ...
- leetCode:237 删除链表的结点
删除链表的结点 编写一个函数,在给定单链表一个结点(非尾结点)的情况下,删除该结点. 假设该链表为1 -> 2 -> 3 -> 4 并且给定你链表中第三个值为3的节点,在调用你的函数 ...
- 237 Delete Node in a Linked List 删除链表的结点
编写一个函数,在给定单链表一个结点(非尾结点)的情况下,删除该结点. 假设该链表为1 -> 2 -> 3 -> 4 并且给定你链表中第三个值为3的节点,在调用你的函数后,该链表应变为 ...
- 数据结构:链表 >> 链表按结点中第j个数据属性排序(冒泡排序法)
创建结点类,链表类,测试类 import java.lang.Object; //结点node=数据date+指针pointer public class Node { Object iprop; p ...
- A Magic Lamp---hdu3183(链表删除| RMQ)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 给你一个长度<1000的数a,和m<len(a); 让把数a删除m个数字之后剩下的数 ...
- 删除Oracle Online Redo 测试
删除Oracle Online Redo 测试 SQL> select * from v$log; GROUP# THREAD# SEQUENCE# BYTES BLOCKS ...
- xml解析-jaxp删除结点
jaxp删除结点 / 删除sex结点 * 1.创建解析器工厂 * 2.根据解析器工厂创建解析器 * 3.解析xml返回document * * 4.得到sex结点 * 5.得到sex的父节点 getP ...
- C语言:将字符串中的字符逆序输出,但不改变字符串中的内容。-在main函数中将多次调用fun函数,每调用一次,输出链表尾部结点中的数据,并释放该结点,使链表缩短。
//将字符串中的字符逆序输出,但不改变字符串中的内容. #include <stdio.h> /************found************/ void fun (char ...
- LeetCode 876. Middle of the Linked List(获得链表中心结点)
题意:获得链表中心结点.当有两个中心结点时,返回第二个. 分析:快慢指针. /** * Definition for singly-linked list. * struct ListNode { * ...
随机推荐
- Jenkins进阶系列之——18Jenkins语言本地化
在Jenkins中,英语一大片,看着各种蛋疼.非常高兴的是,Jenkins作为一个主流流行的持续构建工具,提供了一个本地化语言的配置界面. 你可以找到它,在Jenkins每页的左下角.如下图: 点击帮 ...
- 我理解的Hanlder--android消息传递机制
每一个学习Android的同学都会觉得Handler是一个神奇的东西,我也一样,开始我以为我懂了Handler的机制,后来发现自己是一知半解,昨天想想,我能否自己实现一个Handler,让子线程与Ac ...
- ASP.NET 页面缓存
ASP.NET 实现页面缓存页面缓存的使用方法非常的简单,只需要在aspx页的顶部加一句声明<%@ OutputCache Duration="60" VaryByParam ...
- JavaWeb之jsp编译为java源码的文件地址
..\..\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\project_ ...
- GO语言数组和切片实例详解
本文实例讲述了GO语言数组和切片的用法.分享给大家供大家参考.具体分析如下: 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式: ...
- linux android真机测试
1. 在终端运行 lsusb 会发现结果有会有如下类似记录: Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 002 ...
- oracle递归查询树的SQL语句
来自互联网 SELECT * FROM a_ParkingLot AWHERE A.REGIONID IN( SELECT r.ID FROM a_region r START WITH ...
- 用Okhttp框架登录之后的Cookie设置到webView中(转)
1.webview中设置: [java] view plain copy @SuppressWarnings("deprecation") public void synCooki ...
- zabbix监控网络的出入口流量
首先我们登录到zabbix 点击配置---->模板-->Template OS Linux 下的监控项 点击右上角的添加监控项目 我们的服务器是在Ucloud上的,我们的网卡名称为eth0 ...
- CNN中的BN
w权值的初始化,之前最好的方法是 也就是输入神经元和输出神经元中随机一个数,然后除以输入神经元的个数开根号 因为全连接层波动较大,所以加在FC后面 这里Y,b是为了对信息的一个还原