It's not easy to create, my guest, pay attention, collect and subscribe to one button three times ❤😜
preface
Program = data structure + algorithm. Algorithm is a mixture of mathematical theory and engineering implementation. It is a very interesting and magical knowledge. Understanding the algorithm and looking at programming from another perspective will be a new feeling. If you are also learning the algorithm, you might as well learn with director Mengxin super poor and win the algorithm!
Catalogue of series articles
python daily algorithm | Radix sorting PK quick sorting, hand tearing Radix sorting algorithm!
python daily algorithm | picture and text + vivid example detailed bucket sorting
python daily algorithm | uncover the secret of counting and sorting
summary
This issue will introduce the basic knowledge of data structure (I): stack and queue and the most classic maze problem.
catalogue
Super python daily algorithm mind map
Basic knowledge of data structure
Logical structure of data structure
Implementing stack with python
Application of stack: bracket matching problem
Implementation mode of queue: Ring queue
Implementing queue with python
python queue built-in module: deque
Application of queue: using deque to implement Linux tail command
Super python daily algorithm mind map
Basic knowledge of data structure
What is the data structure?
Data structure refers to the collection of data elements with one or more relationships and the relationship between data elements in the collection. Simply put, data structure is to design how data is organized and stored in the computer.
For example, lists, sets and dictionaries are all data structures.
N.Wirth said, "program = data structure + algorithm"
Logical structure of data structure
According to its logical structure, data structure can be divided into linear structure, tree structure and graph structure.
linear structure
Linear structure: there is a one-to-one relationship between the elements in the data structure, such as a list.
Tree structure: there is a one to many relationship between the elements in the data structure, such as heap.
Graph structure: the elements in the data structure have many to many relationships
list
List (called list in python and array in other languages) is a basic data type.
Questions about lists:
How are the elements in the list stored?
On a 32-bit machine, an integer occupies 4 bytes, an address occupies 4 bytes, and a 64 bit address occupies 8 bytes.
The existing list is as follows:
1 | 2 | 3 | 4 | 5 |
Taking a 32-bit machine as an example, the array is stored as follows:
If the memory address of element 1 is 100, the memory address of element 2 is 104, and so on, then a[2]=100+2*4=108.
For the list, if the address of 1 is 200, 2 -- > 300, 3 -- 88, the list is to find the address, and then find the corresponding element through an address.
200 | 300 | 88 |
The difference between array and list:
1. The element types of the array need to be consistent, and the element types of the list do not need to be consistent;
2. The length of the array is fixed, and the python list can be infinite.
Basic operations of the list: insert elements, delete elements... What is the time complexity of these operations?
Insert: O(n). Each insert will move the front and rear elements
Delete (pop): O(n). The following address will be moved forward after each deletion
Stack
What is the stack
Stack is a data set, which can be understood as a list that can only be inserted or deleted at one end.
Stack features: LIFO (last in, first out)
For example, for a pile of books in the picture, the last one is the most advanced and the first to go out.
The concept of stack: top and bottom of stack
Basic operation of stack
Stack: push, (put another book on a pile of books)
Out of stack: pop (take the top book of a stack of books)
Take the top of the stack: gettop (I only read what the top book is)
Implementing stack with python
Stack implementation: the stack can be realized by using the general list structure.
Stack: lst.append()
Stack out: lst.pop()
Stack top: lst[-1]
class stack: def __init__(self): self.stack = [] def push(self,element): self.stack.append(element) # Stack operation def pop(self): return self.stack.pop() # Delete stack top def get_top(self): if len(self.stack) > 0: # Make sure there are elements in the stack return self.stack[-1] # Take stack top else: return None stack = stack() stack.push(1) stack.push(2) stack.push(3) stack.push(4) print(stack.pop()) print(stack) print(stack.get_top()) # Output results: # 4 # <__main__.stack object at 0x000001CC63BBEFD0> # 3
Application of stack: bracket matching problem
Bracket matching problem: give a string, including parentheses, brackets and braces, and find out whether the brackets in the string match.
For example:
() [] {} -- > match
([{()}]) -- > match
[] (-- > mismatch
[(]) -- > mismatch
#Bracket mismatch problem
"""
For example: () [] [{()}]
1. The "(" at the top of the stack matches the next ")" at the top of the stack, and the stack is pushed out of the stack;
2. Next, the "[" at the top of the stack matches "]" and "[" comes out of the stack
3. Stack top: "[", followed by "{" in the stack, followed by "(" in the stack, ")" in the stack and matched at the top of "C", so the stack is pushed out of the stack
4. Next "}" is matched with "{" at the top of the stack, and the stack is pushed out of the stack
5. "]" enters the stack, matches "[" at the top of the stack, and exits the stack
"""
def brace_match(str1): match_dict = {')':'(','}':'{',']':'['} # Establish matching mechanism stack = Stack() for i in str1: if i in {'(','[','{'}: # Left part stack stack.push(i) else: # i in {')','}',']'} if stack.is_empty(): return False elif stack.get_top() == match_dict[i]: stack.pop() else: # The stack character does not match the top of the stack return False if stack.is_empty: return True else: return False print(brace_match("{{[()]}}")) # Output: # True print(brace_match("{{[()]{()}}}")) # Output: # True print(brace_match("{[)]{()}}")) # output # False
queue
What is the queue
Queue: a queue is a data collection. It can only be inserted at one end of the list and deleted at the other end.
The end of the insertion is called the end of the team (rear), and the insertion action is called entering the team or joining the team
The end of the deletion is called the front, and the deletion action is called out of the queue
Nature of queue: first in, first out
Bidirectional queue
Both ends of the two-way queue support incoming and outgoing operations. The basic operations of the two-way queue are as follows:
Team first team
Team first team
Team tail into team
Out of the team at the end of the team
Implementation mode of queue: Ring queue
As shown in the figure, in the out of queue and in queue process of bit ring queue, rear=front is empty.
1.A enters the team, rear -- > + 1
2.BCDEFGH enters the team, and the rear increases by 1 in turn
3.ABCD out of the team, front -- > 5, team head -- > F, team tail -- > H
4.IJKM enters the team -- > near plus 1
5. When P enters the team, the team is full. (why does rear and front not coincide? To ensure whether the team is empty or full.)
Therefore, the team is full -- > rear + 1 = front, air to air: rear = front
Ring queue: when the end of the queue pointer front == Maxsize (queue length) - 1, another position will automatically reach 0
Head of line pointer forward 1: front = (front + 1)% maxsize
End of queue pointer forward 1: rear = (rear + 1)% maxsize
Air condition: rear == front
Full queue condition: (rear + 1)% maxsize = = front
Implementing queue with python
class Queue: def __init__(self,size=100): #Queue length is 100 self.size = size self.queue = [0 for i in range(size)] self.rear = 0 # Tail pointer self.front = 0 # Header pointer def push(self,element): # Join the team if not self.is_filled(): # Ensure team dissatisfaction self.rear = (self.rear+1) % self.size self.queue[self.rear] = element else: raise IndexError("Queue is filled") def pop(self): # Out of the team if not self.is_empty(): # Make sure the team is not empty self.front = (self.front + 1) % self.size return self.queue[self.front] else: raise IndexError("Queue is empty.") def is_empty(self): # Judge team empty return self.rear == self.front def is_filled(self): # Judge team full return (self.rear + 1) % self.size == self.front q = Queue(5) for i in range(4): q.push(i) print(q.pop()) q.push(13) print(q.pop()) q2 = Queue(5) for i in range(5): q.push(i) print(q.is_filled()) # Output results # 0 # 1 # IndexError: Queue is filled
python queue built-in module: deque
Built in module of queue: deque
from collections import deque q = deque() q.append(1) # Team tail into team print(q.popleft()) # Team first team # Output results # 1 # print(q.popleft()) # Team air condition # Output results # IndexError: pop from an empty deque q = deque([1,2,3,4) # Queue length 4 q.append(5) # Team tail into team print(q) print(q.popleft()) # Team first team # Output results # deque([1, 2, 3, 4, 5], maxlen=5) # 1 # For bidirectional queues # q.appendleft() # Team first team # q.pop() # Out of the team at the end of the team
Application of queue: using deque to implement Linux tail command
test: " cc 1314 hi I am chaochao follow chaochao,day day up together "
def tail(n): with open("test",'r') as f: q = deque(f,n) return q # print(tail(1)) # Output results # deque(['chaochao'], maxlen=1) for line in tail(3): print(line,end="") # Output results # hi # I am chaochao # follow chaochao,day day up together
Maze problem
Give a two-dimensional list to represent the maze (0 represents the channel and 1 represents the fence). The algorithm is given to find a path out of the maze.
maze = [
[1,1,1,1,1,1,1,1,1,1],
[1,0,0,1,0,0,0,1,0,1],
[1,0,0,1,0,0,0,1,0,1],
[1,0,0,0,0,1,1,0,0,1],
[1,0,1,1,1,0,0,0,0,1],
[1,0,0,0,1,0,0,0,0,1],
[1,0,1,0,0,0,1,0,0,1],
[1,0,1,1,1,0,1,1,0,1],
[1,1,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1]
]
Stack: depth first search
The idea of backtracking method: (one way to the black) start from a node, arbitrarily find the next point that can go. When the point that can go cannot be found, return to the previous point to find whether there are points in other directions. Use the stack to store the current path.
code implementation
maze = [ [1,1,1,1,1,1,1,1,1,1], [1,0,0,1,0,0,0,1,0,1], [1,0,0,1,0,0,0,1,0,1], [1,0,0,0,0,1,1,0,0,1], [1,0,1,1,1,0,0,0,0,1], [1,0,0,0,1,0,0,0,0,1], [1,0,1,0,0,0,1,0,0,1], [1,0,1,1,1,0,1,1,0,1], [1,1,0,0,0,0,0,0,0,1], [1,1,1,1,1,1,1,1,1,1] ] # Representation of four directions dir_lst = [ lambda x,y:(x+1,y), lambda x,y:(x-1,y), lambda x,y:(x,y-1), lambda x,y:(x,y+1) ] def maze_path(x1,y1,x2,y2): stack = [] stack.append((x1,y1)) # The initial position is a binary while(len(stack)>0): # When the stack is not empty, the loop has a way to go curNode = stack[-1] # Current coordinates, list form # Judge whether we have reached the end if curNode[0] == x2 and curNode[1]== y2: for i in stack: print(i) return True """ Four directions indicate: Left-->(x-1,y),right-->(x+1,y),upper-->(x,y-1),lower-->(x,y+1) """ for dir in dir_lst: nextNode = dir(curNode[0],curNode[1]) # If the next point can go if maze[nextNode[0]][nextNode[1]] == 0: stack.append(nextNode) # Mark the point passed, so a value of 2 indicates that it has passed maze[nextNode[0]][nextNode[1]] = 2 break # break when you find a place to go else: maze[nextNode[0]][nextNode[1]] = 2 stack.pop() # Push the stack out of the stack, backtrack, and then cycle to find the point where you can go else: print("There is no way to go") return False # verification maze_path(1,1,8,8) # Output results # (1, 1) # (2, 1) # (3, 1) # (4, 1) # (5, 1) # (5, 2) # (5, 3) # (6, 3) # (6, 4) # (6, 5) # (7, 5) # (8, 5) # (8, 6) # (8, 7) # (8, 8)
Queue: breadth first search
Idea: start from one node, look for all the points that can continue to go next, and continue to look until you find the exit. Use a queue to store the nodes currently under consideration. The queue stores the current point.
Store the following columns:
current location | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Previous point position | -1 (default) | 0 | 1 | 2 (3 let it come) | 2 (3 let it come) | 3 (4 let it come) | 4 (5 let him come) |
code implementation
from collections import deque maze2 = [ [1,1,1,1,1,1,1,1,1,1], [1,0,0,1,0,0,0,1,0,1], [1,0,0,1,0,0,0,1,0,1], [1,0,0,0,0,1,1,0,0,1], [1,0,1,1,1,0,0,0,0,1], [1,0,0,0,1,0,0,0,0,1], [1,0,1,0,0,0,1,0,0,1], [1,0,1,1,1,0,1,1,0,1], [1,1,0,0,0,0,0,0,0,1], [1,1,1,1,1,1,1,1,1,1] ] dirs = [ lambda x,y:(x+1,y), lambda x,y:(x-1,y), lambda x,y:(x,y-1), lambda x,y:(x,y+1) ] # Output path at end point def print_r(path): curNode = path[-1] # Last node realpath = [] # route while curNode[2] != -1: # That is, when the last node is deployed to the destination realpath.append(curNode[0:2]) curNode = path[curNode[2]] realpath.append(curNode[0:2]) # starting point realpath.reverse() # Flashback list for i in realpath: print(i) def maze_path_queue(x1,y1,x2,y2): queue = deque() queue.append((x1,y1,-1)) path = [] # Put the dequeued nodes in the path list while len(queue) > 0: # Queue out of time cycle curNode = queue.popleft() path.append(curNode) if curNode[0] == x2 and curNode[1] == y2: # Reach the end print_r(path) # Reach the destination and output the path return True for dir in dirs: nextNode = dir(curNode[0],curNode[1]) if maze2[nextNode[0]][nextNode[1]] == 0: queue.append((nextNode[0],nextNode[1],len(path[-1])-1)) # Follow up nodes enter the team and record which node brings her maze2[nextNode[0]][nextNode[1]] = 2 # Mark that this point has passed else: print("There is no way to go") return False maze_path_queue(1,1,6,8)
It's not easy to create. Please give me a compliment and comment! Chao chao, come on with you ❤😜