单链表递归和非递归两种翻转方法(手写链表)

一.对称翻转的思想

首先最直接的翻转就是对称翻转,以1为对称轴,把后面的数字依次插入最前边形成翻转


1    2    3    4    5

2   1   3    4    5

3    2    1    4    5

4    3    2    1    5

5    4    3    2    1


Current 指针指向1

pnext   指针指向2

 ptr       指针指向3

以1为对称轴,即用current指针一直指向1,每做一次循环,pnext所指的数字都移动到链表附加头的后面,然后pnext和ptr向右偏移一位(current不变),

每次循环的先决条件是pnext存在(ptr为空表示pnext为链表的最后一位)

那么可以有下面的伪代码


(1)初始状态:(初始化)

current一直指向1,//1的地址可以从初始状态时head->next得到;

pnext 等于current所指的下一个节点;

ptr 等于pnext所指的下一个节点;

(2)循环的先决条件是(pnext存在):

循环内部是:

1.1把current后的元素即pnext插到附加头的后面;

1.2把pnext和ptr都向右移一位(即以current为参考点重新赋值);

【小技巧】


#include<iostream>
using namespace std;
//链表节点结构体
struct LinkNode
{
 int data;
 LinkNode *link;
 LinkNode(LinkNode*p = NULL){ link = p; }
 LinkNode(constint&Item, LinkNode *p = NULL){ data = Item, link = p; }
};
//建立链表
class list
{
public:
 list(){ first = newLinkNode; }
 void input(int); //建立链表节点
 void output();
 void Reversal(); //翻转
 LinkNode*Reversalist(LinkNode*); //翻转(递归)
 LinkNode* getfirstnode();
 
private:
 LinkNode *first, *last;
};
 void list::input(int a)
{
 LinkNode *newnode;
 
 if (NULL==first->link)
 last = first;
 
 newnode = new LinkNode(a);
 if (newnode == NULL)
{
 cerr << "存储分配错误" << endl; exit(1);
}
 last->link = newnode;
 last = newnode;
 
}
void list::output()
{
 LinkNode *outdata =first->link;
 while (outdata)
{
 cout <<outdata->data << endl;
 outdata =outdata->link;
 }
}
//反转链表(非递归)
void list::Reversal()
{
 
 LinkNode *current, *pnext,*ptr;
 current = first->link;
 pnext = current->link;
 //ptr = pnext->link; 应放在循环里,当pnext存在才正确
 while (pnext)
{
 ptr =pnext->link;
 current->link = ptr;
 pnext->link =first->link;
 first->link = pnext;
 pnext = current->link;
}
}
//反转链表(递归)
 LinkNode*list::Reversalist(LinkNode* firstnode)
{
 if (NULL == firstnode ||NULL == firstnode->link)
 return firstnode;
 else
{
 LinkNode* newhead =Reversalist(firstnode->link);
 firstnode->link->link= firstnode; //注意参数
 firstnode->link = NULL;
 
 first->link = newhead;
 return newhead;
}
 
}
 
LinkNode*list::getfirstnode()
{
 return first->link;
}
void main()
{
list testlist;
testlist.input(1);
testlist.input(2);
testlist.input(3);
testlist.input(4);
testlist.input(5);
testlist.input(6);
testlist.input(7);
testlist.output();
 
testlist.Reversal();
cout <<"----------------" << endl;
testlist.output();
cout <<"----------------" << endl;
testlist.Reversalist(testlist.getfirstnode());
testlist.output();
system("pause");
}



 

1.递归翻转单链表的算法的总结:

 

LinkNode*list::Reversalist(LinkNode* firstnode)

{

if (NULL == firstnode ||NULL == firstnode->link)

return firstnode;

else

{

LinkNode* newhead =Reversalist(firstnode->link); //-----------------1

firstnode->link->link= firstnode; //重要的翻转操作--2

firstnode->link = NULL;

//first->link =newhead;// ----------------------------3

return newhead;

}

}

(1)首先这种递归方法只关心结点指针

函数的参数中输入的节点指针就是要翻转的单链表的首节点指针

递归思想:

每次递归要完成的操作是:把当前参数所指向的结点的pnext成员指向上一个结点,修改链表方向,完成链表方向的翻转


重要延伸:

 

这种递归翻转可以翻转以任意位置开始的后面的单链表

 

1->2->3->4->5->6->7->8->9->10

 

假如结点 3 的指针是 node3,Reversalist(node3)表示从结点3开始翻转其后的链表,此时

 

1->2->

 

3<-4<-5<-6<-7<-8<-9<-10

Reversalist(node3)返回的值是翻转后的链表的首节点

1->2->此时要指向翻转后的链表的首节点来连成一个完整的链表,标注3就是完成这部操作的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值