链表基础3(超简单)--单链表的逆序

链表基础和链表的插入删除可以看上两篇博客!
链表基础1(超简单)–创建一个长度为n的单链表
链表基础2(超简单)–单链表的插入和删除
这一节我们来看一下链表的逆序,稍微有一丢丢的难度!
链表是由一个个的节点构成的嘛!话不多说上图理解!
在这里插入图片描述
有这样一个链表,除去表头就是a1,a2,a3对吧!如果我们要逆序,逆序完成应该是a3,a2 a1。我们要如何逆序呢?
便于观察我们简写一下链表格式:

表头 a1 a2 a3 a4 a5 a6 a7.......

如果我们将a2提出以来,a1和a3相连是不是就是

表头 a2 a1 a3 a4 a5 a6 a7.......

如果我们把a3提出来,a1,a4相连是不是就是:

表头 a3 a2 a1 a4 a5 a6 a7.......

我们在多写几个
提出a4,a1和a5相连是不是就是

表头 a4 a3 a2 a1 a5 a6 a7.......

看起来是不是很简单呢,一步步提出再连接是不是不就逆序完成了嘛。

接下来到重点了,代码实现。
先看一下链表节点结构

typedef struct lianbiao
{
        int date;
        struct lianbiao *pnext;
}link;
link *phead;//头节点

首先我们是不是要打断a2嘛,所以我们是不是要先保存a2的地址。
我们要怎样表示a2的地址呢?
这里再提一下链表的逆序,表头不变。
设表头地址是L,我们在增加一个变量current

current=L->pnext;

这个是不是a1的地址,存在表头的指针域中!
哪a2的地址是不是就是current->pnext,既然我们要保存a2的地址是不是还要在增加一个参数,我们就在增加一个参数p
a2的地址是不是就是

p=current->pnext

这样我们就保存了a2的地址,然后我们让a1,a3相连

current->pnext=p->pnext

这样是不是a1,a3连起来了
接下来我们是不是需要把表头,a2,a1连起来,不就构成 L->a2->a1->a3…了嘛
我们在实现a2->a1->a3…

p->pnext=L->pnext

这是不是a2连上了a1,就剩下了一个表头和a2了嘛,我们在连一下

L->pnext=p

这样不就成功了第一步了嘛 L->a2->a1->a3…

p=current->pnext
current->pnext=p->pnext
p->pnext=L->pnext
L->pnext=p

就这样四句代码,是不是很简单呀!
我们继续下去

L->a2->a1->a3->a4->a5->a6......

再次看一下哪四句代码,第一句是不是保存a2的地址为p
但是执行完第二句a1连接a3的操作后,current->pnext是不是保存的是a3的地址了?注意,a2的地址已经保存在参数p中了。如果我们再次执行一遍这四个语句

p=current->pnext

执行完后p是不是就是a3的地址了,他是不是存放在a1的指针域里面。

current->pnext=p->pnext

再执行完这一句你会发现是不是a1和a4连接了现在是不是就是

表头 a2 a1 a4  提出来了a3

是不是只用再实现a3和表头,a2相连就构成了

表头 a3 a2 a1.....
p->pnext=L->pnext

执行完这一句是不是a2的地址放在了a3的指针域里面,实现了

a3 a2 a1.....

就差一个表头了

L->pnext=p

这样是不是就构成了表头 a3 a2 a1.....
回头看一下执行完第二句子后,p的数值是不是又变成了a4的地址
我们是不是提出a4,a1,a5相连,再连表头是不是又变成了

表头 a4 a3 a2 a1 a5.......

写到这里你这会应该发现不是只要循环执行哪四个语句就行了
害!!!累死我了
p的地址是不是一直再变,a2,a3,a4…我们可以把这个作为循环判断条件把!我们给封装成一个函数

void turn(link *L)
{
    link *current,*p;
    current=L->pnext;
    while(current->pnext!=NULL)
    {
        p=current->pnext;//保存a2地址
        current->pnext=p->pnext;//a1连a3,孤立a2
        p->pnext=L->pnext;//a2连a1
        L->pnext=p;//a2连头节点
    }
}

到此!结束!!!
附上完整程序代码:

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

typedef struct lianbiao
{
        int date;
        struct lianbiao *pnext;
}link;
link *pnew;//新节点
link *phead;//头节点
link *ptemp;//临时节点
link *pdel;//删除功能用
link *pins;//插入功能用
int count=1;
void creat(void);
void add(void);
void del(void);
void ins(void);
void turn(link *L);
int main()
{
    int n,i;
    printf("请输入所需要创建的链表长度,不可为0\n");
    scanf("%d", &n);
    creat();
    for(i=0;i<n-1;i++)
    {
        add();
    }
  printf("链表创建完毕,输出链表所有数据\n");
  //printf("%d ", phead->date);
  for(ptemp=phead;ptemp!=NULL;ptemp=ptemp->pnext)
   {
       printf("%d ", ptemp->date);
   }
   ins();

   del();
   printf("删除后的链表数据\n");
   ptemp=phead;
   while(ptemp!=NULL)
   {
       printf("%d ", ptemp->date);
       ptemp=ptemp->pnext;
   }
    printf("\n");
    printf("链表逆序:\n");
    turn(phead);
   return 0;
}
void creat(void)
{
    phead=(link*)malloc(sizeof(link));
    phead->pnext=NULL;
    phead->date=0;
    //memset(link,0,sizeof(link));
}
void add(void)
{
    pnew=(link*)malloc(sizeof(link));
    pnew->date=count;
    pnew->pnext=NULL;
    ptemp=phead;
    while(ptemp->pnext!=NULL)
    {
        ptemp=ptemp->pnext;
    }
    ptemp->pnext=pnew;
    //pnew=NULL;
    count++;
}
void del(void)
{
    int x;
    int flag=0;
    printf("\n");
    printf("请输入你要删除的数\n");
    scanf("%d", &x);
    ptemp=phead;
    while(ptemp->pnext!=NULL)
    {
        if(ptemp->pnext->date==x)
        {
            flag=1;
            break;
        }
        ptemp=ptemp->pnext;
    }
    pdel=ptemp->pnext;
    if(flag==1)
    {
        ptemp->pnext=pdel->pnext;
        free(pdel);
    }
}
void ins(void)
{
    int y;
    int flag=0;
    printf("\n");
    printf("请输入你要插入的数的位置\n");
    scanf("%d", &y);
    ptemp=phead;
    while(ptemp->pnext!=NULL)
    {
        if(ptemp->pnext->date==y)
        {
            flag=1;
            break;
        }
        ptemp=ptemp->pnext;
    }
    if(flag=1)
    {
        printf("已找到插入位置\n");
    }
    pnew=(link*)malloc(sizeof(link));
    pnew->date=99;
    pins=ptemp->pnext;//保存·后一个节点地址
    ptemp->pnext=pnew;
    pnew->pnext=pins;
    printf("插入完成,输出所有数据\n");
    ptemp=phead;
    while(ptemp!=NULL)
    {
        printf("%d ", ptemp->date);
        ptemp=ptemp->pnext;
    }

}
//逆序头节点不变
void turn(link *L)
{
    link *current,*p;
    current=L->pnext;
    while(current->pnext!=NULL)
    {
        p=current->pnext;//保存a2地址
        current->pnext=p->pnext;//a1连a3,孤立a2
        p->pnext=L->pnext;//a2连a1
        L->pnext=p;//a2连头节点

        //每循环一次,输出一次逆序结果
           ptemp=phead;
          while(ptemp!=NULL)
          {
             printf("%d ", ptemp->date);
              ptemp=ptemp->pnext;
          }
           printf("\n");
    }
}

运行结果
在这里插入图片描述
我再链表头节点的数据域里面也存了数据,输出也包括头节点。不是错误哟!
感谢评阅,如有问题可以在评论区或者私信我!欢迎指正交流。qq:918619587

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值