[数据结构] 栈&队列

一. 栈(stack)

栈是限定只能在一端进行插入和删除操作的线性数据结构,具有后进先出(last in first out,LIFO)的特征.

    

 

栈允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零 时称为空栈。插入一般称为进栈(PUSH),删除则称为出栈(POP)。对于进栈和出栈而言,时间复杂度都为O(1).

 

(一). 栈的Python实现

对于stack, 可以使用python内置的list实现. list属于线性表,可以用下标为0的一端作为栈底, 定义一个top变量来指向栈顶元素在数组中的位置.

 1 class Stack(object):
 2     def __init__(self, limit = 20):
 3         self.items = []    # 初始化为空列表
 4         self.limit = limit    # 指定栈的容量
 5 
 6 
 7     '''判断栈是否为空,返回布尔值'''
 8     def is_empty(self):
 9         return self.items == []
10 
11 
12     '''返回栈的大小'''
13     def size(self):
14         if self.items:
15             return len(self.items)
16 
17 
18     '''查看堆栈最上面的元素'''
19     def peek(self):
20         if self.items:
21             return self.items[len(self.items)-1]
22 
23 
24     '''入栈'''
25     def push(self,value):
26         if len(self.items) >= self.limit:
27             raise IndexError('index out of range!')
28         else:
29             self.items.append(value)
30 
31 
32     '''出栈'''
33     def pop(self):
34         if self.items:
35             self.items.pop()
36         else:
37             raise IndexError('can not pop item from an empty stack')
38 
39 
40 # 测试
41 if __name__ ==  "__main__":
42     # 初始化一个栈对象
43     my_stack = Stack()
44     my_stack.push('a')
45     my_stack.push('bc')
46     print(my_stack.size())
47     print('---1---')
48     print(my_stack.peek())
49     print('---2---')
50     my_stack.pop()
51     print(my_stack.peek())
52     print('---3---')
53     print(my_stack.size())
54     print('---4---')
55     my_stack.pop()
56     print(my_stack.is_empty())

tips. 实际应用中, 栈不需要我们自己定义,使用列表结构即可:

  1. 进栈:append

  2. 出栈:pop

  3. 查看栈顶:list [-1] 直接取索引

 

(二). 栈的常见应用

1. 递归 -- 斐波那契数列

 Fibonacci数列定义: f(0) = 0,  f(1) = 1,  f(n) = f(n-1) + f(n-2)

 1 '''栈的应用 -- 1. 递归'''
 2 # 实现斐波那契数列
 3 
 4 def fibonacci_recursion(n):
 5     if n < 2:
 6         return n
 7     else:
 8         return fibonacci_recursion(n-1) + fibonacci_recursion(n-2)
 9 
10 # 测试
11 if __name__ == "__main__":
12     input = int(input('请输入数字:'))
13     if input < 0:
14         print('请输入正整数')
15     else:
16         print(fibonacci_recursion(input))

 

2. 括号匹配

  思路:

  (1). 只要碰到左括号, 进栈;

  (2). 一旦碰到右括号, 先判断栈顶与当前字符是否是一对;

  (3). 如果匹配, 就让栈顶的左括号出栈, 继续下一个字符;

  (4). 如果不匹配, 直接return False;

 1 def balance_parentheses(parentheses):
 2     stack = Stack(len(parentheses))   # 初始化一个栈(数组)
 3     balance = {'}':'{', ')':'(', ']':'[', '>':'<','':''}    # 字典:方便一一对应
 4     for parenthesis in parentheses:
 5         if parenthesis in balance.values():    # 如果是左括号
 6             stack.append(parenthesis)
 7         elif parenthesis in balance.keys():
 8             if balance[parenthesis] != stack.pop():
 9                 return False
10     return True
11 
12 # 测试
13 if __name__ == "__main__":
14     examples = ['((){})《','()()<>()(','','(({})))']
15     for example in examples:
16         print(example+':'+ str(balance_parentheses(example)))

 

 二. 队列 

 队列(queue)是一种具有先进先出特征的线性数据结构,元素的增加只能在一端进行,元素的删除只能在另一端进行。能够增加元素的队列一端称为队尾,可以删除元素的队列一端则称为队首.

   

 队列符合先进先出[FIFO]的原则.

 队列有两种实现形式:数组链表.

 队列属于常见的一种线性结构,对于出队和进队而言,时间复杂度都为 O(1).

 

(一). 队列的python实现

对于queue, 可以使用列表简单模拟队列. 可以用下标为0的一端作为队头,保证先进的先出. 队尾就是list[len(list)-1] 这个元素.

 1 # python 实现队列
 2 class Queue(object):
 3     def __init__(self, size):
 4         self.size = size
 5         self.queue = []
 6 
 7     '''判断队列是否满了'''
 8     def is_full(self):
 9         if len(self.queue) == self.size:
10             return True
11         return False
12 
13     '''判断队列是否为空'''
14     def is_empty(self):
15         return self.queue == []
16 
17     '''获取当前队列的长度'''
18     def get_length(self):
19         return len(self.queue)
20 
21     '''入队'''
22     def enqueue(self,item):
23         if self.is_full():
24             raise IndexError('full error')
25         self.queue.append(item)
26 
27     '''出队'''
28     def dequeue(self):
29         if self.is_empty():
30             raise IndexError('empty error')
31         first_ele = self.queue[0]
32         self.queue.remove(first_ele)
33         return first_ele
34 
35 # 测试
36 if __name__ == '__main__' :
37   queueTest = Queue(5)
38   for i in range(5) :
39     queueTest.enqueue(i)
40   print(queueTest.is_full())
41   print(queueTest.get_length())
42   queueTest.dequeue()
43   print(queueTest.is_empty())
44   print(queueTest.get_length())

 

(二). python内置的队列模块  --  queue

 Python有自己的队列模块,我们只需要在使用时引入该模块就行.并且支持双向队列,优先级队列等;

 

 [ 队列分类 ]:

      

 

 [ 队列的方法 ]:

      

  

1. 单向队列

from collections import Queue

q = queue.Queue(10)    # 不设置长度的话,默认为无限长度
print(q.maxsize)    # 无括号
q.put(111)
q.put('abc')
q.put(['d','f'])
print(q.get())
print(q.get())
print(q.get())
------------- 10 111 abc ['d', 'f']

 

2. 后进先出队列

from collections import LifoQueue

q = queue.LifoQueue(10)    # 不设置长度的话,默认为无限长度
print(q.maxsize)    # 无括号
q.put(111)
q.put('abc')
q.put(['d','f'])
print(q.get())
print(q.get())
print(q.get())

------------
10
['d', 'f']
abc
111

 

3.优先级队列

优先级队列put的是一个元组,(优先级,数据),优先级数越小,级别越高.

from collections import PriorityQueue

q = queue.PriorityQueue()
print(q.maxsize)    # 无括号
q.put((1,'111'))
q.put((2,'abc'))
q.put((1,'def'))
print(q.get())
print(q.get())
print(q.get())

-------------
0
(1, '111')
(1, 'def')
(2, 'abc')

 

4. 双线队列

from collections import deque

q = queue.deque()
q.append(111)
q.append('abc')
q.appendleft('def')
print(q)
print(q.pop())
print(q.popleft())

---------------

deque(['def', 111, 'abc'])
abc
def

 

  🔚👋 

 

 

 

 

 

 

 

posted @ 2020-09-25 14:36  RheaH  阅读(139)  评论(0编辑  收藏  举报