Smarter Python数据结构:如何翻转栈

简介: Smarter Python数据结构:如何翻转栈

简说Python,号主老表,Python终身学习者,数据分析爱好者,从18年开始分享Python知识,原创文章227篇,写过Python、SQL、Excel入门文章,也写过Web开发、数据分析文章,老表还总结整理了一份2022Python学习资料和电子书资源,关注后私信回复:2022 即可领取。

今天给大家分享的书籍《Python程序员面试算法宝典》第二章第三小节:如何翻转栈。

如果你是第一次看,也许,你可以看看本系列下面的文章:

Python数据结构:链表合集(12+7),复现几遍,包你学会

Smaller And Smarter Python数据结构:自己动手实现栈

Smaller And Smarter Python数据结构:自己动手实现队列

今日问题

"""
目标:写一个程序,翻转栈内所有元素
输入:5,4,3,2,1
输出:1,2,3,4,5
Goal: write a program to flip all elements in the stack
Input: 5, 4, 3, 2, 1
Output: 1, 2, 3, 4, 5
"""

解题

首先我们之前已经写好了栈和队列的基本操作,在b_1_implementation_stack.pyb_2_implementation_queue文件中,所以我们先导入这两个包。

from StackQueueHash.b_1_implementation_stack import LinkStack
from StackQueueHash.b_2_implementation_queue import LinkQueue

方法一:数组(列表)实现队列

"""
Method One : 借助辅存
核心思想:充分利用栈和队列特性,栈先进后出,每次只能去栈顶元素,队列先进先出。
我们将栈内元素一一取出,存放到队列中,栈空后,我们再将队列内的元素一一取出,
存入到栈中,实现翻转。
时间复杂度:O(N)
空间复杂度:O(N)
Method one: with the help of auxiliary storage
Core idea: make full use of stack and queue characteristics, stack
 first in first out, can only go to the top element of stack each 
 time, queue first in first out. We take out the elements in the 
 stack one by one and store them in the queue. After the stack is 
 empty, we take out the elements in the queue one by one and store 
 them in the stack to realize the flipping.
"""

代码

def flip_stack_one(s):
    q = LinkQueue()  # 初始化一个队列
    while not s.stack_is_empty():
        # 遍历栈,将栈中元素取出,存入队列
        x = s.get_stack_top()  # 获取栈首元素
        s.stack_pop()  # 出栈
        q.queue_push(x)  # 入队列
    while not q.queue_is_empty():
        # 遍历队列,将队列中元素取出,存入栈,实现翻转
        x = q.get_queue_top()  # 获取队首元素
        q.queue_pop()  # 出队列
        s.stack_push(x)  # 入栈

方法二:链表实现队列

"""
Method Two : 递归翻转
核心思想:第一次递归,把栈去除栈顶,生成子栈,把每个子栈的栈底元素翻转到栈顶,
第二次递归,对每个子栈操作,遍历到栈底(不断出栈,直到栈为空为止),栈空后开
始回溯,把栈内相邻的两个元素进行互换位置,这样不断从上到下递归回溯,可以实现
把栈底元素翻转到栈顶。
递归两大要素:递归定义 , 递归终止条件。
递归定义:将当前栈最低元素翻转到栈顶,然后对不包含栈顶元素的子栈进行同样操作。
终止条件:栈为空。
时间复杂度:O(N^2)
空间复杂度:O(1)
Method two: recursive flip
Core idea: for the first recursion, remove the stack top, generate
 the sub stack, flip the stack bottom elements of each sub stack 
 to the top of the stack, for the second recursion, operate on each 
 sub stack, traverse to the bottom of the stack (keep going out of 
 the stack until the stack is empty), start to backtrack after the 
 stack is empty, and exchange the two adjacent elements in the stack, 
 so as to recursively backtrack from the top to the bottom, which can 
 be realized Flip the bottom element to the top of the stack.
Two elements of recursion: recursion definition and recursion termination
 condition.
Recursion definition: flip the lowest element of the current stack to the
 top of the stack, and then do the same for the sub stack that does not 
 contain the top element.
Termination condition: stack is empty.
"""

代码

def change_stack_top(s):
    top1 = s.get_stack_top()  # 取出栈顶
    # print(top1)
    s.stack_pop()  # 出栈
    if not s.stack_is_empty():  # 栈不为空时一直递归遍历
        change_stack_top(s)  # 递归
        top2 = s.get_stack_top()  # 取出当前栈顶
        s.stack_pop()  # 出栈
        s.stack_push(top1)  # 入栈
        s.stack_push(top2)  # 入栈,实现相邻元素交换位置
    else:  # 栈为空时,开始回溯
        s.stack_push(top1)  # 入栈
def flip_stack_two(s):
    if s.stack_is_empty():  # 栈为空,直接返回
        return
    # 第一步:将当前栈顶与栈尾交换位置
    change_stack_top(s)
    # 第二步:取出当前栈顶,开始递归处理子栈
    top = s.get_stack_top()
    s.stack_pop()
    flip_stack_two(s)
    # 第三步:回溯时,将之前取出的栈顶元素入栈
    s.stack_push(top)

测试代码

# 当然,也许还有别的方法,比如建一个辅助的链表
# 欢迎你说出你的想法
# 程序入口,测试函数功能
if __name__ == "__main__":
    s = LinkStack()  # 初始化一个栈对象
    stack_data = [1, 2, 3, 4, 5]  # 栈元素
    for i in stack_data:   # 初始化栈内元素
        s.stack_push(i)  # 入栈
    # flip_stack_one(s)  # 翻转栈内元素
    flip_stack_two(s)  # 翻转栈内元素
    while not s.stack_is_empty():  # 遍历打印栈内元素
        print(s.get_stack_top(), end="  ")  # 打印当前栈顶元素
        s.stack_pop()  # 出栈

运行结果

image.png

本文代码思路来自书籍《Python程序员面试宝典》,书中部分代码有问题,文中已经修改过了,并添加上了丰厚的注释,方便大家学习,后面我会把所有内容开源放到Github上,包括代码,思路,算法图解(手绘或者电脑画),时间充裕的话,会录制视频。

希望大家多多支持。


大家好,我是老表

觉得本文不错的话,转发、留言、点赞,是对我最大的支持。

欢迎关注微信公众号:简说Python

关注后回复:1024,可以领取精选编程学习电子书籍。

相关文章
|
2月前
|
Java 数据挖掘 数据处理
(Pandas)Python做数据处理必选框架之一!(一):介绍Pandas中的两个数据结构;刨析Series:如何访问数据;数据去重、取众数、总和、标准差、方差、平均值等;判断缺失值、获取索引...
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。 Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。 Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。
390 0
|
5月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
159 1
|
6月前
|
编译器 C语言 C++
栈区的非法访问导致的死循环(x64)
这段内容主要分析了一段C语言代码在VS2022中形成死循环的原因,涉及栈区内存布局和数组越界问题。代码中`arr[15]`越界访问,修改了变量`i`的值,导致`for`循环条件始终为真,形成死循环。原因是VS2022栈区从低地址到高地址分配内存,`arr`数组与`i`相邻,`arr[15]`恰好覆盖`i`的地址。而在VS2019中,栈区先分配高地址再分配低地址,因此相同代码表现不同。这说明编译器对栈区内存分配顺序的实现差异会导致程序行为不一致,需避免数组越界以确保代码健壮性。
126 0
栈区的非法访问导致的死循环(x64)
232.用栈实现队列,225. 用队列实现栈
在232题中,通过两个栈(`stIn`和`stOut`)模拟队列的先入先出(FIFO)行为。`push`操作将元素压入`stIn`,`pop`和`peek`操作则通过将`stIn`的元素转移到`stOut`来实现队列的顺序访问。 225题则是利用单个队列(`que`)模拟栈的后入先出(LIFO)特性。通过多次调整队列头部元素的位置,确保弹出顺序符合栈的要求。`top`操作直接返回队列尾部元素,`empty`判断队列是否为空。 两题均仅使用基础数据结构操作,展示了栈与队列之间的转换逻辑。
|
11月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
516 77
|
9月前
|
存储 人工智能 索引
Python数据结构:列表、元组、字典、集合
Python 中的列表、元组、字典和集合是常用数据结构。列表(List)是有序可变集合,支持增删改查操作;元组(Tuple)与列表类似但不可变,适合存储固定数据;字典(Dictionary)以键值对形式存储,无序可变,便于快速查找和修改;集合(Set)为无序不重复集合,支持高效集合运算如并集、交集等。根据需求选择合适的数据结构,可提升代码效率与可读性。
|
10月前
|
算法 调度 C++
STL——栈和队列和优先队列
通过以上对栈、队列和优先队列的详细解释和示例,希望能帮助读者更好地理解和应用这些重要的数据结构。
240 11
|
10月前
|
DataX
☀☀☀☀☀☀☀有关栈和队列应用的oj题讲解☼☼☼☼☼☼☼
### 简介 本文介绍了三种数据结构的实现方法:用两个队列实现栈、用两个栈实现队列以及设计循环队列。具体思路如下: 1. **用两个队列实现栈**: - 插入元素时,选择非空队列进行插入。 - 移除栈顶元素时,将非空队列中的元素依次转移到另一个队列,直到只剩下一个元素,然后弹出该元素。 - 判空条件为两个队列均为空。 2. **用两个栈实现队列**: - 插入元素时,选择非空栈进行插入。 - 移除队首元素时,将非空栈中的元素依次转移到另一个栈,再将这些元素重新放回原栈以保持顺序。 - 判空条件为两个栈均为空。
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
1030 9

推荐镜像

更多