单链表递归和非递归两种翻转方法(手写链表)
2016-10-25 11:24
288 查看
一.对称翻转的思想
首先最直接的翻转就是对称翻转,以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为对称轴,把后面的数字依次插入最前边形成翻转
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就是完成这部操作的。
相关文章推荐
- 链表面试题--两种方法逆序打印单链表(栈和递归)
- 用递归和非递归两种方法翻转一个链表
- 用递归和非递归两种方法翻转一个链表
- 用递归和非递归的方法 逆置单链表
- 单链表的设计和非递归,递归逆序方法源代码,dev-c++下可直接运行.
- 从尾到头打印链表(五种方法包括链表翻转、递归、栈、容器逆序)
- 面试题:单链表逆置(分别用非递归和递归两种方法实现)
- 从头到尾打印链表,两种方法:用栈先进后出,另一种为递归。
- 两种方法求n!,递归和非递归调用
- 单链表翻转(递归与非递归)
- 两种方法实现从尾到头打印链表--栈和递归
- 已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。使用非递归方法以及递归方法。
- 链表翻转的图文讲解(递归与迭代两种实现)
- 递归求集合子集(两种方法实现(数组,链表))
- 单链表倒置,给你一个头指针,用递归与非递归的方法分别实现;
- 两种方法(递归,非递归)实现单链表的逆转
- 链表反转(使用递归和非递归两种方式)
- 链表面试题-合并两个有序单链表(递归和非递归)
- 链表有环判断,快慢指针两种方法/合并链表/删除重复元素/二分递归和while
- 将单链表翻转的两种方法