c语言链表结点后倒置,单链表的倒置(递归和非递归)

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

链表倒置

干货之前的一点废话

自己下意识的觉得数据结构对编程来说应该是基础而且重要的东西。毕竟关于各种语言的特性,只能在大量的使用中渐渐领悟,而关于数据结构,关于算法却是在各种语言中通用的。

在人生中第一次求职面试中,面试官问了我一个简单而基础的问题——单链表的倒置。这个问题简单考察了关于链表的知识,当时的我没答上来,后来解决了这个问题之后,我对C语言的指针与引用也有了更清晰的认识。

指针与引用

在讲链表倒置之前先提一点关于C的东西,那就是&与*,前者表示引用,而后者表示指针。

所谓指针,实际上就是保存地址的一种变量。而引用,就是取变量的存储地址。例如:1

2

3

4

5

6

7

8int *p=(int *)malloc(sizeof(int));

int *p=NULL;

int a=0;

int *p=a;

//因为指针所指的是内存地址,所以在给指针赋初值时,只能用已得到内存的变量,或是采用malloc动态分配内存。如果暂时不确定指针的指向,应将它初始化为NULL。

int a=0;

int * p=a;

//这里声明了一个整型指针变量p,p表示存储一个整型变量的地址,而*p则表示p地址里存储的整型变量。

我们可以从下面这段代码体会一下:1

2

3

4

5

6

7#include

void main(){

int a=2;

int *b=&a; //这行代码也可以变成这样:int *b=NULL; b=&a;就是说int *b=&a; 中的*只是为了声明b是一个指针,在程序的其它地方*b表示一个整型变量,是不能用一个地址给它赋值的。

if(&a==b)

printf("&a = b");

}

最后再来总结一下,p是一个指针变量。

那么&p就表示存储p变量的地址,p表示&p这个地址中存储的值,也是一个地址,通俗的讲就是指针p所指变量的地址,而*p则表示指针p所指的变量。也就是p所指的地址中保存的值

C语言实现单链表

要实现链表的倒置,我们应该先明确链表是什么。

0ed058e46053a7dcef2f73e0995b13bd.png

这里为什么要明确头结点和尾节点的概念呢,只有知道头结点和尾节点在哪,你才能找到自己分配给每一个结点的内存,在不需要它的时候,才能准确地把它释放掉。

链表的名字已经告诉了我们它是像铁链一样一环扣一环的东西。而它的每一环是这样的:1

2

3

4typedef struct LNode{

int data;

struct LNode * next;

}LinkNode;

这里有一点递归的思想,一个结构体中保存了两个变量,data保存的是这个节点的信息,在这个实例中它是整型的,而next则是与这个结构体相同类型的指针变量,它指向“下一节铁链”。

在我们对链表有了一个概念之后,我们将试着造出一节节铁链并把它连起来。1

2

3

4

5

6

7

8

9

10

11

12

13void CreatList(int a[],LinkNode *L,int n){

int i=0;

LinkNode *s1=L,*s2=NULL;

for(i=0;i

printf("%dn",i);

s2=(LinkNode *)malloc(sizeof(LinkNode)); //这里使用了动态分配内存的方法。

s2->data=a[i];

s1->next=s2;

s1=s2;

}

s1->next=NULL;

}

我们可以写一个函数来直观地感受一下链表。1

2

3

4

5

6

7

8

9void Traverse(LinkNode *L){

int i=0;

LinkNode *s3=L;

while(s3!=NULL){

i++;

printf("第%d节铁链为%dn",i,s3->data);

s3=s3->next;

}

}

链表倒置

非递归方式1

2

3

4

5

6

7

8

9

10

11

12void Reverse1(LinkNode **L){ //这里直接把L指针的地址作为参数传进去了,函数能够改变L指针的值。

LinkNode *next=NULL,*prev=NULL;

while(*L!=NULL){

next=(*L)->next;

(*L)->next=prev;

prev=*L;

*L=next;

}

*L=prev;

Traverse(*L);

}1

2

3

4

5

6

7

8

9

10

11LinkNode * Reverse2(LinkNode *L){//这里实参的值不会发生改变,所以需要返回头结点

LinkNode *next=NULL,*prev=NULL;

while(L!=NULL){

next=L->next;

L->next=prev;

prev=L;

L=next;

}

return prev;

}

递归方式1

2

3

4

5

6

7

8LinkNode * Reverse3(LinkNode *L){//头结点需要提前保存。

LinkNode *s=NULL;

if(L->next==NULL)

return L;

s=Reverse3(L->next);

s->next=L;

L->next=NULL;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值