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

欢迎关注微信公众号:简说Python
关注后回复:1024,可以领取精选编程学习电子书籍。

这两天和几个朋友组了个互相督促学习群,想着督促一下自己学习,也督促自己的原创输出,其实很多时候都是懒,真不是没有东西可以写了,这不,我在我的免费知识星球简说编程里开了个新的标签日常编程问题,后面我会把自己学习工作中遇到的一些问题和解决方法记录到里面,有些可以扩展的点,我会写到微信公众号里。
我定的目标是:

我简单写了个规则,大家说可以,然后,我们就开始吧,我习惯把该做的事情提前一天做(如果有时间的话)。

今天给大家分享的书籍《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()  # 出栈

运行结果

Smaller And Smarter Python数据结构:如何翻转栈_第1张图片
本文代码思路来自书籍《Python程序员面试宝典》,书中部分代码有问题,文中已经修改过了,并添加上了丰厚的注释,方便大家学习,后面我会把所有内容开源放到Github上,包括代码,思路,算法图解(手绘或者电脑画),时间充裕的话,会录制视频。 希望大家多多支持。

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

欢迎关注微信公众号:简说Python
关注后回复:1024,可以领取精选编程学习电子书籍。

你可能感兴趣的:(数据结构,Python)