程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Data structure Python Version (III) - stack

編輯:Python

Catalog

  • One 、 What is stack? ?
  • Two 、 Order of the stack
    • 2.1 Some applications of sequence stack
      • 2.1.1 Parentheses matching
      • 2.1.2 Smallest stack
  • 3、 ... and 、 Chain stack
    • 3.1 Some applications of chain stack
      • 3.1.1 Legal stack sequence
  • Four 、LeetCode actual combat
    • 4.1 LeetCode#71—— Simplified path
    • 4.2 LeetCode#735—— Planetary collision
    • 4.3 LeetCode#143—— Rearrange the list

One 、 What is stack? ?

Stack is a method that can only be used in At the same end Insert / Delete the The linear table . Insertion is allowed in the table / One end of the delete operation is called To the top of the stack . The current position of the top of the stack is dynamic , You can use a position indicator called the stack top pointer to indicate . The other end of the table is called At the bottom of the stack . When there are no elements in the stack, it is called Empty stack . The insertion operation of stack is usually called Into the stack or Push , The deletion of the stack is usually called Out of the stack or Backstack .

A major feature of stack is LIFO, namely Last In First Out.

The definition of abstract data type stack is as follows :

Data objects : D = { a i ∣ 0 ≤ i ≤ n − 1 , n ≥ 0 } Data relation : R = { r } r = { < a i , a i + 1 > ∣ a i , a i + 1 ∈ D , i = 0 , ⋯ , n − 2 } Basic operation : empty() : sentence break Stack yes no by empty push(e) : take e Pressure Enter into Stack in pop() : take Out Stack The top element plain gettop() : return return Stack The top element plain \begin{aligned} &\text{ Data objects :} D=\{a_i|0\leq i\leq n-1,n\geq0\} \\ &\text{ Data relation :} \\ &\quad R = \{r\} \\ &\quad r=\{<a_i,a_{i+1}>|a_i,a_{i+1}\in D,i=0,\cdots, n-2\} \\ &\text{ Basic operation :} \\ &\quad \text{empty()}: Judge whether the stack is empty \\ &\quad \text{push(e)}: take e Pressure into the stack \\ &\quad \text{pop()}: Take out the top element of the stack \\ &\quad \text{gettop()}: Back to top of stack element \\ \end{aligned} ​ Data objects :D={ ai​∣0≤i≤n−1,n≥0} Data relation :R={ r}r={ <ai​,ai+1​>∣ai​,ai+1​∈D,i=0,⋯,n−2} Basic operation :empty(): sentence break Stack yes no by empty push(e): take e Pressure Enter into Stack in pop(): take Out Stack The top element plain gettop(): return return Stack The top element plain ​

Two 、 Order of the stack

Because the logical relationship of the elements in the stack is the same as that of the linear table , Therefore, we can learn from the two storage structures of linear tables to store stacks .

When using sequential storage structure to store , Use list data To store the elements in the stack , be called Order of the stack . because Python The list provides the function of dynamic expansion at one end , For this reason will data[0] As the bottom of the stack , take data[-1] As the top of the stack , among len(data) Represents the number of elements in the stack .

Next, we directly and completely implement the basic functions of the sequence stack :

class SqStack:
def __init__(self):
self.data = []
def empty(self):
return len(self.data) == 0
def push(self, e):
self.data.append(e)
def pop(self):
assert not self.empty()
return self.data.pop()
def gettop(self):
assert not self.empty()
return self.data[-1]

You can see from the above , The time complexity of various basic operations of the stack is O ( 1 ) \mathcal{O}(1) O(1).

2.1 Some applications of sequence stack

2.1.1 Parentheses matching

Suppose that the expression entered by the user contains parentheses 、 Square brackets and curly braces , And only these brackets . Design an algorithm to determine whether the parentheses in the expression are paired .

We can use sequence stack to solve this problem :

def is_match(string):
stack = SqStack()
for e in string:
if e == '(' or e == '[' or e == '{':
stack.push(e)
else:
if e == ')':
if stack.empty() or stack.gettop() != '(':
return False
stack.pop()
if e == ']':
if stack.empty() or stack.gettop() != '[':
return False
stack.pop()
if e == '}':
if stack.empty() or stack.gettop() != '{':
return False
stack.pop()
return stack.empty()
string_1 = '([)]'
string_2 = '([])'
print(is_match(string_1))
# False
print(is_match(string_2))
# True

2.1.2 Smallest stack

Design a minimum stack . That is, based on the original stack structure , Add one getmin() Method , Used in O ( 1 ) \mathcal{O}(1) O(1) Return the smallest element in the stack within the time of .

We can add one to the original mindata list , among data The list represents the main stack ,mindata The list represents the auxiliary stack , Used to store the current minimum element ( notes :mindata There may be multiple elements in ).

class SqStack:
def __init__(self):
self.data = []
self.__mindata = []
""" min The basic operation of stack """
def __minempty(self):
return len(self.__mindata) == 0
def __minpush(self, e):
self.__mindata.append(e)
def __minpop(self):
assert not self.__minempty()
return self.__mindata.pop()
def __mingettop(self):
assert not self.__minempty()
return self.__mindata[-1]
""" Basic operation of main stack """
def empty(self):
return len(self.data) == 0
def push(self, e):
if self.empty() or e <= self.getmin():
self.__mindata.append(e)
self.data.append(e)
def pop(self):
assert not self.empty()
x = self.data.pop()
if x == self.__mingettop():
self.__minpop()
return x
def gettop(self):
assert not self.empty()
return self.data[-1]
def getmin(self):
assert not self.empty()
return self.__mindata[-1]

3、 ... and 、 Chain stack

The stack with chain storage structure is called chain stack , Here we use single linked list to realize .

The advantage of chain stack is that it doesn't need to consider stack overflow .

As shown in the figure , The first node is the top node of the stack , The tail node is the bottom node . The four elements of the chain stack are as follows :

  • Stack empty condition :head.next == None;
  • The stack condition is full : Unless memory overflows , Otherwise, don't consider ;
  • Elements e e e Into the stack : The node that will contain the element s s s Insert as the first node ;
  • The stack, : Return the value of the first node and delete the node .

The type of each node in the chain stack is the same as that of the ordinary single chain list :

class LinkNode:
def __init__(self, data=None, next=None):
self.data = data
self.next = next

The design of the chain stack class is as follows :

class LinkStack:
def __init__(self):
self.head = LinkNode()
self.head.next = None

Next, we implement the basic operation of the stack in the chain stack :

class LinkStack:
def __init__(self):
self.head = LinkNode()
self.head.next = None
def empty(self):
return self.head.next == None
def push(self, e):
s = LinkNode(e)
s.next = self.head.next
self.head.next = s
def pop(self):
assert not self.empty()
p = self.head.next
self.head.next = p.next
return p.data
def gettop(self):
assert not self.empty()
return self.head.next.data

3.1 Some applications of chain stack

3.1.1 Legal stack sequence

The same stack sequence can produce different stack sequences . for example , Set the stack sequence as ( 1 , 2 , 3 , 4 , 5 ) (1,2,3,4,5) (1,2,3,4,5), We can let 1 , 2 , 3 1,2,3 1,2,3 Push 、 Out of the stack , let 4 , 5 4,5 4,5 Push 、 Out of the stack , The stack sequence thus obtained is ( 3 , 2 , 1 , 5 , 4 ) (3,2,1,5,4) (3,2,1,5,4). We can also let 1 , 2 1,2 1,2 Push 、 Out of the stack , let 3 , 4 , 5 3,4,5 3,4,5 Push 、 Out of the stack , The stack sequence thus obtained is ( 2 , 1 , 5 , 4 , 3 ) (2,1,5,4,3) (2,1,5,4,3).

Given the stack sequence a, Design an algorithm to judge b Whether it is a Legal stack sequence of ( among a and b Are all 1 ∼ n 1\sim n 1∼n An arrangement of ).

We just need to simulate the process :

def is_valid(a, b):
stack = SqStack()
j = 0
for i in range(len(a)):
stack.push(a[i])
while not stack.empty() and stack.gettop() == b[j]:
stack.pop()
j += 1
return stack.empty()
print(is_valid([1, 2, 3, 4], [1, 3, 2, 4]))
# True
print(is_valid([1, 2, 3, 4], [4, 3, 1, 2]))
# False

Four 、LeetCode actual combat

4.1 LeetCode#71—— Simplified path



The problem is very simple , There is no need for too much explanation .

But here's the thing , For the sake of simplicity , We use lists directly to simulate stacks , No longer write a class alone .

class Solution:
def simplifyPath(self, path: str) -> str:
stack = list()
for s in path.split('/'):
if s:
if s != '.' and s != '..':
stack.append(s)
if s == '..' and stack:
stack.pop()
return '/' + '/'.join(stack)

4.2 LeetCode#735—— Planetary collision


class Solution(object):
def asteroidCollision(self, asteroids):
stack = list()
for new in asteroids:
while stack and new < 0 < stack[-1]:
if stack[-1] < -new:
stack.pop()
continue
elif stack[-1] == -new:
stack.pop()
break
else:
stack.append(new)
return stack

4.3 LeetCode#143—— Rearrange the list


The specific idea is , First, find the intermediate node , Then cut off the first half and the second half of the list , Then reverse the linked list in the second half , Finally, merge the two linked lists .

class Solution:
def reorderList(self, head: ListNode) -> None:
if not head:
return
mid = self.middleNode(head)
l1 = head
l2 = mid.next
mid.next = None
l2 = self.reverseList(l2)
self.mergeList(l1, l2)
def middleNode(self, head: ListNode) -> ListNode:
slow = fast = head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
return slow
def reverseList(self, head: ListNode) -> ListNode:
prev = None
curr = head
while curr:
nextTemp = curr.next
curr.next = prev
prev = curr
curr = nextTemp
return prev
def mergeList(self, l1: ListNode, l2: ListNode):
while l1 and l2:
l1_tmp = l1.next
l2_tmp = l2.next
l1.next = l2
l1 = l1_tmp
l2.next = l1
l2 = l2_tmp

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved