C/C++数据结构---单链表逆转(PTA)

个人主页:

仍有未知等待探索_数据结构,C语言疑难,小项目-CSDN博客

专题分栏:

数据结构_仍有未知等待探索的博客-CSDN博客

目录

一、前言

二、题目

函数接口定义:

裁判测试程序样例:

输出样例:

三、理解+代码

1.理解

2.分析 

3.代码 


一、前言

        对于初次学习数据结构,一定要把最基础的,最简单的样例给写的十分熟练,自己每写一遍也将会增加对其结构的理解,为接下来更难的知识打好坚实的基础 !一定一定不要一味的照着别人的代码敲,最后一定要自己独自去写!

二、题目

本题要求实现一个函数,将给定的单链表逆转。

函数接口定义:

List Reverse( List L );

其中List结构定义如下:

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */

L是给定单链表,函数Reverse要返回被逆转后的链表。

裁判测试程序样例:

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
    ElementType Data;
    PtrToNode   Next;
};
typedef PtrToNode List;

List Read(); /* 细节在此不表 */
void Print( List L ); /* 细节在此不表 */

List Reverse( List L );

int main()
{
    List L1, L2;
    L1 = Read();
    L2 = Reverse(L1);
    Print(L1);
    Print(L2);
    return 0;
}

/* 你的代码将被嵌在这里 */

5
1 3 4 5 2

输出样例:

1
2 5 4 3 1

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

三、理解+代码

1.理解

在看到这道题目的时候,可能会突然感觉很熟悉,好像是跟前学过的字符串逆转很相似。

字符串逆转的思路很多样:

一、非递归:就是用两个变量,一个变量left指向字符串的第一个字符,另一个变量right指向字符串的最后一个字符,然后进行交换,判断一下结束的标志就好了。(关键代码如下)

while(left<right)
{
    //交换
}

二、递归,根据递归的特性来实现逆序

#include<stdio.h>
int my_strlen(char* arr)
{
	if (*arr != '\0')
		return 1 + my_strlen(arr + 1);
	else
		return 0;
}
char* rev(char* arr)
{
	char tmp = *arr;
	int len = my_strlen(arr);
	*arr = *(arr + len - 1);
	*(arr + len - 1) = '\0';
	if (my_strlen(arr+1) >=2)
		rev(arr + 1);
	*(arr + len - 1) = tmp;
}
int main()
{
	char arr[] = "abcdef";
	rev(arr);
	printf("%s", arr);
	return 0;
}

问:那说回来,单链表逆序是不是也可以采用这样的方式呢?

答:1、如果用第一种思路的话,指向最后节点的指针如何往前移呢,这得需要用要一个一重循环来找到只想最后节点的前一个节点的地址,比较麻烦。2、如果用第二种思路的话,就在纸上写一写的话,感觉是能用的,这就交给大家一个小小的思考题(根据上述的递归写法来进行仿照,看看能不能实现)。

2.分析 

那除了字符串逆转的用的那些思路,还有没有根据链表的特性来完成这个单链表的逆转呢?

在创建链表的时候,我介绍过两种方法,一种是头插法,另外一种是尾插法,这两种方法有什么特点呢?各位还记得吗?(不记得的链接如下:)数据结构---顺序表---链式存储结构1(不带头节点)_仍有未知等待探索的博客-CSDN博客 

头插法和尾插法最本质的特征就是创建完,数据的存储顺序与输入数据的顺序。 头插法是存储顺序与输入数据的顺序相反,尾插法是存储顺序与输入数据的顺序相同。

所以,根据头插法的思路,我们可不可以将单链表的数据一个个的按顺序读取出来,然后在用头插法新建一个链表进行存储呢?答案是可以的。而且这种方式的话比之前的思路更简便、更加体现了链表的一些特性。

  //头插法不需要对head是否为空进行判断,再之前的文章中也讲解过。

3.代码 

List Reverse( List L )
{
    List p=L,head=NULL,q;//创建一个头指针
    //头插法不需要对head是否为空进行判断,再之前的文章中也讲解过
    while(p!=NULL)
    {
        q=(List)malloc(sizeof(struct Node));
        q->Next=NULL;
        q->Data=p->Data;
        q->Next=head;
        head=q;
        p=p->Next;
    }
    if(L!=NULL)
        L->Next=NULL;
    return head;
}

 谢谢大家的支持!

猜你喜欢

转载自blog.csdn.net/qq_73435980/article/details/133345851
今日推荐