剑指offer——从尾到头打印链表节点的值
输入一个链表,从尾到头打印链表每个节点的值。
输入描述:输入为链表的表头
输出描述:输出为需要打印的“新链表”的表头
一、问题分析
初拿到这个题目时,这应该是考察单向链表这一数据结构。单向链表的遍历总是从头指针逐项遍历各个节点,现在要求从尾到头打印节点的值,我们可以在遍历时把各节点压入栈内,最后出栈打印各个节点值,即可达到要求。
实现之前,我们先来看看如何创建一个链表。
1,链表节点的数据结构定义
1 struct ListNode {
2 int val;
3 struct ListNode *next;
4 ListNode(int x) :
5 val(x), next(NULL) {
6 }
7 };
在链表的定义中,包含自己的整形成员(当然也可以定义为其它数据类型,如double),以及下一个节点的位置信息(next)。这里我们还定义了节点的构造函数(ListNode),方便节点的初始化。
2,链表的创建
这里我们考虑单向链表。如果通过用户输入来创建链表,我们可以进行如下操作:
1)创建头节点head,指向NULL。因为此时没有任何节点
2)为加入的节点分配空间,赋初值(如1中考虑的int类型)并指向NULL。判断head==NULL?head指向该节点:“上一节点”指向该节点
3)更新新加入的节点为“上一节点”
4)判断节点是否添加结束,若否,重复2,3,4步骤继续添加节点。
二、问题的解决思路
1,利用stack反转输出链表节点值
#include <iostream>
#include <vector>
#include <stack>
using namespace std; //链表节点定义
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
}; //链表从尾到头输出节点值方法实现
class Solution {
public:
//方法1,通过stack 这个container来实现反转链表
vector<int> printListFromTailToHead(struct ListNode* head) {
vector<int> result;
if(head == NULL)
return result;
stack<ListNode*> reverse;
ListNode* node = head;
while(node != NULL) {
reverse.push(node);
node = node->next;
}
while(!reverse.empty()) {
node = reverse.top();
result.push_back(node->val);
reverse.pop();
}
return result;
}
//方法2,原地反转链表,不介入其它container
//不断的使“下一个节点”指向“前一个”节点
vector<int> printListFromTailToHead2(struct ListNode* head) {
vector<int> vec;
ListNode *buf = head;
ListNode *pre = buf;
if(head == NULL)
return vec;
while(head->next != NULL){
buf = head->next;
head->next = buf->next;
buf->next = pre;
pre = buf;
}
while(buf){
vec.push_back(buf->val);
buf = buf->next;
}
return vec;
}
}; struct ListNode* CreateListNode(struct ListNode* head) {
struct ListNode *p1, *p2;
int i = ;
p1 = p2 = (struct ListNode*)malloc(sizeof(ListNode));
cout << "Please input the 1st node, it's address is p1_addr = " << p1 << endl;
cout << "And input -1 to quit.";
cin >> (p1->val);
p1->next = NULL; while (p1->val != -) {
if (NULL == head) {
head = p1;
}
else
p2->next = p1;
p2 = p1;
p1 = (struct ListNode*)malloc(sizeof(ListNode));
++i;
cout << "Please input the " << i << " node," << "it's address is p" << i << "_addr = " << p1 <<endl;
cin >> (p1->val);
}
free(p1);
p2->next = NULL;
p1 = NULL;
cout << "End of creating ListNode." << endl;
return head;
} int main () {
std::vector<int> v;
struct ListNode* head = NULL;
head = CreateListNode(head); Solution s;
v = s.printListFromTailToHead2(head);
for (int var : v) {
cout << var << ' ';
} //测试节点的初始化,与本题无关
struct ListNode myListNode();
cout << myListNode.val << endl; }
上述程序在gcc version 6.1.0下编译通过。
在上面的程序中,实现反转的方法有两个:
1)利用stack先入后出的特性实现链表的反转
2)不借用其它container,不断的使“后一个”节点指向“前一个节点”来原地反转链表。下面来谈谈原地反转链表
2,原地反转链表
我们看函数printListFromTailToHead2()。首先,我们先定义两个指针(buf, pre),并与head共同指向链表的头节点。然后,通过head->next遍历原始链表,并同时更新buf指向已经遍历到的节点(buf = head->next),而这期间head始终指向头节点。然后,更新head—>next指向buf的下一个节点(head->next = buf->next)。接着,通过buf->next = pre, 使buf指向前一个节点,紧接着更新pre,使其指向当前节点,以便下一轮更新。
当head->next遍历完链表后,buf指向了原始链表最后一个节点,head->next的值变为了NULL。现在从buf开始遍历,即可反向遍历链表。
剑指offer——从尾到头打印链表节点的值的更多相关文章
- 剑指Offer 从尾到头打印链表
题目描述 输入一个链表,从尾到头打印链表每个节点的值. 输入描述: 输入为链表的表头 输出描述: 输出为需要打印的“新链表”的表头 思路: 用容器vector,递归到最后一个元素,push_back到 ...
- 剑指Offer——从尾到头打印链表
题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 分析: 方法1:利用栈的性质,先从头到尾遍历链表每个节点的值存入栈中,最后一个一个出栈顺序便是从尾到头的. 方法2:直接从头到尾遍历链表存储节 ...
- 剑指offer —— 从尾到头打印链表
1.问题:输入一个链表,从尾到头打印链表每个节点的值. /** * public class ListNode { * int val; * ListNode next = null; * * Lis ...
- 用js刷剑指offer(从尾到头打印链表)
题目描述 输入一个链表,按链表从尾到头的顺序返回一个ArrayList. 牛客网链接 js代码 /*function ListNode(x){ this.val = x; this.next = nu ...
- 4、剑指offer——从尾到头打印链表java实现
**题目描述** **输入一个链表,按链表从尾到头的顺序返回一个ArrayList.** 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M 思路: 1.如果链 ...
- [剑指Offer]6-从尾到头打印链表
典型的后进先出,可以借助栈,也可以使用递归. 考虑到若链表过长递归可能造成函数调用栈溢出,所以使用栈更好. 注意stack无遍历操作,全部用push(),pop(),top()完成. 以下创建列表胡乱 ...
- 剑指Offer-3.从尾到头打印链表(C++/Java)
题目: 输入一个链表,按链表从尾到头的顺序返回一个ArrayList. 分析: 很简单的一道题,其实也就是从尾到头打印链表,题目要求返回ArrayList,其实也就是一个数组. 可以将链表中的元素全部 ...
- 剑指Offer_6_从尾到头打印链表
题目描述 输入应该链表的头节点 , 从尾到头反过来打印出每个节点的值.链表定义如下 : typedef struct ListNode { int m_nKey ; ListNode * ...
- 剑指offer--18.从尾到头打印链表
递归,逐个加到后面 ------------------------------------------------------------------------------ 时间限制:1秒 空间限 ...
随机推荐
- 【转】CodeGear RAD 2007 SP4
转自:http://blog.csdn.net/Rzhghost/article/details/2512150 CodeGear RAD 2007 up4最新下载及破解 官方http下载:http: ...
- 根据老赵轻量级Actor进行修改的Actor模型
学习了老赵轻量级Actor模型,并在实际中使用,效果不错. 老赵轻量级Actor模型: ActorLite:一个轻量级Actor模型实现(上) ActorLite:一个轻量级Actor模型实现(中) ...
- 标准建立二叉树NEW
#include<iostream> #include<sstream> #include<stdio.h> #include<string> #inc ...
- poj2459 Treasure Exploration (闭包+二分)
这道题是让求派出机器人的最少数量,乍一看以为是简单的求最小路径覆盖,后来发现错了,因为有的点可以走多次,而二分中每个点只能走一次,所以要先用floyd进行传递闭包,然后用二分 #include< ...
- javascript外部ファイル
function myFunction() { document.getElementById("demo").innerHTML = "Paragraph cha ...
- python执行shell命令
1 os.system 可以返回运行shell命令状态,同时会在终端输出运行结果 例如 ipython中运行如下命令,返回运行状态status os.system('cat /etc/passwdqc ...
- Silverlight第三方控件专题
原文http://www.cnblogs.com/nasa/archive/2008/12/01/1344927.html 这里我收集整理了目前网上silverlight第三方控件的专题,若果有所遗漏 ...
- PHPExcel 多工作表 导入
//参数初始化 $filePath = ''; if ($_FILES["file"]["error"] > 0) { returnJSON(ERROR_ ...
- Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!)
Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!) 1.控制面板中卸载所有带sql server的程序. 2.在C盘C:\Program Files中sqlserv ...
- HDU 3468 Treasure Hunting(BFS+网络流之最大流)
题目地址:HDU 3468 这道题的关键在于能想到用网络流.然后还要想到用bfs来标记最短路中的点. 首先标记方法是,对每个集合点跑一次bfs,记录全部点到该点的最短距离.然后对于随意一对起始点来说, ...