【问题标题】:Trying to build a Stack Algoritm using an array尝试使用数组构建堆栈算法
【发布时间】:2020-07-01 18:38:04
【问题描述】:

我正在尝试这样做,但它总是错误的。我不明白我应该怎么做...这是我的代码:

class WrongStack:
def __init__(self):        
    self.__items = numpy.array([])

def push(self, item): 
    numpy.concatenate(self.__items,item)

def pop(self):  
    return numpy.delete(self.__items,0,-1)

def peek(self):  
    return self.__items[len(self.__list) - 1]

def is_empty(self):            
    return len(self.__items) == 0

def size(self):                 
    return len(self.__items)


s = WrongStack()
number = input('Choose a number, 0 to finish')
while number != '0':
  s.push(numpy.array([nmr]))
  number = input('Choose a number, 0 to finish')
while not s.is_empty():
  number = s.pop()
  print(number)

错误是:

File "C:/Users/JJ/OneDrive - ISCTE-IUL/EDA/Aula 4.py", line 55, in <module>
s.push(numpy.array([nmr]))

File "C:/Users/JJ/OneDrive - ISCTE-IUL/EDA/Aula 4.py", line 38, in push
numpy.concatenate(self.__items,item)

File "<__array_function__ internals>", line 6, in concatenate
TypeError: only integer scalar arrays can be converted to a scalar index

我知道这不是构建普通堆栈的方法,但我必须这样做。

【问题讨论】:

  • 您使用 numpy 数组而不是简单列表是否有原因?
  • @DarrylG 这是我的数据结构和算法课上的一个练习。我认为实现这个算法之后的主要目标是说它是否具有与普通堆栈算法(使用列表)相比的良好性能。
  • 恐怕为此目的性能可能会比使用列表更差。 Numpy 有开销,但在对大量数据进行计算时它是值得的。对于您的简单使用,它可能会更慢。

标签: python arrays algorithm stack


【解决方案1】:

对您的代码进行修改以使其正常工作。

在我更改代码的地方放置了“Mod”。

代码

import numpy as np

class WrongStack:
  def __init__(self):        
      self.__items = np.array([])

  def push(self, item): 
      # Mod--concatenate takes list contains items to concatenate
      self.__items = np.concatenate([self.__items,item])

  def pop(self):  
      # Mod--np.delete returns a new array
            # also retrieve last element before delete
      last = self.__items[-1]
      self.__items = np.delete(self.__items,-1, 0)
      return last

  def peek(self):  
      return self.__items[len(self.__list) - 1]

  def is_empty(self): 
      # Mod--use function size    
      return self.size() == 0

  def size(self):                 
      return len(self.__items)

  def __str__(self):
    # Mod--added for display the array
    return str(self.__items)

s = WrongStack()
number = input('Choose a number, 0 to finish: ')
while len(number) > 0 and number != '0': #Mod done if no input or '0' entered
  # Mod--convert numer to integer
  s.push(np.array([number], dtype=np.int32)) # specify type (i.e. int32)
  number = input('Choose a number, 0 to finish: ')

# Mod--print array created
print('Array created:', s)

while not s.is_empty():
  number = s.pop()
  print('number: ', number)

测试

Choose a number, 0 to finish: 1
Choose a number, 0 to finish: 2
Choose a number, 0 to finish: 3
Choose a number, 0 to finish: 4
Choose a number, 0 to finish: 5
Choose a number, 0 to finish: 0
Array created: [1. 2. 3. 4. 5.]
number:  5.0
number:  4.0
number:  3.0
number:  2.0
number:  1.0

替代方案

依赖于 Numpy 固定大小的数组。使用切片和范围检查来确保我们保持在分配的大小范围内。

import numpy as np

class WrongStack:
  def __init__(self, maxlen=100):        
      self.__items = np.array([0]*maxlen) # Fixed size Numpy array
      self._count = 0
      self._maxlen = maxlen

  def push(self, item): 
      # Mod--concatenate takes list contains items to concatenate
      if self._count < self._maxlen:
        self.__items[self._count] = item
        self._count += 1
      else:
        print('push: no more space')


  def pop(self):  
      # Mod--np.delete returns a new array
            # also retrieve last element before delete
      if self._count > 0:
        last = self.__items[self._count-1]
        self._count -= 1
        return last
      else:
        return None

  def peek(self):
      if self._count > 0:
        return self.__items[self._count-1]
      else:
        return None

  def is_empty(self): 
      # Mod--use function size    
      return self.size() == 0

  def size(self):                 
      return self._count

  def __str__(self):
    # Mod--added for display the array
    return str(self.__items[:self._count])

s = WrongStack(10) # will handle stack with up to 10 elements
number = input('Choose a number, 0 to finish: ')
while len(number) > 0 and number != '0': #Mod done if no input or '0' entered
  # Mod--convert numer to integer
  s.push(number) # specify type (i.e. int32)
  number = input('Choose a number, 0 to finish: ')

# Mod--print array created
print('Array created:', s)

while not s.is_empty():
  number = s.pop()
  print('number: ', number)

【讨论】:

  • 我至少有一个问题。在 pop 函数中,当您编写:self.__items = np.delete(self.__items,-1, 0) 时,这会创建一个没有您删除的元素的新数组还是更改原始数组?我希望你明白我想说什么。并且原始数组在之后是否变为空:while not s.is_empty(): number = s.pop() print('number: ', number) ???
  • @JoãoJúlio--根据documentation delete 返回一个新数组。
  • @JoãoJúlio--这是一个shared online version of my running code,你可以试试。
  • @JoãoJúlio--扩展我之前的评论,因为 delete 返回一个新数组,这意味着在你原来的 pop 方法中 return numpy.delete(self.__items,0,-1) 离开 self.__items unchanged
  • @JoãoJúlio——this answer 指出 Numpy 数组的大小是固定的,因此无法更改。所以删除操作必须创建一个新数组。所以你是对的,Numpy 数组用作堆栈时效率低下,因为我们在从堆栈中添加(推送)和删除(弹出)元素时不断创建新数组。这就是为什么简单的list 更适合此目的。
【解决方案2】:

您正在尝试将 numpy 数组用作堆栈,这可能不会像您希望的那样工作。 Numpy 数组是为数学计算而设计的,而不是作为通用数据结构。

而只是使用 Python 列表来实现您的堆栈。事实上,Python 文档甚至包括 a section 来说明如何做到这一点:

>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]

【讨论】:

  • 我已经做过这种类型的堆栈了。现在我需要使用数组来构建堆栈,我被触发了,因为数组不适合这种类型的“工作”,而且我不知道如何更正这段代码。 @robbrit
猜你喜欢
  • 2015-02-04
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 2018-04-27
  • 2020-08-17
  • 1970-01-01
相关资源
最近更新 更多