我想反转堆栈,但我不知道如何使用递归来反转这个......如何在不使用递归的情况下反转堆栈

Posted

技术标签:

【中文标题】我想反转堆栈,但我不知道如何使用递归来反转这个......如何在不使用递归的情况下反转堆栈【英文标题】:I want to reverse the stack but i dont know how to use recursion for reversing this... How can i reverse the stack without using Recursion 【发布时间】:2021-04-08 09:00:16 【问题描述】:

我想使用堆栈数据结构而不使用递归来反转字符串

str= 我们打败了 Corona

reversed str = anoroC detaefed ew

from collections import deque

class Stack:
    def __init__(self):
        self.container = deque()
    def rev(self):
        nstk= deque()
        for i in self.container(len(self.container),0,-1):
            nstk.append(i)
        return nstk
    def push(self,val):
        self.container.append(val)
    def peek(self):
        return self.container
        
st = Stack()
lst= list('we defeated Corona')
st.push(lst)
print(st.peek())
revStack= st.rev()
print(revStack) 

为什么我不能使用下面的代码来反转...

def rev(self):
    self.container.reverse()

【问题讨论】:

反转后的字符串就是str[::-1],它提供了你想要的输出。 你能帮我分享一些代码吗。我是初学者 @Sauravsharma--我不清楚你的确切问题。您是否正在尝试为 dequeue 创建一个包装器来执行包括反向在内的操作?请注意,deque 本身具有反向操作。还要注意你的 self.container.append(val) 是附加一个列表而不是列表的元素。 【参考方案1】:

就地修改与返回修改后的副本

假设您有一个名为“CookieJar”的容器类

CookieJar 有一个名为 insert() 的方法

假设我们执行以下代码:

cj = CookieJar()
# [some time later...]
output = cj.insert("new cookie")

问题:

cj 是否与调用 insert() 方法之前相同? output 中究竟存储了什么?

在计算机编程中,有两种方法可以修改 cookie jar 的内容:

official name of the paradigm changes to input output
[unknown name] leave the input cookie jar alone. output a modified copy of the cookie jar
MODIFY IN-PLACE Modify the original cookie jar In python, output None. In languages other than python, (Java, C#, etc...) this would be known as a "void returning method"

计算机程序员最常犯的错误之一是他们假设 mutator 将返回容器的修改副本。

from collections import deque

my_deque = deque()
my_deque.appendleft("a")
my_deque.appendleft("b")
my_deque.appendleft("c")

print(my_deque)

output = my_deque.reverse()
print(output)
# output == None 

deque 类的reverse() 方法就地修改dequesreverse() 输出None

txt = "  kiwi  "

print("BEFORE `rstrip` txt is: ", repr(txt))

# ABOUT RSTRIP():
#     RSTRIP()` removes `\n`, `\r` `\t`, space, etc...
#     from the right-hand side of the string

output = txt.rstrip()

print("output is:", repr(output))
print("AFTER EXECUTING `rstrip()`, txt is: ", repr(txt))
MODIFY IN-PLACE RETURN MODIFIED COPY
AFTER EXECUTING rstrip(), what happens to txt? txt becomes: " kiwi" txt is still the original " kiwi "
What is the value returned by rstrip()? return value isNone return value is " kiwi"

计算机程序员对于他们选择使用哪种范式并不一致。

collections 库中的deque 类的mutator 方法修改了dequein-place。

字符串类str的python mutator方法,永远不要修改原始字符串。

【讨论】:

【参考方案2】:

简单的列表和普通函数

如果您只需要实现一个堆栈,我认为没有理由使用collections.deque。我们可以轻松地围绕一个简单的列表构建,[] -

# stack.py

def empty():
  return []

def push(t, x):
  t.append(x)

def pop(t):
  return t.pop()

def load(t, iterable):
  for x in iterable:
    push(t, x)

def unload(t):
  while t:
    yield pop(t)

使用堆栈很直观-

# main.py

import stack

input = "we have not defeated corona"

s = stack.empty()
stack.load(s, input)

output = "".join(stack.unload(s))

print(output)
anoroc detaefed ton evah ew

让它更像 python

如果您希望stack 具有更面向对象的感觉,我们可以在普通函数周围添加一个接口 -

# stack.py (continued)

class stack:
  def empty(): return stack(empty())
  def __init__(self, t): self.t = t
  def push(self, v): return push(self.t, v)
  def pop(self): return pop(self.t)
  def load(self, iterable): return load(self.t, iterable)
  def unload(self): return unload(self.t)

现在我们可以写main如下-

# main.py

from stack import stack

input = "we have not defeated corona"

s = stack.empty()
s.load(input)
output = "".join(s.unload())

print(output)
anoroc detaefed ton evah ew

扩展堆栈模块

继续往 Stack 模块添加其他功能 -

# stack.py (continued)

def reverse(t):
  t.reverse()

def peek(t):
  if not t:
    return None
  else:
    return t[-1]

在面向对象的界面中包装你的新函数 -

# stack.py (continued)

class stack:
  def empty(): ...
  def __init__(): ...
  def push(): ...
  def pop(): ...
  def load(): ...
  def unload(): ...
  def reverse(self): return reverse(self.t)  # <-
  def peek(self): return peek(self.t)        # <-

让我们验证 seekreverse 是否正常工作 -

# main.py

from stack import stack

input = "we have not defeated corona"

s = stack.empty()
s.load(input)

print(s.peek())
s.pop()
print(s.peek())
s.reverse()
print(s.peek())
a
n
w

相关阅读

在recent Q&A 中,我展示了如何设计类似于上述stack 的模块。如果您想了解随着程序的发展如何应用此技术,我鼓励您查看该帖子:D


持久堆栈

作为一个有趣的练习,我们可以在不使用dequelist 或任何其他内置数据容器的情况下实现堆栈。相反,我们将使用普通的None 和匿名函数。我分享这个例子是为了让你意识到程序员可以在他们的想象中构建任何东西,即使你使用的语言不包含特定的功能 -

# stack.py

empty = None

def push(t, v):
  return lambda k: k(t, v)

def pop(t):
  if not t:
    raise RuntimeError("cannot pop empty stack")
  else:
    return t(lambda next, v: (next, v))

def load(t, iterable):
  for v in iterable:
    t = push(t, v)
  return t

def unload(t):
  while t:
    (next, v) = pop(t)
    yield v
    t = next

def reverse(t):
  return load(empty, unload(t))

def peek(t):
  if not t:
    return None
  else:
    (_, v) = pop(t)
    return v

class stack:
  def empty(): return stack(empty)
  def __init__(self, t): self.t = t
  def push(self, v): return push(self.t, v)
  def pop(self):
    (next, v) = pop(self.t)
    return (stack(next), v)
  def load(self, iterable): return stack(load(self.t, iterable))
  def unload(self): return unload(self.t)
  def reverse(self): return stack(reverse(self.t))
  def peek(self): return peek(self.t)

每个堆栈操作都会创建一个堆栈,而不是使用.append.pop.reverse 修改底层堆栈。如果我们愿意,请注意我们如何unload 两次(或更多)堆栈 -

from stack import stack

input = "we have not defeated corona"

s = stack.empty().load(input)

print("".join(s.unload()))
print("".join(s.reverse().unload()))
print("".join(s.unload()))
anoroc detaefed ton evah ew
we have not defeated corona
anoroc detaefed ton evah ew

【讨论】:

以上是关于我想反转堆栈,但我不知道如何使用递归来反转这个......如何在不使用递归的情况下反转堆栈的主要内容,如果未能解决你的问题,请参考以下文章

这段代码如何反转? (递归)

C++:使用递归反转字符串

为什么我的递归函数不能遍历堆栈中的所有数据?

反转 UITableView 滚动行为

遍历列表时反转列表与非尾递归

在 PySpark 中反转 Group By