Soul Searching: Why Data structures?
Data structures, in plain English, are the study of how data is stored. Data storage has only one purpose, that is, to facilitate the later reuse of data. Therefore, the storage of data in computer storage space is not random, which requires us to choose a good way to store data, and this is the core content of data structure. It can be said that data structures are fundamental to all programming. Learning data structures is learning the idea of how to translate real problems into computer language representations. For computer learning friends, learning data structure is a basic skill. For non computer major, but in the future to data analysis, development direction of large data, or on the use of Python can be the friend that has a large span, the data structure is a kind of very important logical thinking ability of exercise, in employment, career development, problem solving, etc, can have subtle big help.
@TOC
Data Structures — Stacks (sequential stacks and linked stacks)
Chapter 1 basic knowledge of stack
Stacks and queues are also, strictly speaking, linear tables, because they are also used to store data in a one-to-one logical relationship. Use stack structure to store data, pay attention to “advanced after out”, that is, the most advanced stack data, last out of the stack; Queues are used to store data, and “first in, first out” is emphasized, that is, the data in the most advanced queue is also the first to exit the queue. Since both stacks and queues belong to linear tables, according to the characteristics of linear tables into sequential and linked lists, stacks can also be divided into sequential stacks and linked stacks, and queues are also divided into sequential and linked queues, which will be explained in detail in this chapter.
1. Stack storage structure
1.1 Basic introduction to stack
Like sequential and linked lists, a stack is a linear storage structure for one-to-one data, as shown in Figure 1.
From Figure 1, we can see that the stack storage structure is different from the linear storage structure we learned before, because the stack has special requirements for the process of “storing” and “fetching” data:
(1) The stack can only access data from one end of the table, and the other end is closed, as shown in Figure 1;
(2) In the stack, no matter storing or fetching data, the principle of “first in, last out” must be followed, that is, the most advanced elements of the stack are last out. Taking the stack in Figure 1, element 1 is the most advanced stack, judging from the storage state of the data in the figure. Therefore, when it is necessary to remove element 1 from the stack, according to the “first in, last out” principle, element 3 and element 2 need to be removed from the stack before element 1 can be successfully removed. Thus, we can define a stack as a linear storage structure that accesses data from only one end of the table and follows the “first in, last out” principle.
In general, the open end of the stack is called the top; Accordingly, the sealing end is called the bottom of the stack. Therefore, the top element is the element closest to the top of the stack. In Figure 2, the top element is element 4. Similarly, the bottom element of the stack refers to the element at the bottom of the stack, and the bottom element in Figure 2 is element 1.
1.2 In and out of the stack
Based on the characteristics of the stack structure, the following two operations are usually performed on the stack in practical applications:
(1) Adding elements to the stack, a process called “pushing” (pushing or pushing);
(2) Extract the specified element from the stack, this process is called “out of the stack” (or pop stack);
1.3 Concrete implementation of stack
The stack is a “special” linear storage structure, so the concrete implementation of the stack has the following two ways:
(1) Sequential stack: the sequential storage structure can simulate the characteristics of stack storage data, so as to realize the stack storage structure;
(2) Chain stack: the chain storage structure is used to realize the stack structure; The difference between the two implementations is limited to the relative location of data elements in the actual physical space. Array is used at the bottom of the sequential stack, and linked list is used at the bottom of the chain stack. Detailed implementation of sequential stacks and linked stacks will be explained in subsequent chapters.
1.4 Application of stack
Based on stack structure, data access adopts the principle of “first in, last out”, which can be used to achieve many functions. For example, we often use browsers to find information on various websites. Suppose you browse to page A, close page A to go to page B, and then close page B to go to page C. If we want to go back to page A, we have two options:
(1) Search again to find page A;
(2) Use the browser’s “rollback” function. The browser will go back to page B and then back to page A. The implementation of browser “back” function, the underlying use is the stack storage structure. When you close page A, the browser pushes page A; Similarly, when you close page B, the browser pushes page B. Therefore, when you do A rollback, you see page B first, then page A, which is the effect of the stack moving out of the stack.
Not only that, but the stack storage structure can also help us detect bracket matching problems in our code. Most programming languages use parentheses (parentheses, brackets and braces), error using brackets (usually throw right parenthesis) will cause the program to compile errors, and lots of development tools are testing code editing error function, which contains parentheses matching problem of testing code, use the function of the underlying implementation is stack structure.
At the same time, the stack structure can also realize the function of numeric conversion. For example, writing a program to automatically convert a decimal number to a binary number can be done using a stack storage structure.
2. Sequential stack and basic operations (including loading and unloading)
2.1 Basic introduction of sequential stack
Sequential stack, that is, sequential table to achieve stack storage structure. From the previous study, we know that using the stack storage structure to manipulate data elements must comply with the principle of “first in, last out”. This section will give a detailed introduction to “how to use the sequence table to simulate the stack and realize the basic operations on the stack data (out and onto the stack)”.
If you look closely at sequential tables (which are arrays at the bottom) and stack structures, you will see that they store data in a very similar way, except that stacks have special restrictions on how data can be accessed while sequential tables do not.
For example, we first use a sequential table (array A) to store {1,2,3,4}, as shown in Figure 1:
Similarly, the stack storage structure is used to store {1,2,3,4}, and its storage state is shown in figure 2:
As you can see from the comparison of Figure 1 and Figure 2, it is easy to simulate the stack structure using a sequential table by storing the data sequentially from the subscript 0 position of array A.
It is common to store data from an array with subscript 0 on an analog stack. It is also possible to store data from other array subscripts.
Now that you know that the sequential table simulates the stack storing data, let’s look at how to simulate the operation of an element on the stack leaving the stack. Since the stack has a “first in, last out” order for storing elements, if you want to remove element 1 stored in Figure 1 from the stack, you need to remove element 4, element 3, and element 2 from the stack in sequence.
This paper gives the common implementation idea of using the sequence table to simulate the stack storage structure, that is, to set a variable pointing to the top element of the stack in real time in the sequence table (generally named top), the initial value of TOP is -1, indicating that no data elements are stored in the stack and the stack is “empty”. Once a data element is pushed, top does +1; Conversely, if the data element goes off the stack, top does -1.
2.2 Sequential stack elements “pushed”
For example, the stack is simulated to store {1,2,3,4}. Initially, the stack is “empty”, that is, the array is empty, and the top value is the initial value -1, as shown in Figure 3:
We first add element 1 to the stack. Our default array subscript is 0 to indicate the bottom of the stack. Therefore, element 1 is stored in array A [1] with top +1, as shown in Figure 4:
Use the above method to store elements 2, 3, and 4 in sequence, and finally, the top value becomes 3, as shown in Figure 5:
2.3 Sequential Stack elements “off the stack”
In fact, the setting of the top variable does not actually help to simulate the “push” operation of the data, it is in preparation for the “push” operation of the data.
For example, to unstack element 2 in Figure 5, elements 4 and 3 need to be unstacked first. Note that when data is pushed out of the stack, top is -1. Therefore, the process of removing elements 4 and 3 from the stack is shown in Figure 6a) and 6b) respectively:
Note that the disappearance of elements in the array in Figure 6 is only for the convenience of beginners. In fact, only -1 operation is needed here for the top value, because the top value itself represents the position of the top of the stack, so top-1 is equivalent to the removal of the top element from the stack. And when an element is added to the stack later, the new element is stored in the location of the old element, such as element 4, overwriting the old element.
For the sequential stack Python programming code, please refer to ↓ (personally written, for reference only, welcome to put forward valuable suggestions)
Task 1: Sequential stack representation and implementation (Difficulty: ★)
Implement basic functions :(including but not limited to, can continue to expand according to their own capabilities)
(1) Initialize the empty stack
(2) Determine whether the stack is empty
(3) Return the top element
(4) Return the stack length
(5) Stack (also known as stack, stack)
(6) Out of stack
(7) Empty the stack
Code implementation:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/7/27 13:52
# @Author : vaxtiandao
# @File : sqStack_21.py
# -*-coding:utf-8-*-
# define the sequential stack
class sqStack:
Initialize the stack
def __init__(self, MAXSIZE) :
self.MAXSIZE = MAXSIZE
self.data = [None] * self.MAXSIZE
self.top = -1
Check whether the current stack is empty
def is_empty(self) :
return self.top == -1
def gettop(self) :
if self.is_empty():
print("Current order stack is empty")
return None
else:
return self.data[self.top]
# into the stack
def Push(self, item) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
self.data[self.top+1] = item
self.top += 1
# list push
def ListPush(self, x) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
for i in range((len(x))):
self.Push(x[i])
# the stack
def Pop(self) :
Check whether the stack is empty
if self.is_empty():
return "sqStack is empty"
rs = self.data[self.top]
self.top -= 1
return rs
Output stack length
def size(self) :
return self.top + 1
# Output stack elements
def display(self) :
Check whether the stack is empty
if self.is_empty():
print("Current order stack is empty", end="")
else:
print(The current list element is:, end="")
for i in range(self.top+1) :print(self.data[i], end="")
print(a)# to empty stack
def clear(self) :
self.data = [None] * self.MAXSIZE
self.top = -1
if __name__ == '__main__':
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
Initialize a sequence stack of length 20
s = sqStack(20)
print("Initialize stack:", s)
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
Check whether the current stack is empty
print("Is the current stack empty:", s.is_empty())
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
# Output stack elements
s.display()
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
print("Stack elements before pushing:", end="")
s.display()
# into the stack
s.Push(1)
s.Push(10)
s.Push(100)
Print the current stack element
print("Stack element after pushing:", end="")
s.display()
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
print("The current stack length is:", s.size())
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
print("Queue in front of stack element:", end="")
s.display()
s.ListPush([1.2.3.4])
print("Queue after stack element:", end="")
s.display()
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
print("Current top stack element is:", s.gettop())
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
# The top element goes off the stack
print("Elements in the stack before pushing:", end="")
s.display()
print("The unstack element is:", s.Pop())
print("After the stack element:", end="")
s.display()
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
Print the current stack element
s.display()
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
s.clear()
s.display()
print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --')
Copy the code
Effect:
3. Detailed explanation of chain stack and basic operations (including loading and unloading)
3.1 Basic introduction of chain stack
Linked stack, that is, linked list to achieve stack storage structure.
The chain stack implementation idea is similar to the sequential stack, the sequential stack is the numberThe order sheetOne end is the bottom of the stack, the other end is the top of the stack; The same is true for linked stacks. Usually, we use the head of the list as the top of the stack and the tail as the bottom, as shown in Figure 1:Using the head of the list as the top end of the stack avoids the time-consuming task of traversing the list while implementing data “on” and “off” operations.
The head of the list as the top of the stack means:
(1) Data needs to be inserted from the head of the linked list when data is “pushed”;
(2) In the realization of data “out of the stack” operation, need to delete the first node in the head of the linked list; Thus, a stack is essentially a linked list in which data can be inserted or deleted only by header insertion.
3.2 Stack elements are pushed
For example, pushing elements 1, 2, 3, and 4 in sequence is equivalent to adding each element to the linked list in sequence by using the header method. The process of adding each data element is shown in Figure 2:
3.3 Unstack elements
For example, in the linked stack shown in Figure 2e, to remove element 3 from the stack, according to the principle of “in first, out later”, element 4 must be removed from the list before element 3 can be removed from the stack. The whole operation process is shown in Figure 3:
For the code of chained Stack Python programming, please refer to ↓ (personally written for reference only, welcome to put forward valuable suggestions).
Task 2: Presentation and implementation of chain stack (Difficulty: ★★)
Implement basic functions :(same as sequential stack)
(1) Initialize the empty stack
(2) Determine whether the stack is empty
(3) Return the top element
(4) Return the stack length
(5) Stack (also known as stack, stack)
(6) Out of stack
(7) Empty the stack
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/7/27 14:47
# @Author : vaxtiandao
# @File : liStack.py
# define the stack node
class Node(object) :
Initialize the stack
def __init__(self, data) :
self.data = data
self.next = None
# define the stack
class linkstack(object) :
Initialize the stack
def __init__(self) :
self.top = None
Check whether the stack is empty
def is_empty(self) :
return self.top == None
Clear the stack
def clear(self) :
self.top = None
Return the length of the current stack
def size(self) :
i = 0
tempnode = self.top
while tempnode is not None:
tempnode = tempnode.next
i += 1
return i
The element is pushed
def push(self, item) :
node = Node(item)
node.next = self.top
self.top = node
The element at the top of the stack exits the stack
def pop(self) :
x = self.top.data
self.top = self.top.next
return x
Get the top element of the stack
def gettop(self) :
return self.top.data
# output the current stack element
def display(self) :
if self.top == None:
print("Current stack element is empty", end="")
else:
print("Current stack element is:", end="")
tempnode = self.top
while tempnode is not None:
print(tempnode.data, end="")
tempnode = tempnode.next
print(a)if __name__ == "__main__":
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
s1 = linkstack()
print("The initialized stack is:", s1)
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
print("The stack element before pushing is:", end="")
s1.display()
s1.push(1)
s1.push(2)
s1.push(3)
s1.push(4)
s1.push(5)
s1.push(6)
print("The stack element after being pushed is:", end="")
s1.display()
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
print("Current top stack element is:", s1.gettop())
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
print("The current stack length is:", s1.size())
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
print("The stack element before the stack is:", end="")
s1.display()
print("The unstack element is:", s1.pop())
print("The stack element after the stack is:", end="")
s1.display()
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
print("The clearest stack element is:", end="")
s1.display()
s1.clear()
print("The empty stack element is:", end="")
s1.display()
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
print("Is the current stack empty:", s1.is_empty())
print("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --")
Copy the code
Effect:
4. Stack application (difficulty: ★★)
Application 1: bracket matching problem
The checking algorithm relies on a stack. Whenever an open parenthesis is read, it is pushed directly into the stack and waits for the matching close parenthesis of the same kind. Each time a close parenthesis of the same type as the open parenthesis at the top of the stack is read, the two are matched and the open parenthesis at the top of the stack is pushed off the stack until the expression is scanned.
As part of the process, consider the case of mismatching parentheses. For example, in the case of (()[]), the stack is empty because the previous open parentheses are known to match the following close parentheses, so the last scanned close parentheses cannot be matched. The error [([]) occurs when an expression scan is completed and one of the left brackets in the stack does not match; the error (()] occurs when the left bracket at the top of the stack does not match the last close bracket.
Test cases :(you need to use the following three cases to test your code!) Case 1: {{([] [])} ()} case 2: [[{{() ()}}]] case 3: [[() () () ()]] {}
Running results:
About this problem programming code can refer to ↓ (personal writing, for reference only, welcome to put forward valuable suggestions)
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/7/28 10:14
# @Author : vaxtiandao
# @File : ds_parentMatching.py
# define the sequential stack
class sqStack:
Initialize the stack
def __init__(self, MAXSIZE) :
self.MAXSIZE = MAXSIZE
self.data = [None] * self.MAXSIZE
self.top = -1
Check whether the current stack is empty
def is_empty(self) :
return self.top == -1
def gettop(self) :
if self.is_empty():
print("Current order stack is empty")
return None
else:
return self.data[self.top]
# into the stack
def Push(self, item) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
self.data[self.top + 1] = item
self.top += 1
# list push
def ListPush(self, x) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
for i in range((len(x))):
self.Push(x[i])
# the stack
def Pop(self) :
Check whether the stack is empty
if self.is_empty():
return "sqStack is empty"
rs = self.data[self.top]
self.top -= 1
return rs
Output stack length
def size(self) :
return self.top + 1
# Output stack elements
def display(self) :
Check whether the stack is empty
if self.is_empty():
print("Current order stack is empty", end="")
else:
print(The current list element is:, end="")
for i in range(self.top + 1) :print(self.data[i], end="")
print(a)# to empty stack
def clear(self) :
self.data = [None] * self.MAXSIZE
self.top = -1
def matching(strings) : The # input is a string of characters
bktStack = sqStack(60) Create class instance
flag = 1
opens = "{[("
closes = "})"
# for each input character
for i in strings:
When an open parenthesis is encountered, push it
if i in opens:
bktStack.Push(i)
# Close parenthesis encountered
elif i in closes:
# if no open parentheses match it
if bktStack.is_empty():
# no match, end
return False
In what order should the left parentheses be entered? The right parentheses should be removed in reverse order.
# If matched, the close bracket will always cancel the top bracket.
# pop bktstack.pop (), check whether the open bracket at the top of the stack matches the current close bracket
ifcloses.index(i) ! = opens.index(bktStack.Pop()):# no match, end
return False
# if there is no return but a loop, and no extra open parentheses remain on the stack, then a match is made. Otherwise, it does not match.
return bktStack.is_empty()
Check whether the value returned is True or False
def check(strings) :
if matching(strings):
print("%s matches correctly!" % strings)
else:
print("Wrong %s match!" % strings)
if __name__ == "__main__":
# test function
for i in range(4):
stringa = input()
check(stringa)
Copy the code
Effect:
Application 2: Decimal to binary
When converting a decimal integer M into a binary number, in the calculation process, the bits of the binary number obtained by M and 2 are pushed onto the stack in turn. After the calculation, the binary number in the stack is output in turn. The output result is the binary number to be obtained.
Test Cases: [200, 254, 153, 29, 108, 631, 892]
Running results:
About this problem programming code can refer to ↓ (personal writing, for reference only, welcome to put forward valuable suggestions)
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/7/28 10:31
# @Author : vaxtiandao
# @File : ds_10to2.py
# define the sequential stack
class sqStack:
Initialize the stack
def __init__(self, MAXSIZE) :
self.MAXSIZE = MAXSIZE
self.data = [None] * self.MAXSIZE
self.top = -1
Check whether the current stack is empty
def is_empty(self) :
return self.top == -1
def gettop(self) :
if self.is_empty():
print("Current order stack is empty")
return None
else:
return self.data[self.top]
# into the stack
def Push(self, item) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
self.data[self.top + 1] = item
self.top += 1
# list push
def ListPush(self, x) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
for i in range((len(x))):
self.Push(x[i])
# the stack
def Pop(self) :
Check whether the stack is empty
if self.is_empty():
return "sqStack is empty"
rs = self.data[self.top]
self.top -= 1
return rs
Output stack length
def size(self) :
return self.top + 1
# Output stack elements
def display(self) :
Check whether the stack is empty
if self.is_empty():
print("Current order stack is empty", end="")
else:
print(The current list element is:, end="")
for i in range(self.top + 1) :print(self.data[i], end="")
print(a)# to empty stack
def clear(self) :
self.data = [None] * self.MAXSIZE
self.top = -1
if __name__ == "__main__":
s = sqStack(20)
data = int(input("Please enter the number to be converted to binary:"))
whiledata ! =0:
ys = data % 2
s.Push(ys)
data = data // 2
whiles.top ! = -1:
print(s.Pop(), end=' ')
Copy the code
Effect:
Application of 3
Decimal to N-base (application 2 extension) When converting a decimal integer M to n-base number, in the calculation process, the bits of the n-base number obtained by M and N are stacked in turn. After the calculation, the n-base number in the stack is output in turn. The output result is the n-base number to be obtained.
Test Cases: Tests: [200, 254, 153, 29, 108, 631, 892]
Here, I mainly use random. Choice () to randomly select the base of the test number to be converted. The test code is shown below for reference only.
Running results:
About this problem programming code can refer to ↓ (personal writing, for reference only, welcome to put forward valuable suggestions)
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/7/28 10:32
# @Author : vaxtiandao
# @File : ds_10toN.py
# define the sequential stack
class sqStack:
Initialize the stack
def __init__(self, MAXSIZE) :
self.MAXSIZE = MAXSIZE
self.data = [None] * self.MAXSIZE
self.top = -1
Check whether the current stack is empty
def is_empty(self) :
return self.top == -1
def gettop(self) :
if self.is_empty():
print("Current order stack is empty")
return None
else:
return self.data[self.top]
# into the stack
def Push(self, item) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
self.data[self.top + 1] = item
self.top += 1
# list push
def ListPush(self, x) :
Check whether the stack is full
if self.top == self.MAXSIZE - 1:
return "sqStack is full."
for i in range((len(x))):
self.Push(x[i])
# the stack
def Pop(self) :
Check whether the stack is empty
if self.is_empty():
return "sqStack is empty"
rs = self.data[self.top]
self.top -= 1
return rs
Output stack length
def size(self) :
return self.top + 1
# Output stack elements
def display(self) :
Check whether the stack is empty
if self.is_empty():
print("Current order stack is empty", end="")
else:
print(The current list element is:, end="")
for i in range(self.top + 1) :print(self.data[i], end="")
print(a)# to empty stack
def clear(self) :
self.data = [None] * self.MAXSIZE
self.top = -1
def divideByN(number, base) :
digits = "0123456789ABCDEF"
remstack = sqStack(100)
while number > 0:
rem = number % base
remstack.Push(rem)
number = number // base
newString = ""
while not remstack.is_empty():
newString = newString + digits[remstack.Pop()]
return newString
import random
numbers = [200.254.153.29.108.631.892]
bases = [4.8.6]
for number in numbers:
base = random.choice(bases)
print("%d 的 %d 进制数为:%s" % (number, base, divideByN(number, base)))
Copy the code
Effect:
Python data structures series: Linear tables
What do you understand about operation and maintenance
Selenium Test tool: How to automate your browser
Flask Concepts and Basics