数据结构笔记-栈与队列 python

概述

栈与队列是程序设计中被广泛应用的两种重要的数据结构,都是在特定范围的存储单元内存储数据,这些数据都可以被重新取出使用,与线性表相比,他们的插入和删除受到更多的约束,固又称限定性的线性表结构。他们是最简单的缓存结构,他们只支持数据项的存储与访问,不支持数据项之间的任何关系。因此,这两种数据集合都很小,很简单,其中最重要的操作就是元素的存入与取出。作为数据结构,他们还需要几个任何数据结构都需要的操作,如结构的创建,检查是否为空状态等。

在计算中,中间数据对象的生成有早有晚,存在时间上的先后顺序。在后面使用这些元素时,也可能需要考虑他们的生成时间顺序。

→栈是保证元素后进先出(后存入者先使用,Last In First Out,LIFO)关系的结构。

→队列是保证元素先进先出(先存入者先使用,First In First Out)关系的结构。

 

1.栈

栈是一种容器,可存入数据,访问元素,删除元素等。存入栈中的元素相互之间没有任何具体关系,只有到来的时间先后顺序。在这里没有元素的位置,元素的前后顺序等概念。栈的基本性质保证,在任何时刻可以访问,删除的元素都是在此之前的最后存入的那个元素。因此,栈确定了一种默认元素的访问顺序,访问数无需其他信息。

 

1_1.栈的抽象数据类型描述:

ADT Stack:
    Stack(self)    #创建空栈
    is_empty(self) #判断栈是否为空,空时返回True否则返回False
    push(self,e)   #将元素elem加入栈,称为压入或推入
    pop(self)      #删除栈里最后压入的元素并将其返回,常称为弹出
    top(self)      #取得栈里最后压入的元素,不弹出

1_2.栈的数组实现

把数组的首元素当做栈底,同时记录栈中的个数size,假设数组的首地址为arr,压栈的操作就是将元素放入arr[size],弹栈就是取数组arr[size-1]的元素,然后执行size减一,根据这个原理实现栈。

#!/usr/bin/python
# -*- coding:utf-8 -*-  

#实现栈
#方法一:数组实现栈
class MyStack:
	__slots__ = ('items')#该属性仅对当前类有用 继承类没用
	#模拟栈
	def __init__(self):
		self.items = []
	#判断栈是否为空
	def is_empty(self):
		return len(self.items)==0
	#返回栈的大小
	def size(self):
		return len((self.items))
	#返回栈顶元素
	def top(self):
		if not self.is_empty():
			return self.items[len(self.items)-1]
		else:
			return None
	#弹栈
	def pop(self):
		if len(self.items)>0:
			return self.items.pop()
		else:
			print('栈已经为空')
			return None
	#压栈
	def push(self,item):
		self.items.append(item)

if __name__ == "__main__":
	s = MyStack()
	s.push(4)
	s.push(3)
	s.push(2)
	s.push(1)
	print('栈顶元素: '+str(s.top()))
	print('栈大小为: '+str(s.size()))
	s.pop()
	print('弹栈成功')
栈顶元素: 1
栈大小为: 4
弹栈成功
[Finished in 0.1s]

 

1_3.栈的列表实现

由于数组的初始大小会占用多余的内存,且在元素量未知的情况下可能会出现扩容的情况,因此也可以使用链表实现栈,但相应的增加了空间代价记录指针位置,但也是一种方法。在执行压栈操作时,只需把链表首节点的next指针指向当前压入元素,再把当前元素next指针指向之前首节点指向的元素地址即可,弹出元素就更简单了,只需修改首节点指针到head.next.next的位置,显示head.next.data即可完成弹栈操作。

#方法二:链表实现
class LNode:
	def __init__(self,x,next_=None):
		self.data = x
		self.next = next_

class MyStack:
	def __init__(self):
		#pHead=LNode()
		self.data = None
		self.next = None
	#判断stack是否为空,如果空返回true,否则返回false

	def empty(self):
		if self.next ==None:
			return True
		else:
			return False

	#获取栈中元素个数
	def size(self):
		size = 0
		p = self.next
		while p != None:
			p = p.next
			size += 1
		return size

	#入栈:放入栈顶
	def push(self,e):
		p = LNode(e)
		p.next = self.next#None
		self.next = p

	def pop(self):
		tmp = self.next
		if tmp != None:
			self.next = tmp.next
			return tmp.data
		print('栈已空')
		return None

	def top(self):
		if self.next != None:
			return self.next.data
		print('栈已空')
		return None

if __name__ == '__main__':
	stack = MyStack()
	stack.push(4)
	stack.push(3)
	stack.push(2)
	stack.push(1)
	print('栈顶元素为: '+str(stack.top()))
	print('栈大小为: '+str(stack.size()))
	stack.pop()
	print('弹栈成功')

与前面数组不同的是,这里需要自定义链表结构LNode.

栈顶元素为: 1
栈大小为: 4
弹栈成功
[Finished in 0.1s]

 

2.队列

队列也称为队,队列中也没有位置的概念,只支持默认的元素存入与取出,其特点就是保证在任何时候访问或删除的元素,都是在此前最早存入队列且尚未删除的那个元素。可以借用数据的存储顺序表示数据的存储时间的先后关系,用线性表作为队列的实现结构,利用元素的存储顺序表示其访问顺序。

2_1.队列的抽象数据类型描述:

ADT Queue:
    Queue(self)        #创建空队列
    is_empty(self)     #判断队列是否为空,空返回True否则返回False
    enqueue(self,e)    #将元素elem加入队列,称为入队
    dequeue(self)      #删除队里最早进入的元素,称为出队
    peek(self)         #查看队列最早进入的元素,不删除

2_2.队列的数组实现

用两个指针front和rear记录队列的首尾元素位置,入队只需将入队元素放到rear的位置,同时执行rear+,出队时只需执行front+的操作即可。

#!/usr/bin/python
# -*- coding:utf-8 -*-  

#方法一:队列实现
class MyQueue:
	def __init__(self):
		self.arr = []
		self.front = 0#队列头
		self.rear = 0#队列尾

	def isEmpty(self):
		return self.front == self.rear
	#返回队列的大小
	def size(self):
		return self.rear - self.front
	#返回队列首元素
	def getFront(self):
		if self.isEmpty():
			return None
		return self.arr[self.front]
	#返回队尾元素
	def getBack(self):
		if self.isEmpty():
			return None
		return self.arr[self.rear-1]
	#删除队列头元素
	def deQueue(self):
		if self.rear>self.front:
			self.front +=1
		else:
			print("队列已空")
	#增加队列元素
	def enQueue(self,item):
		self.arr.append(item)
		self.rear += 1

if __name__ == '__main__':
	queue = MyQueue()
	queue.enQueue(1)
	queue.enQueue(2)
	print('队列首元素'+str(queue.getFront()))
	print('队尾元素'+str(queue.getBack()))
	print('队列大小:'+str(queue.size()))
队列首元素1
队尾元素2
队列大小:2
[Finished in 0.1s]

 

2_3.队列的链表实现

采用链表实现队列与实现栈方法类似,通过使用头指针pHead与尾指针pEnd指向对首先与队尾元素,新元素入队只需将pEnd指针指向新元素并修改pEnd+1,出队则需要修改pHead指针到pHead.next.next,其他不变。

#方法二:链表实现
class LNode:
	def __init__(self,x,next_=None):
		self.data = x
		self.next = next_

class MyQueue:
	#分配头结点
	def __init__(self):
		self.pHead = None
		self.pEnd = None
	#判断队列是否为空
	def isEmpty(self):
		if self.pHead == None:
			return True
		else:
			return False
	#获取栈中元素
	def size(self):
		size = 0
		p = self.pHead
		while p != None:
			p = p.next
			size += 1
		return size
	#入队列:向队列加入元素e
	def enQueue(self,e):
		p = LNode(e)
		p.next = None
		if self.pHead == None:
			self.pHead = self.pEnd = p
		else:
			self.pEnd.next = p
			self.pEnd = p
	#出队列
	def deQueue(self):
		if self.pHead == None:
			print("出队列失败,队列为空")
		print('出队元素:'+str(self.pHead.data))
		self.pHead = self.pHead.next
		if self.pHead == None:
			self.pEnd = None
	#取得队列首元素
	def getFront(self):
		if self.pHead == None:
			print("队列为空")
			return None
		return self.pHead.data
	#取得队尾元素
	def getBack(self):
		if self.pEnd == None:
			print("队列为空")
			return None
		return self.pEnd.data

if __name__ == "__main__":
	queue = MyQueue()
	queue.enQueue(1)
	queue.enQueue(2)
	print('队列首元素'+str(queue.getFront()))
	print('队尾元素'+str(queue.getBack()))
	print('队列大小:'+str(queue.size()))
队列首元素1
队尾元素2
队列大小:2
[Finished in 0.1s]

 

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