单链表逆转(数据结构)

这题看了很多个版本,但基本看不懂,毕竟最怕就是没有注释自己来推,更准确点说,数据结构需要的是思路的传达而不是直接给个代码。最后在一个博主那里看到了他的思路详解,感觉需要学习一下。

6-1 单链表逆转(20 分)

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

函数接口定义:

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
这题的编码主要是在不清楚如何接收数据条件下去打,一开始有些好奇他的输入会不会对于我后面的代码有影响,不过其实多想了,毕竟给你的是已经有数据的链表L1,你直接返回修改后的链表就OK。但思路也会有一些需要琢磨的地方,接下来我就详细说说这思路。


(1).开始的时候,创建一个指针域空的指针为Prev, 指向内容为空(NULL),当List Reverse( List L );这个函数接收的链表内容为A,B,C,D(为了简便我用字母,里面定义是整型,但思路一样适用),如下图:


第一步,用 L->Next  指向 Prev,  切断 L->Next 与B直接的联系,这样一来就变成了下面的样子。


用代码实现就是: L->Next = Prev;


(2).有了第一步,就可以想到第二部怎么做了,但还需要注意一些细节,我们需要修改Prev的指针指向的位置,还有指针L指向的位置,为的是下一步将 B 也连接到 A 指针的后面,如下图:


此时将L重新指向原来的链表的第一个位置,但原来的链表少了一个A,此时就指向了B,让temp指向下C。用代码实现就是:

                                       Prev = L;

                                       L = Temp;

                                       Temp = L->Next;

在这里就实现两个新的链表。


(3)之后就是继续按照第一步走,将L->Next=Pre; 就是让B的Next指针指向A,如下图:


以此类推,相信你应该明白如何移动D了。最后就是结束条件了,在这里可以用 Temp 或 L ,正确的是该用

while(L)来退出,至于有人会误用Temp甚至L->Next,大多数因为一开始就有先写条件的习惯,我的建议是退出条件最后写,不容易写错。那么具体的代码实现如下了。

List Reverse( List L )
{
List Temp, Prev;
Prev = NULL;
while(L)
{
Temp = L->Next;
L->Next = Prev;
Prev = L;
L = Temp;
}
return Prev;

}

而全部代码如果想具体看完也有,还有递归的思路也有

这个博主的思路很详细,我就是从这位博主这里学习的 ,超级感谢这位博主 点击打开链接

这个是具体代码,最好只用来调试。

#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;  
}  
  
/* 建立链表 */  
List Read()  
{  
    List head = NULL;  
    List current;  
    List prev = NULL;  
    int len = 0;  
    scanf("%d", &len);  
    if (len == 0)   return NULL;  
    
    while (len--)   
    {  
        current = (List)malloc(sizeof(struct Node));  
        if (head == NULL)  
            head = current;  
        else  
        prev->Next = current;  
        current->Next = NULL;  
        scanf("%d", &current->Data);  
        prev = current; 
    }  
    return head;  
}  
  
void Print(List L)  
{  
    List p = L;  
    List s = L;  
    List temp;  
    if (p == NULL)  
        printf("NULL");  
    else  
        printf("\n");  
    while (p!=NULL) {  
        printf("%d ", p->Data);  
        p = p->Next;  
    }  
}  
  
List Reverse( List L )  
{  
    List Temp, Prev;  
    Prev = NULL;  
    while(L)  
    {  
        Temp = L->Next;  
        L->Next = Prev;  
        Prev = L;  
        L = Temp;  
    }  
    return Prev;  
}  

编译器:DEV C++

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值