单链表实现反转的3种方法示例代码

前言

单链表的操作是面试中经常会遇到的问题,今天总结一下反转的几种方案:

1 ,两两对换

2, 放入数组,倒置数组

3, 递归实现

代码如下:

#include<stdio.h>
#include<malloc.h>
typedef struct Node
{

 int data;
 struct Node *pnext;

} Node,*pnode;
pnode CreateNode()
{

 pnode phead=(pnode)malloc(sizeof(Node));
 if(phead==NULL)
 {
  printf("fail to allocate memory");
  return -1;
 }
 phead->pnext=NULL;
 int n;
 pnode ph=phead;
 for(int i=0; i<5; i++)
 {

  pnode p=(pnode)malloc(sizeof(Node));
  if(p==NULL)
  {
   printf("fail to allocate memory");
   return -1;
  }
  p->data=(i+2)*19;
  phead->pnext=p;
  p->pnext=NULL;
  phead=phead->pnext;

 }
 return ph;
}
int list(pnode head)
{
 int count=0;
 printf("遍历结果:\n");
 while(head->pnext!=NULL)
 {
  printf("%d\t",head->pnext->data);
  head=head->pnext;
  count++;
 }
 printf("链表长度为:%d\n",count);
 return count;
}
pnode reverse2(pnode head)//两两节点之间不断交换
{
 if(head == NULL || head->next == NULL)
 return head;
 pnode pre = NULL;
 pnode next = NULL;
 while(head != NULL){
  next = head->next;
  head->next = pre;
  pre = head;
  head = next;
}
 return pre;
}
void reverse1(pnode head,int count)//把链表的节点值放在数组中,倒置数组
{
 int a[5]= {0};

 for(int i=0; i<count,head->pnext!=NULL; i++)
 {
  a[i]=head->pnext->data;
  head=head->pnext;

 }
 for(int j=0,i=count-1; j<count; j++,i--)
  printf("%d\t",a[i]);

}

pnode reverse3(pnode pre,pnode cur,pnode t)//递归实现链表倒置
{

 cur -> pnext = pre;
 if(t == NULL)
  return cur; //返回无头节点的指针,遍历的时候注意
 reverse3(cur,t,t->pnext);

}

pnode new_reverse3(pnode head){ //新的递归转置

 if(head == NULL || head->next == NULL)
  return head;
 pnode new_node = new_reverse3(head->next);
 head->next->next = head;
 head->next = NULL;
 return new_node; //返回新链表头指针

}
int main()
{
 pnode p=CreateNode();
 pnode p3=CreateNode();
 int n=list(p);
 printf("1反转之后:\n");
 reverse1(p,n);
 printf("\n");
 printf("2反转之后:\n");
 pnode p1=reverse2(p);
 list(p1);
 p3 -> pnext = reverse3(NULL,p3 -> pnext,p3->pnext->pnext);
 printf("3反转之后:\n");
 list(p3);
 free(p);
 free(p1);
 free(p3);
 return 0;
}

毫无疑问,递归是解决的最简单方法,四行就能解决倒置问题。

思路参考:https://www.jb51.net/article/156043.htm

这里注意: head ->next = pre; 以及 pre = head->next,前者把head->next 指向 pre,而后者是把head->next指向的节点赋值给pre。如果原来head->next 指向 pnext节点,前者则是head重新指向pre,与pnext节点断开,后者把pnext值赋值给pre,head与pnext并没有断开。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • C语言之单链表的插入、删除与查找

    单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素.要实现对单链表中节点的插入.删除与查找的功能,就要先进行的单链表的初始化.创建和遍历,进而实现各功能,以下是对单链表节点的插入.删除.查找功能的具体实现: #include<stdio.h> #include<stdlib.h> #include<string.h> typedef int ElemType; /** *链表通用类型 *ElemType 代表自定义的数据类型 *struct

  • 深入单链表的快速排序详解

    单链表的快排序和数组的快排序基本思想相同,同样是基于划分,但是又有很大的不同:单链表不支持基于下标的访问.故书中把待排序的链表拆分为2个子链表.为了简单起见,选择链表的第一个节点作为基准,然后进行比较,比基准小得节点放入左面的子链表,比基准大的放入右边的子链表.在对待排序链表扫描一遍之后,左边子链表的节点值都小于基准的值,右边子链表的值都大于基准的值,然后把基准插入到链表中,并作为连接两个子链表的桥梁.然后分别对左.右两个子链表进行递归快速排序,以提高性能.但是,由于单链表不能像数组那样随机存储

  • C语言创建和操作单链表数据结构的实例教程

    1,为什么要用到链表 数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了灵活性.但数组也同样存在一些弊病.如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序设计中针对不同问题有时需要3 0个大小的数组,有时需要5 0个数组的大小,难于统一.我们只能够根据可能的最大需求来定义数组,常常会造成一定存储空间的浪费. 我们希望构造动态的数组,随时可以调整数组的大小,以满足不同问题的需要.链表就是我们需要的动态数组.它是在程序的执行过程中根据需要有数据存储就向系统要求

  • C语言实现单链表逆序与逆序输出实例

    单链表的逆序输出分为两种情况,一种是只逆序输出,实际上不逆序:另一种是把链表逆序.本文就分别实例讲述一下两种方法.具体如下: 1.逆序输出 实例代码如下: #include<iostream> #include<stack> #include<assert.h> using namespace std; typedef struct node{ int data; node * next; }node; //尾部添加 node * add(int n, node * h

  • 用C语言实现单链表的各种操作(一)

    最近,从新复习了一下数据结构中比较重要的几个部分,现在把自己的成果记录下来,主要就是仿照严蔚敏的<数据结构>(C 语言版),中的例子和后面的习题进行改编的.首先,是单链表的各种实现,其中,包含了一些常考的知识点.例如,单链表的逆置,单链表的合并,找到单链表的中间节点等的算法实现.下面这个是单链表的结构体的定义: 复制代码 代码如下: typedef struct LNode{ ElemType data; struct LNode *next;}LinkList; 下面的基本的单链表的操作:其

  • 浅析C++中单链表的增、删、改、减

    首先是是一个简单的例子,单链表的建立和输出.程序1.1 复制代码 代码如下: #include<iostream>#include<string>using namespace std;struct Student{ string name; string score; Student *next;//定义了指向Candidate类型变量的指针};int main(){ int n;// cout<<"请输入学生的总数:"; cin>>n

  • C#数据结构之单链表(LinkList)实例详解

    本文实例讲述了C#数据结构之单链表(LinkList)实现方法.分享给大家供大家参考,具体如下: 这里我们来看下"单链表(LinkList)".在上一篇<C#数据结构之顺序表(SeqList)实例详解>的最后,我们指出了:顺序表要求开辟一组连续的内存空间,而且插入/删除元素时,为了保证元素的顺序性,必须对后面的元素进行移动.如果你的应用中需要频繁对元素进行插入/删除,那么开销会很大. 而链表结构正好相反,先来看下结构: 每个元素至少具有二个属性:data和next.data

  • 看图深入理解单链表的反转

    如何把一个单链表进行反转? 方法1:将单链表储存为数组,然后按照数组的索引逆序进行反转. 方法2:使用3个指针遍历单链表,逐个链接点进行反转. 方法3:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾. 方法4:   递归(相信我们都熟悉的一点是,对于树的大部分问题,基本可以考虑用递归来解决.但是我们不太熟悉的一点是,对于单链表的一些问题,也可以使用递归.可以认为单链表是一颗永远只有左(右)子树的树,因此可以考虑用递归来解决.或者说,因为单

  • 单链表反转python实现代码示例

    单链表的反转可以使用循环,也可以使用递归的方式 1.循环反转单链表 循环的方法中,使用pre指向前一个结点,cur指向当前结点,每次把cur->next指向pre即可. 代码: class ListNode: def __init__(self,x): self.val=x; self.next=None; def nonrecurse(head): #循环的方法反转链表 if head is None or head.next is None: return head; pre=None; c

  • C++中单链表的建立与基本操作

    准备数据 准备在链表操作中需要用到的变量及数据结构 示例代码如下: 复制代码 代码如下: struct Data   //数据结点类型 { string key;  //关键字  string name; int age;};struct CLType  //定义链表结构 { Data nodeData; Data *nextNode;}; 定义了链表数据元素的类型Data以及链表的数据结构CLType.结点的具体数据保存在一个结构Data中,而指针nextNode用来指向下一个结点. 我们可以

随机推荐