栈:概念与实现

栈(stack)是一种容器,可存入数据元素,访问元素,删除元素等。存入栈中的元素之间相互没有任何具体联系,只有到来的先后顺序。
栈可以实现为在一端进行插入和删除的线性表,因此也称为后进先出表(LIFO)
在表实现中,执行插入和删除一端的操作称为栈顶,另一端称为栈底。访问和弹出的都应该显是栈顶元素。

  • 对于顺序表,后端插入和删除是O(1)时间操作,应该用后端作为栈顶
  • 对于链接表,前端插入和删除都是O(1)时间操作,应该用前端作为栈顶

1 栈的顺序表实现

  • 建立空栈对应于创建一个空表 [] ,判断空栈对应于检查是否为空表
  • 由于list 采用动态顺序表技术(分离式实现),作为栈的表不会满
  • 压入元素在表单尾端进行,对应于lst.append(x)
  • 访问栈顶元素应该用 list[-1]
  • 弹出元素操作也应该在表单尾端进行,无参数的lst.pop()默认弹出表尾元素
这里把list 当做栈使用,完全可以满足应用的需要。但是这样的对象还是list,提供了list 类型的所有操作,
特别是提供了一大批栈结构原来不应该支持的操作,威胁安全性
例如:栈要求未经弹出的元素应该存在,但是表允许删除。

现在考虑基于顺序表定义一个栈类,使之成为一个独立的类型,把Python 的list隐藏在这个类的内部,作为其实现基础。
下面是一个栈类的定义,其中用一个list类型的数据属性_elems作为栈元素存储区,用_elems的首端作为栈底,尾端作为栈顶

class SStack():									# 基于顺序表实现的栈类		
	def __init__(self):							# 用list对象_elems存储栈中元素
		self._elems = [ ]							# 所有栈操作都映射到栈操作

	def is_empty(self):
		return self._elems == [ ]

	def top(self):
		if self._elems == [ ]:
			raise StackUnderflow( 'in stack.top()' )
		else:
			return self._elems[-1]
	def push(self, elem):
		self._elems.append(elem)

	def pop(self):
		if self._elems == []:
			rasie StacakUnderflow(' in stack.pop()')
		else:
			return self._elems.pop()

以上代码都是基于Python 的list实现,所有理解起来不是很难

2 栈的链接表实现

使用顺序表实现栈,还是有些缺点,比如当list的元素存储区满了以后,要扩大元素存储区是一次高代价操作,而且,顺序表还需要完整的大的存储区。链接表的实现在这两个问题上都有优势。
当然,链接表的缺点是更多的依赖是解释器的存储管理,每个节点的链接开销,以及链接结点在实际计算机内存中任意散步可能带来的操作开销。
采用链接表技术,自然用表头一端作为栈顶,表尾作为栈底

class LStack():				# 基于链接表技术实现的栈类,用LNode作为结点
	def __init__(self):
		self._top = None
	
	def is_empty(self):
		return self._top is None

	def top(self):
	    if self._top is None:
	    	raise StackUnderflow('in LStack.top()')
	    else:
	        return self._top.elem

    def push(self, elem):
        # 入栈->链接表->插入首端->新元素成为首元素
        # 此时self._top 等于新的元素
        self._top = LNode(elem, self._top)

    def pop(self):
    	if self._top is None:
    		raise StackUnderflow("in LStack.pop()")
    	p = self._top
    	# 移除第一个元素,此时首元素为原先的第二个
    	self._top = p.next
    	return p.elem
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值