您的位置:首页 > 其它

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

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就是完成这部操作的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息