一.对称翻转的思想
首先最直接的翻转就是对称翻转,以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就是完成这部操作的。