单链表是很基础的算法题
有至少三种方法可以实现:
1:将单链表储存为数组,然后按照数组的索引逆序进行反转。
2:使用三个指针遍历单链表,逐个链接点进行反转。
3:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾。
方法1的问题是浪费空间。方法2和方法3效率相当。一般方法2较为常用。
在这里只贴出前两种方法。
方法1:
bool List::printListFromTailToHead() {
Node* temp = m_pList; //m_pList即为头节点
int lengthOfList=0,len=0;
while( temp !=NULL)
{
lengthOfList ++; //算出链表长度
temp=temp->next;
}
vector<int> n(lengthOfList) ; //申请合适大小的容器vector
len = lengthOfList; //记录以便打印
temp=m_pList;
while(lengthOfList>0)
{
n[lengthOfList-1] =temp->data; //倒序放入数据
temp=temp->next;
lengthOfList--;
}
for(int i=0;i<len;i++) //正序打印
cout << n[i]<<endl; //若要得到新链表此处要修改为正序创建新链表
return true;
}
方法2:
bool List::listReversal()
{
Node* p=NULL;
Node* q=NULL;
Node* r=NULL;
p=m_pList; //头节点
q=p->next; //用来判断循环停止的条件
while(q) //原则是要用先保存,存完才能用,以免被覆盖
{
r=q->next; //保存下一个指向
q->next=p; // 修改指向
p=q; //保存当前结点,以便下次循环使用时能够找到
q=r; //向下循环
}
m_pList->next=NULL; //最后修改原头指针为尾指针
while(p)
{
cout<<p->data<<endl;
p=p->next;
}
return true;
}
提示:
以上两段代码需要配合以前笔记中单链表部分中Node.cpp以及List.cpp文件中代码,此外,为了可以使用容器vector,不要忘记加入#include<vector>
为了便于验证,在函数内打印出data,此非明智之举。
验证代码domo.cpp:
#include<iostream>
#include"List.h"
using namespace std;
int main(void)
{
Node node1;
node1.data=3;
node1.next=NULL;
Node node2;
node2.data=4;
node2.next=NULL;
Node node3;
node3.data=5;
node3.next=NULL;
Node node4;
node4.data=6;
node4.next=NULL;
Node node5;
node5.data=7;
node5.next=NULL;
List *pList = new List();
cout<<"insert from tail:"<<endl;
pList->ListInsertTail(&node1);
pList->ListInsertTail(&node2);
pList->ListInsertTail(&node3);
pList->ListInsertTail(&node4);
pList->ListInsertTail(&node5);
pList->ListTraverse();
cout<<"after reversal by way1:"<<endl;
pList->printListFromTailToHead();
//cout<<"after reversal by way2:"<<endl;
//pList->listReversal();
delete pList;
pList = NULL;
return 0;
}
运行结果:
注明:如有错误,还请指出。
本文借鉴自博客
http://blog.csdn.net/sicofield/article/details/8850269
该博客还有第三种方法的实现代码。