您的位置:首页 > 职场人生

面试题四 从尾到头打印链表

2014-03-17 22:55 531 查看
题目

  输入一个链表的头结点,从尾到头反过来打印出每个结点的值。

分析

  这个题目有三种解法,可以根据实际情况灵活选用。

解法一 堆栈法

  设立一个堆栈,然后遍历一次链表,其间将数据依次存入堆栈。遍历完之后将所有元素依次出栈并打印即可。

  PS:这里堆栈直接用C++中的stack容器适配器实现

代码实现( 含测试 )

#include <iostream>
#include <stack>

using namespace std;

/*
* 定义结点类型
*/
struct ListNode {
int value;
ListNode *next;
};

// 逆序打印函数
void rPrint(ListNode * head);

/*
* 测试函数:建立一个链表,有10个结点,结点的值依次为1-10。
*          然后调用rPrint函数将数据从尾到头打印出来。
*/
int main()
{
ListNode *head = new ListNode();
head->value = 1;

ListNode *q = head;
ListNode *p = NULL;

for (int i=2; i<=10; i++) {
p = new ListNode();
p->value = i;
q->next = p;
q = q->next;
}
p->next = NULL;

p = head;
cout << "目标链表:" << endl;
while (p != NULL) {
cout << p->value << " ";
p = p->next;
}
cout << endl;

rPrint(head);

return 0;
}

/*
* 逆序打印函数
*/
void rPrint(ListNode * head)
{
// 定义一个堆栈( 容器适配器 )
stack<ListNode *> s;

// 顺序遍历链表并将数据存进堆栈
ListNode *p = head;
while (p!=NULL) {
s.push(p);
p = p->next;
}

// 所有数据出栈并打印
cout << "逆序打印之:" << endl;
while (!s.empty()) {
p = s.top();
s.pop();
cout << p->value << " ";
}

cout << endl;
}


运行测试

  


解法二 递归法

  递归打印此链表,这也是最简单的解法。

代码实现( 含测试 )

#include <iostream>

using namespace std;

/*
* 定义结点类型
*/
struct ListNode {
int value;
ListNode *next;
};

// 逆序打印函数
void rPrint(ListNode * head);

/*
* 测试函数:建立一个链表,有10个结点,结点的值依次为1-10。
*          然后调用rPrint函数将数据从尾到头打印出来。
*/
int main()
{
ListNode *head = new ListNode();
head->value = 1;

ListNode *q = head;
ListNode *p = NULL;

for (int i=2; i<=10; i++) {
p = new ListNode();
p->value = i;
q->next = p;
q = q->next;
}
p->next = NULL;

p = head;
cout << "目标链表:" << endl;
while (p != NULL) {
cout << p->value << " ";
p = p->next;
}
cout << endl;

rPrint(head);

cout << endl;

return 0;
}

/*
* 逆序打印函数
*/
void rPrint(ListNode * head)
{
if (head == NULL)
return;

if (head->next != NULL) {
rPrint(head->next);
cout << head->value << " ";
}
else
cout << head->value << " "; // 递归“出口”
}


运行测试

  


解法三 临时修改链表法

  如果有些时候要求你不能使用栈或者递归( 内存空间很小 ),这时候应当使用这种方法:

  1. 首先将链表从头到尾翻转一次,同时遍历指针到达表尾。

  2. 然后将链表从尾到头翻转一次,在这次的翻转过程中同时输出结点数据。

代码实现( 含测试 )

#include <iostream>

using namespace std;

/*
* 定义结点类型
*/
struct ListNode {
int value;
ListNode *next;
};

// 逆序打印函数
void rPrint(ListNode * head);

/*
* 测试函数:建立一个链表,有10个结点,结点的值依次为1-10。
*          然后调用rPrint函数将数据从尾到头打印出来。
*/
int main()
{
ListNode *head = new ListNode();
head->value = 1;

ListNode *q = head;
ListNode *p = NULL;

for (int i=2; i<=10; i++) {
p = new ListNode();
p->value = i;
q->next = p;
q = q->next;
}
p->next = NULL;

p = head;
cout << "目标链表:" << endl;
while (p != NULL) {
cout << p->value << " ";
p = p->next;
}
cout << endl;

rPrint(head);

return 0;
}

/*
* 逆序打印函数
*/
void rPrint(ListNode * head)
{
/*
* 下面三个if判断分别处理结点数为0,1,2时候的情况。
*/
if (head == NULL)
return;
if (head != NULL && head->next == NULL) {
cout << head->value << endl;
return;
}
if (head != NULL && head->next != NULL && head->next->next == NULL) {
cout << head->next->value << " " << head->value << endl;
return;
}

// 下面是结点数大于等于3时候的处理。

// 首先,翻转链表一次。
ListNode *s, *p, *q;
q = head; p = head->next; s = head->next->next;
q->next = NULL; // 这步别忘

while (s != NULL) {
p->next = q;
q = p;
p = s;
s = s->next;
}
// 收尾
p->next = q;

// 然后,再翻转链表一次。
q = p;
p = q->next;
s = p->next;

q->next = NULL; // 这步别忘
cout << q->value << " " << p->value << " "; // 先将头两个结点的数据输出
while (s != NULL) {
cout << s->value << " "; // 翻转的过程中输出链表数据
p->next = q;
q = p;
p = s;
s = s->next;
}
// 再次收尾
p->next = q;

cout << endl;
}


运行测试

  


小结

  C++中的容器及容器适配器都挺实用的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: