从尾到头打印链表(C++和Python 实现)
(说明:本博客中的题目、题目详细说明及参考代码均摘自 “何海涛《剑指Offer:名企面试官精讲典型编程题》2012年”)
题目
输入一个链表的头结点, 从尾到头反过来打印出每个结点的值。
进一步详细说明:
不允许在打印时修改链表的结构。链表结点可定义为:
struct ListNode {int m_nKey;ListNode* m_pNext; };
算法设计思想
正常情况,遍历链表都是从前到后的,即从头到尾。如果从尾到头打印链表元素,可以借助栈的 “后入先出” (Last in, First out)的性质,在正向遍历时将链表元素依次压栈,当到达链表末尾时,再依次弹出并打印。
具体实现可以采用两种方法:迭代和递归。正如书中所说,“递归在本质上就是一个栈结构”。递归实现,从理论上,完全可以利用栈结构转换为非递归实现,即迭代方法。
C++ 实现
#include <iostream> #include <stack>struct ListNode {int m_nKey;ListNode* m_pNext; };void AddToTail(ListNode** pHead, int value) {ListNode* pNew = new ListNode();pNew->m_nKey = value;pNew->m_pNext = NULL;if (*pHead == NULL){*pHead = pNew;}else{ListNode* pNode = *pHead;while (pNode->m_pNext != NULL)pNode = pNode->m_pNext;pNode->m_pNext = pNew;} }void PrintLinkedList(const ListNode* head) {if (head == NULL) // 易漏点return;ListNode* ptr = (ListNode*) head;while (ptr->m_pNext != NULL){std::cout << ptr->m_nKey << " -> ";ptr = ptr->m_pNext;}std::cout << ptr->m_nKey << std::endl; }void DestroyLinkedList(ListNode** pHead) {if (pHead == NULL || *pHead == NULL) // 易漏点return;ListNode* pNode = NULL;while (*pHead != NULL){pNode = *pHead;*pHead = (*pHead)->m_pNext;delete pNode;} }// Iterative method void PrintListReversingly_Iteratively(const ListNode* pHead) {if (pHead == NULL)return;ListNode* pNode = (ListNode*) pHead;std::stack<ListNode*> nodes;while (pNode != NULL){nodes.push(pNode);pNode = pNode->m_pNext;}while (!nodes.empty()){pNode = nodes.top();nodes.pop();std::cout << pNode->m_nKey << ", ";}std::cout << std::endl; }// Recursive method void PrintListReversingly_Recursively(const ListNode* pHead) {if (pHead != NULL){if (pHead->m_pNext != NULL){PrintListReversingly_Recursively(pHead->m_pNext);}std::cout << pHead->m_nKey << ", ";} }void unitest() {ListNode* head = NULL;AddToTail(&head, 1);AddToTail(&head, 2);AddToTail(&head, 3);AddToTail(&head, 5);AddToTail(&head, 4);std::cout << "Print forward: ";PrintLinkedList(head);std::cout << "Print reversely iteratively: ";PrintListReversingly_Iteratively(head);std::cout << "Print reversely recursively: ";PrintListReversingly_Recursively(head);// Release memoryDestroyLinkedList(&head); // 易漏点 }int main() {unitest();return 0; }
Python 实现
#!/usr/bin/python # -*- coding: utf8 -*-from __future__ import print_functionclass ListNode:def __init__(self, value, next_node=None):self.value = valueself.next = next_nodedef add_to_tail(head, value):q = ListNode(value)if head is None:head = qelse:p = headwhile p.next is not None:p = p.nextp.next = qreturn head def print_list_reversely_iteratively(head):p = headstack = []# Push into stackwhile p is not None:stack.append(p.value)p = p.next# Pop from stackwhile stack:elem = stack.pop()print(elem, end=', ')print('')def print_list_reversely_recursively(head):if head is None:returnif head.next is not None:print_list_reversely_recursively(head.next)print(head.value, end=', ')def print_linked_list_forward(head):if head is None:print("This linked list is empty!")returnp = headwhile p is not None:print(p.value, end='')if p.next is not None:print(' -> ', end='')p = p.nextprint('')def unitest():linked_list = Nonelinked_list = add_to_tail(linked_list, 1)linked_list = add_to_tail(linked_list, 2)linked_list = add_to_tail(linked_list, 3)linked_list = add_to_tail(linked_list, 5)linked_list = add_to_tail(linked_list, 4)print("Print forward: ", end='')print_linked_list_forward(linked_list)print("Print reversely iteratively: ", end='') print_list_reversely_iteratively(linked_list)print("Print reversely recursively: ", end='') print_list_reversely_recursively(linked_list)if __name__ == '__main__':unitest()
注:使用 Python 利用函数建立链表时,需要注意函数参数的值传递和引用传递,此为易错点。
参考代码
1. targetver.h (05_PrintListInReversedOrder/ 目录)
#pragma once// The following macros define the minimum required platform. The minimum required platform // is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run // your application. The macros work by enabling all features available on platform versions up to and // including the version specified.// Modify the following defines if you have to target a platform prior to the ones specified below. // Refer to MSDN for the latest info on corresponding values for different platforms. #ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. #define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. #endif
View Code
2. stdafx.h (05_PrintListInReversedOrder/ 目录)
// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #pragma once#include "targetver.h"#include <stdio.h> #include <tchar.h>// TODO: reference additional headers your program requires here
View Code
3. stdafx.cpp (05_PrintListInReversedOrder/ 目录)
// stdafx.cpp : source file that includes just the standard includes // PrintListInReversedOrder.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h"// TODO: reference any additional headers you need in STDAFX.H // and not in this file
View Code
4. PrintListInReversedOrder.cpp
// PrintListInReversedOrder.cpp : Defines the entry point for the console application. //// 《剑指Offer——名企面试官精讲典型编程题》代码 // 著作权所有者:何海涛 #include "stdafx.h" #include "..\Utilities\List.h" #include <stack>void PrintListReversingly_Iteratively(ListNode* pHead) {std::stack<ListNode*> nodes;ListNode* pNode = pHead;while(pNode != NULL){nodes.push(pNode);pNode = pNode->m_pNext;}while(!nodes.empty()){pNode = nodes.top();printf("%d\t", pNode->m_nValue);nodes.pop();} }void PrintListReversingly_Recursively(ListNode* pHead) {if(pHead != NULL){if (pHead->m_pNext != NULL){PrintListReversingly_Recursively(pHead->m_pNext);}printf("%d\t", pHead->m_nValue);} }void Test(ListNode* pHead) {PrintList(pHead);PrintListReversingly_Iteratively(pHead);printf("\n");PrintListReversingly_Recursively(pHead); }// 1->2->3->4->5 void Test1() {printf("\nTest1 begins.\n");ListNode* pNode1 = CreateListNode(1);ListNode* pNode2 = CreateListNode(2);ListNode* pNode3 = CreateListNode(3);ListNode* pNode4 = CreateListNode(4);ListNode* pNode5 = CreateListNode(5);ConnectListNodes(pNode1, pNode2);ConnectListNodes(pNode2, pNode3);ConnectListNodes(pNode3, pNode4);ConnectListNodes(pNode4, pNode5);Test(pNode1);DestroyList(pNode1); }// 只有一个结点的链表: 1 void Test2() {printf("\nTest2 begins.\n");ListNode* pNode1 = CreateListNode(1);Test(pNode1);DestroyList(pNode1); }// 空链表 void Test3() {printf("\nTest3 begins.\n");Test(NULL); }int _tmain(int argc, _TCHAR* argv[]) {Test1();Test2();Test3();return 0; }
View Code
5. targetver.h (Utilities/ 目录)
#pragma once// The following macros define the minimum required platform. The minimum required platform // is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run // your application. The macros work by enabling all features available on platform versions up to and // including the version specified.// Modify the following defines if you have to target a platform prior to the ones specified below. // Refer to MSDN for the latest info on corresponding values for different platforms. #ifndef WINVER // Specifies that the minimum required platform is Windows Vista. #define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. #endif#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. #define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. #endif#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. #endif#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. #define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. #endif
View Code
6. stdafx.h (Utilities/ 目录)
// stdafx.h : include file for standard system include files, // or project specific include files that are used frequently, but // are changed infrequently // #pragma once#include "targetver.h"#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: #include <windows.h> #include <stdio.h>// TODO: reference additional headers your program requires here
View Code
7. stdafx.cpp (Utilities/ 目录)
// stdafx.cpp : source file that includes just the standard includes // Utilities.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h"// TODO: reference any additional headers you need in STDAFX.H // and not in this file
View Code
8. List.h
// 《剑指Offer——名企面试官精讲典型编程题》代码 // 著作权所有者:何海涛struct ListNode {int m_nValue;ListNode* m_pNext; };__declspec( dllexport ) ListNode* CreateListNode(int value); __declspec( dllexport ) void ConnectListNodes(ListNode* pCurrent, ListNode* pNext); __declspec( dllexport ) void PrintListNode(ListNode* pNode); __declspec( dllexport ) void PrintList(ListNode* pHead); __declspec( dllexport ) void DestroyList(ListNode* pHead); __declspec( dllexport ) void AddToTail(ListNode** pHead, int value); __declspec( dllexport ) void RemoveNode(ListNode** pHead, int value);
View Code
9. List.cpp
// Utilities.cpp : Defines the exported functions for the DLL application. //// 《剑指Offer——名企面试官精讲典型编程题》代码 // 著作权所有者:何海涛 #include "stdafx.h" #include "list.h" #include <stdio.h> #include <stdlib.h>ListNode* CreateListNode(int value) {ListNode* pNode = new ListNode();pNode->m_nValue = value;pNode->m_pNext = NULL;return pNode; }void ConnectListNodes(ListNode* pCurrent, ListNode* pNext) {if(pCurrent == NULL){printf("Error to connect two nodes.\n");exit(1);}pCurrent->m_pNext = pNext; }void PrintListNode(ListNode* pNode) { if(pNode == NULL){printf("The node is NULL\n");}else{printf("The key in node is %d.\n", pNode->m_nValue);} }void PrintList(ListNode* pHead) {printf("PrintList starts.\n");ListNode* pNode = pHead;while(pNode != NULL){printf("%d\t", pNode->m_nValue);pNode = pNode->m_pNext;}printf("\nPrintList ends.\n"); }void DestroyList(ListNode* pHead) {ListNode* pNode = pHead;while(pNode != NULL){pHead = pHead->m_pNext;delete pNode;pNode = pHead;} }void AddToTail(ListNode** pHead, int value) {ListNode* pNew = new ListNode();pNew->m_nValue = value;pNew->m_pNext = NULL;if(*pHead == NULL){*pHead = pNew;}else{ListNode* pNode = *pHead;while(pNode->m_pNext != NULL)pNode = pNode->m_pNext;pNode->m_pNext = pNew;} }void RemoveNode(ListNode** pHead, int value) {if(pHead == NULL || *pHead == NULL)return;ListNode* pToBeDeleted = NULL;if((*pHead)->m_nValue == value){pToBeDeleted = *pHead;*pHead = (*pHead)->m_pNext;}else{ListNode* pNode = *pHead;while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)pNode = pNode->m_pNext;if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value){pToBeDeleted = pNode->m_pNext;pNode->m_pNext = pNode->m_pNext->m_pNext;}}if(pToBeDeleted != NULL){delete pToBeDeleted;pToBeDeleted = NULL;} }
View Code
10. 参考代码下载
项目 05_PrintListInReversedOrder 下载: 百度网盘
何海涛《剑指Offer:名企面试官精讲典型编程题》 所有参考代码下载:百度网盘
参考资料
[1] 何海涛. 剑指 Offer:名企面试官精讲典型编程题 [M]. 北京:电子工业出版社,2012. 49-53.
转载于:https://www.cnblogs.com/klchang/p/7590302.html
从尾到头打印链表(C++和Python 实现)相关推荐
- 【剑指Offer专题】链表系列:从尾到头打印链表、反转链表、回文链表、合并两个排序的链表(C++和Python实现)...
关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 剑指Offer(三):从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每 ...
- python 从尾到头打印链表
从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每个节点的值 (用数组返回).示例 1:输入:head = [1,3,2] 输出:[2,3,1] 提供三种题解 # Definition fo ...
- 剑指offer:面试题06. 从尾到头打印链表
题目:从尾到头打印链表 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入:head = [1,3,2] 输出:[2,3,1] 限制: 0 <= 链表长度 & ...
- 《LeetCode力扣练习》剑指 Offer 06. 从尾到头打印链表 Java
<LeetCode力扣练习>剑指 Offer 06. 从尾到头打印链表 Java 一.资源 题目: 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入: ...
- java从尾到头打印链表数据_Java编程实现从尾到头打印链表代码实例
问题描述:输入一个链表的头结点,从尾巴到头反过来打印出每个结点的值. 首先定义链表结点 public class ListNode { int val; ListNode next = null; L ...
- JAVA实现从尾到头打印链表(《剑指offer》)
最近在刷<剑指offer>里的编程题,但是网上关于<剑指offer>的解答多半是C或者C++的,而且官方(作者)也是在用C++进行讲解,这里自己用java写了一些题目的解答代码 ...
- 【剑指Offer】从尾到头打印链表
剑指Offer 从尾到头打印链表 题目描述 解法1 实现代码 一点补充 题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 解法1 这道题主要思路是while循环从头遍历整个列 ...
- 剑指Offer - 九度1511 - 从尾到头打印链表
剑指Offer - 九度1511 - 从尾到头打印链表2013-11-29 21:08 题目描述: 输入一个链表,从尾到头打印链表每个节点的值. 输入: 每个输入文件仅包含一组测试样例. 每一组测试案 ...
- LeetCode-剑指 Offer 06. 从尾到头打印链表
剑指 Offer 06. 从尾到头打印链表 思路一:翻转 1:用vector存从头到尾的每个节点值 2:返回时候用reverse翻转一下 时间复杂度:O(n) 空间复杂度:O(n) /*** Defi ...
最新文章
- Google 的自动驾驶车出事故,被人类撞的
- varchar保存带格式的数据_软件测试必备之数据库知识(一)
- vs插件ZunKoIDE
- Ribbon_窗体_实现Ribbon风格的窗体
- 你知道生气有多可怕吗?“气死人”是有科学依据的
- 东北大学计算机技术考研大纲,东北大学考研大纲
- Oracle Partition By 的使用
- PHP学习笔记:利用百度api实现手机归属地查询
- Python 开源电子书资源
- Dockerfile制作自定义镜像
- 纠结的链接——ln、ln -s、fs.symlink、require
- 快速核对两个表格数据
- Shannon-Fano编码——原理与实现
- react-native-webrtc之采坑之旅
- 垃圾小白羊的leetcode刷题记录7
- reactjs 视频教程
- 【工具】hadoop国内下载镜像
- 一键自动生成字幕、制作双语字幕,懒人必备
- 金碟软件资产负债表中JC,JD,DY,DC表示的是什么
- jquery 动态按钮绑定点击事件