链表逆置(三种方法详解)

@Achievek

6-1 单链表逆转 (20 point(s))

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

##函数接口定义:

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

居中的图片: Alt

##代码入下

**

方法一:就地逆转或者说双链表逆转

思路在注释中 这种方法是最常用的方法 时间复杂度O(n) 空间复杂度

如果上面的没看懂就看下面的分析

总体分为循环核心操作与循环连接操作.
具体来说就是新建一个结构体指针prev,让其初始时指向NULL,然后让链表L的第一个元素指向prev(NULL),这样做形象地说就是将第一个元素从原始链表L剪下,并粘在了prev的前面,形成了新的链表List2;下一次循环的核心操作也是如此,即将第二个元素从被剪后的原始链表中(我们记作List’,L的第二个元素也就是List’的第一个元素)剪下,粘到List2上;但需要注意此时L的指向已经发生改变,故不能直接进行下一次循环操作,还需要一些循环连接操作,使循环得以进行.

那循环连接操作应该怎样做呢?

我们需要一个引入临时指针,在每次循环中指向着List’(第一次循环就是L)的第二个元素.这样,我们就可以保证每一次循环之后,我们都能找到List’的第一个元素,这是为了我们下一次的"剪"做铺垫.
那贴呢?由于我们并没有移动prev,它还指着NULL呢,于是我们就必须让prev也同时往前指,每次循环中都指向刚刚粘过来的元素.,
最后我们只要让L再指向刚刚临时指针temp指向的位置,就能保证下一次能直接把L所指元素直接剪下来拉.这样循环连接操作就完成拉>_
**
代码如下:

//  
List Reverse( List L )
{
 
 List prev=NULL;//初始时先让prev指向NULL
 List temp=L;//定义一个临时指针
 while(temp){
 temp=temp->next;//让临时指针每次循环时指向下一次要剪掉的元素,这是循环连接操作
 L->next=prev; //将L/L'的第一个元素从L/L'中剪下,粘到L2上,并指向prev,这是循环核心操作
 prev=L;//将prev往前指,使得下一次剪下来的元素能够粘到新链表L2的头,这是循环连接操作
 L=temp;//L返回临时指针所指位置,使得下一次可以直接将其剪下,这是循环连接操作
}
 return prev;
}

第二种方法:创建新节点法

具体来说就是,新建一个节点,然后让该节点的值等于链表第一个元素的值;再通过遍历原时链表,每次得到下一节点的值,再利用头插法插入到新链表的前面.这种思路有暴力解决内味儿了,时间复杂度O(n),空间复杂度O(n)

  List Reverse(List L)
{
 if (!L) exit(0);
 List head = L;
 List t;
 t = (List)malloc(sizeof(Node));
 t->Next = NULL;
 
 while (head&&head->Next)
 {
  t->Data = head->Data;
  head = head->Next;
  List q;
  q = (List)malloc(sizeof(Node));
  q->Data = head->Data;
  q->Next = t;
  t = q;
 }
 return t;
}


## 第三种方法:递归
递归的核心思想是将原问题化为更小规模的子问题;
所以我们先从简单情况入手
假设原链表只有一个结点p1,我们只需返回p1结点即可
假设原链表有两个...
生病了 回头补思路
  • 58
    点赞
  • 143
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值