Brain map: https://www.processon.com/mindmap/6179408f0e3e7416bdeb81d1
development environment
Mac C locale configuration
Software: Visual Studio Code
Coder Runner plugin
1, Overview of data structures
1. Definition
How do we save a large number of complex problems in reality to the main memory (memory) with specific data types and specific storage structures, and the corresponding operations to realize a function (such as finding an element, deleting an element, and arranging all elements) on this basis, which is also called algorithm
Narrow sense:
Data structure is specialized in data storage
Data storage includes two aspects: individual storage + individual relationship storage
Generalized:
Data structure includes both data storage and data operation
The operation of storing data is an algorithm
Data structure = individual + individual relationship
Algorithm = operation on stored data
2. Algorithm
What is an algorithm?
Generalized: algorithms are operations on stored objects
Narrow sense: it refers to the methods and steps to solve the problem
Methods and steps of problem solving
How to measure the standard of the algorithm?
1. Time complexity: the approximate number of times the program needs to be executed, not the execution time
2. Space complexity: the maximum memory occupied during the execution of the algorithm
3. Degree of difficulty
4. Robustness
3. The status of data structures?
Data structure is the core course in software
Program = data storage + data operation + language that can be executed by computer
4. How many structures does data storage have?
1. Linear structure

Continuous storage [array]

Advantages: fast storage speed

Disadvantages: slow insertion and deletion of elements
Limited space
You must know the length of the array in advance
Large contiguous storage blocks are required


Discrete storage [linked list]
 Advantages: unlimited space
 Disadvantages: slow storage speed

Application of linear structure  [ stack ]

Application of linear structure  [ queue ]
2. Nonlinear structure
 tree
 chart
2, Preparatory knowledge
1. Pointer
(1) The importance of pointer: the soul of C language
(2) . definition:
 Address:
 Memory storage number (house number)
 Nonnegative integer starting from 0
 Range: 0  > fffffff [04G1]
 Pointer:
 The pointer is the address, and the address is the pointer
 A pointer variable is a variable that stores the address of a memory unit
 The essence of a pointer is a nonnegative integer with limited operation
2. Structure
(1) Why do structures appear?
In order to express some complex data, ordinary basic type variables can not meet the requirements, and the structure is born!
(2) What is a structure
Structure is a composite data type that can be defined by users according to our actual needs
(3) Precautions:
3. Dynamic memory allocation and release
3, Linear structure
What is linear structure?
All nodes can be connected by one line, otherwise it is a nonlinear structure (tree, graph)
1. Sequence table
(1) What is an array?
The elements are of the same type and of the same size
(2) Advantages and disadvantages of arrays?
Self created array
#include<stdio.h> #include<mm_malloc.h> #Include < stdlib. H > / / includes exit(); /* Analog array */ // A data type is defined. The name of the data type is struct Arr and contains three members: pBase, len and cnt struct Arr{ int *pBase; // Stores the address of the first element of the array int len; // The maximum number of elements that the array can hold int cnt; // The number of valid elements in the current array }; /* All statements */ void initArr(struct Arr *pArr, int length); bool isEmpty(struct Arr *pArr); void showArr(struct Arr *pArr); bool appendArr(struct Arr *pArr ,int val); bool insertArr(struct Arr *pArr ,int pos,int val); bool isFull(struct Arr *pArr); bool deleteArr(struct Arr *pArr ,int pos,int *pVal); void inversionArr(struct Arr *pArr); void softArr(struct Arr *pArr); /* Main function */ int main(){ // int val;// Used to receive the value of the deleted element struct Arr arr; // Define a variable arr, which has no content at present initArr(&arr,6); // printf("%d\n",arr.len); // showArr(&arr); // printf("\n\n"); // appendArr(&arr,1); // appendArr(&arr,2); // appendArr(&arr,3); // appendArr(&arr,4); // appendArr(&arr,5); // appendArr(&arr,6); // appendArr(&arr,7); // showArr(&arr); // printf("\n\n"); // insertArr(&arr,6,99); // showArr(&arr); // Test deletear() // appendArr(&arr,1); // appendArr(&arr,2); // appendArr(&arr,3); // appendArr(&arr,4444); // appendArr(&arr,5); // appendArr(&arr,6); // showArr(&arr); // printf("\n\n"); // deleteArr(&arr,4,&val); // Val is the value used to accept the deleted data // printf("deleted element value is:% d\n",val); // showArr(&arr); // Implement inversion // appendArr(&arr,1); // appendArr(&arr,2); // appendArr(&arr,3); // appendArr(&arr,4); // appendArr(&arr,5); // appendArr(&arr,6); // inversionArr(&arr); // showArr(&arr); // printf("\n\n"); // Implement ascending sort printf("\n\n"); appendArr(&arr,2); appendArr(&arr,7); appendArr(&arr,5); appendArr(&arr,4); appendArr(&arr,8); appendArr(&arr,3); softArr(&arr); showArr(&arr); return 0; } /* initialization */ void initArr(struct Arr *pArr, int length){ pArr>pBase = (int *)malloc(sizeof(int) * length); //pArr is the pBase in the structure variable to which the pointer variable points if(NULL == pArr>pBase){ printf("Dynamic memory allocation failed!\n"); exit(1); // Terminate a program }else{ pArr>len = length; // The maximum number of elements that the array can hold pArr>cnt = 0; } return; } /* display output */ void showArr(struct Arr *pArr){ if(isEmpty(pArr)){ printf("Array is empty\n"); }else{ for (int i = 0; i < pArr>cnt; i++) { printf("%d ",pArr>pBase[i]); printf("\n"); } } } /* Determine whether the array is empty */ bool isEmpty(struct Arr *pArr){ if (0 == pArr>cnt){ return true; }else{ return false; } } /* Add */ bool appendArr(struct Arr *pArr ,int val){ // Cannot add when full if(isFull(pArr)){ return false; } // When dissatisfied, you can add: 1. Process 2. Function 3. Trial and error pArr>pBase[pArr>cnt] = val; pArr>cnt++; return true; } /* Judge whether it is full */ bool isFull(struct Arr *pArr){ if(pArr>len == pArr>cnt){ printf("already expired\n"); return true; }else{ return false; } } bool insertArr(struct Arr *pArr ,int pos,int val){ // 1. Judge whether it is full. If it is full, it cannot be inserted if(isFull(pArr)){ return false; } // 2. Then judge whether it crosses the boundary if(pos <1  pos>pArr>cnt+1){ return false; } for(int i = pArr>cnt1; i>=pos1; i){ pArr>pBase[i+1] = pArr>pBase[i]; // Give the last one to the next one } pArr>pBase[pos1] = val; // insert pArr>cnt++; // Effective number plus 1 return true; } bool deleteArr(struct Arr *pArr ,int pos,int *pVal){ if(isEmpty(pArr)){ printf("Array is empty\n"); return false; } if(pos<1 && pos>pArr>cnt){ printf("Range exception"); return false; } // Find this value first *pVal = pArr>pBase[pos1]; // Start deletion for(int i = pos; i<pArr>cnt; i++){ pArr>pBase[i1] = pArr>pBase[i]; } pArr>cnt;// Effective number minus 1 return true; } void inversionArr(struct Arr *pArr){ int i=0; //first int j=pArr>cnt1; // the last one int temp; while (i<j) // Value exchange { temp = pArr>pBase[i]; pArr>pBase[i] = pArr>pBase[j]; pArr>pBase[j] = temp; i++; j; } return; } void softArr(struct Arr *pArr){ // Select sort int temp; for(int i =0; i<pArr>cnt; i++){ for(int j=i+1; j<pArr>cnt;j++){ if(pArr>pBase[i]>pArr>pBase[j]){ temp = pArr>pBase[i]; pArr>pBase[i] = pArr>pBase[j]; pArr>pBase[j] = temp; } } } }
2. Linked list
Preliminary knowledge typedef keyword
Objective: knock on the linked list by hand
1,
#include<stdio.h> typedef int QQ; //Give int a new name int = QQ typedef struct Student{ int sid; char name[100]; char sex; }St; // St is equivalent to struct Student int main(){ int i = 10; QQ j = 10; // QQ is equivalent to int printf("%d %d",i,j); struct Student st; struct Student *ss; St st; // St st is equivalent to struct Student st; St *ss; // St *ss is equivalent to struct Student *ss; return 0; }
2,
#include<stdio.h> typedef struct Student{ int sid; char name[100]; char sex; }*St; // *St is equivalent to struct Student* int main(){ return 0; }
3,
(1) Definition
1. N nodes discrete
2. Each other through the pointer necklace
3. Each node can only have one precursor node, and there can only be one follower node behind each node. The receiving node has no predecessor node, and the tail node has no follower node
Technical Term:
**First node: * * first valid node
**Tail node: * * last valid node
Head node: the node before the first valid node
The header node does not store valid data
The purpose of header node is to facilitate the operation of linked list
The data type of the header node is the same as that of the header node
**Header pointer: * * pointer variable pointing to the header node
**Tail pointer: * * pointer variable pointing to the tail node
How many parameters do we need to determine a linked list????
Only one parameter is needed: the header pointer, because we can calculate all the other information of the linked list through the header pointer
(2) Classification
1. Single linked list
2. Double linked list: each node has two pointers
3. Circular linked list: all other nodes can be found through any node
4. Acyclic linked list:
(3) Algorithm
The algorithm has two standards, one is broad and the other is narrow. In a narrow sense, the algorithm is related to the storage of data. In a broad sense, then
It's irrelevant.
Generic:
The effect of using a certain technology is that different storage methods perform the same operations
Note: there are differences between narrow sense and broad sense
 Narrow sense: from the internal real realization
 Generalized:
How to learn algorithms?
Related to mathematics, take out the answer and understand the answer!
How to change a program (answer) from not understanding to understanding?
 technological process
 Function of each statement
 Trial and error
1. Traversal
2. Search
3. Empty
4. Destroy
5. Find length
6. Sort
7. Delete node
...
Self created linked list
#include<stdio.h> #include<mm_malloc.h> typedef struct Node{ int data; //Data domain struct Node *pNext; }NODE,*PNODE; //Declarative function PNODE create_list(); void traverse_list(PNODE pHead); bool is_empty(PNODE pHead); int getLenght(PNODE pHead); bool insert_list(PNODE pHead,int pos,int val); bool deleteList(PNODE pHead,int pos,int *val); // The third parameter is used to store the value of the deleted linked list void softList(PNODE pHead); //sort bool insertList(PNODE pHead,int pos,int val); //Linked list insertion, pos starts from 1 bool deleteList(PNODE pHead,int pos,int *pVal); int main(){ PNODE pHead = NULL; // Equivalent to struct Node *pHead = NULL; pHead = create_list(); //create_list() function: create an acyclic single linked list and assign the address of the head node of the linked list to pHead traverse_list(pHead);//traverse_list traversal output if (is_empty(pHead)) { printf("The linked list is empty!\n"); }else{ printf("Linked list is not empty!\n"); } int len = getLenght(pHead); printf("The length of the linked list is:%d\n",len); printf("\n\n"); //Test sequencing // softList(pHead); // traverse_list(pHead); printf("\n\n"); //Test insertion // insertList(pHead,4,520); // traverse_list(pHead); printf("\n\n"); //Test delete int val; if (deleteList(pHead,4,&val)) { printf("Deletion succeeded. The value of this element is:%d\n",val); }else{ printf("Deletion failed. The deleted element does not exist\n"); } traverse_list(pHead); return 0; } PNODE create_list(){ // A header node that does not store valid data is allocated PNODE pHead = (PNODE)malloc(sizeof(NODE));// if(NULL == pHead){ printf("Allocation failed, program terminated!"); exit(1); } PNODE pTail = pHead; pTail>pNext = NULL; int len; int i; // Used to store the number of valid user input nodes int val; // It is used to temporarily store the value of the node entered by the user printf("Please enter the number of nodes you need to generate the linked list:len="); scanf("%d",&len); for(i=0; i<len; i++){ printf("Please enter page%d Values for nodes:",i+1); scanf("%d",&val); PNODE pNew = (PNODE)malloc(sizeof(NODE)); if(NULL == pHead){ printf("Allocation failed, program terminated!"); exit(1); } pNew>data=val; // How to hang the generated node to the pahead header pointer? The method is as follows pTail>pNext = pNew; pNew>pNext = NULL; pTail = pNew;// pTail points to the address of the structure object where pNew will be located } return pHead; } void traverse_list(PNODE pHead){ // Traversal output PNODE p = pHead>pNext; while (p!= NULL) { printf("%d ",p>data); p = p>pNext; } printf("\n"); return; } bool is_empty(PNODE pHead){ if (pHead>pNext==NULL) { return true; }else{ return false; } } int getLenght(PNODE pHead){ int len = 0; // Traversal output PNODE p = pHead>pNext; while (p!= NULL) { len++; p = p>pNext; } return len; } // bool insert_list(PNODE pHead,int pos,int val); //Bubble sorting /* */ void softList(PNODE pHead){ int i,j; int temp; int len =getLenght(pHead); PNODE p,q; for (i=0,p=pHead>pNext; i<len1; i++,p=p>pNext) // Outer loop, 6 numbers, only need to compare 5 times { for(j=i+1,q=p>pNext; j<len; j++,q=q>pNext){ if(p>data>q>data){ //Class uses a [i] > a [J] in the array temp = p>data; p>data =q>data; q>data = temp; } } } return; } // Insert a new node before the pos node of the linked list pointed to by pHead. The value of this node is val, and the value of pos starts from 1 bool insertList(PNODE pHead,int pos,int val){ //Is the scope of pos legal int i = 0; PNODE p = pHead; while (p!=NULL && i <pos1) //The purpose of this loop is to make p point to the previous node of pos { p = p>pNext; // Eventually p will point to i++; } if (p==NULL  i >pos1) { return false; } PNODE pNew = (PNODE)malloc(sizeof(NODE)); if(NULL == pNew){ printf("Allocation failed, program terminated!"); exit(1); } pNew>data=val; //Value storage //Start insertion PNODE q = p>pNext; //q is an intermediate variable p>pNext = pNew; pNew>pNext=q; return true; /* The core code of these three behaviors  detailed analysis can be seen in the flow chart below PNODE q = p>pNext; //q Is an intermediate variable p>pNext = pNew; pNew>pNext=q; */ } bool deleteList(PNODE pHead,int pos,int *pVal){ //Is the scope of pos legal int i = 0; PNODE p = pHead; while (p>pNext!=NULL && i <pos1) //The purpose of this loop is to make p point to the previous node of pos { p = p>pNext; // Eventually p will point to i++; } if (NULL==p>pNext  i >pos1) { return false; } //Accept the value stored by the deleted node *pVal = p>pNext>data; //Start deletion PNODE q = p>pNext; // Save the element to be deleted first to free up space later p>pNext = p>pNext>pNext; // The socalled deletion is to point p to the next element to be deleted, and then release the space of p free(p); }
Insert 3 lines of code analysis:
(4) Circular linked list
Definition: a linked list with head and tail (that is, the pointer field of the last node in the list points to the head node, and the whole linked list forms a ring)
==Advantages: = = starting from any node in the table, you can find other nodes in the table.
How to merge two circular linked lists with tail pointers?
What are the operations?
(1) . keep the head node of Ta first: P = Ta  > next
(2) . connect the footer of Ta table to the first valid node of Tb table: Ta  > next = Tb  > next  > next;
(3) . release the header node of TB table: free (TB  > next); delete Tb>next;
(4) The tail node of Tb table points to the head node of Ta table: Tb  > next = P
(5) Bidirectional linked list
1. Definition: add a pointer field prior to its direct precursor in each node of the single linked list. In this way, a chain with two different directions is formed in the linked list, so it is called a twoway linked list.
2. Structure:
Insertion of bidirectional linked list
(6) Bidirectional circular linked list
(7) Comparison between sequential list and linked list
1, Advantages and disadvantages of linked list:
advantage:
1. Node space can be dynamically applied for and released
2. Delete and insert operations only need to modify the pointer without moving the element
Disadvantages:
3. The storage density is low because each node needs to store the addresses of its subsequent nodes and precursor nodes while storing the data itself, which takes up a large space
4. Non random access structure, the time complexity is improved
What is random access?
That is, any element can be obtained through the following table
(8) Application of linear table
1. Merging of linear tables
Implementation method:
2. Merge of ordered linear tables
Why non decreasing ordering?
Because there may be duplicate elements
Sequential tables are used to merge sequential tables:
Linked list to achieve ordered table merging
[the external chain image transfer fails. The source station may have an antitheft chain mechanism. It is recommended to save the image and upload it directly (imgntndse7k1636095678603) (/ users / ouyangyansong / library / Application Support / typora user images / image20211031151933666. PNG)]
Note: in the worst case, La is as long as Lb, and all must be executed. The maximum time complexity is 👆🏻
(9) Case 1: operation of univariate polynomial
(10) Case 2: operation of sparse polynomials
1. Sequential storage implementation
Problems with using sequential tables for storage:**==
1. It is not easy to determine how much space is allocated for storage, and the storage space allocation is not flexible
2. It is necessary to create a new array with high space complexity
How to solve the above problems?
Answer: use linked list for storage
2. Chain storage implementation
Create polynomial code
Polynomial addition algorithm
(11) Case 3: implementation of library management system
3. Stack
(1) Definition
A storage structure that can implement "first in first out" or "last in first out"
A: there can be no cab, because if c is on the stack, a and b must also be on the stack
Only possible: cba
(2) Code implementation related algorithms
1. Implementation of sequential stack
Code implementation of sequential stack
Initialization of sequential stack
Judge whether the sequence stack is empty
Find the length of sequential stack
Empty sequence stack
Note: the premise if(S.base) is to judge whether the stack is empty in advance. If it is already empty, it is not necessary to continue the following operations
Destruction of sequential stack
Sequential stacking / pressing
Sequential stack
2. Implementation of chain stack
Initialization stack
Judge whether the chain stack is empty
Insertion of chain stack
1,initStack(); Initialize stack: make pTop and pBottom point to a useless header node, which creates an empty stack
void initStack(PSTACK pS){ pS>pTop = (PNODE)malloc(sizeof(NODE)); //Create a null node (PNODE)malloc(sizeof(NODE)) if (NULL == pS>pTop) { printf("Dynamic memory allocation failed"); exit(1); }else{ pS>pBottom = pS>pTop; // Make both pTop and pBottom point to it pS>pTop>pNext = NULL; // pS>pBottom>pNext = NULL; And set its value to null } }
2. Out of stack
// Take the stack pointed to by pS out of the stack once, and store the out of stack element in the variable pointed to by the formal parameter pVal. If the out of the stack fails, return false, otherwise return true; bool popStack(PSTACK pS,int *pVal){ if (empt(pS)) { return false; }else{ // Stack out = = = (delete and save the value of the deleted node to the variable pointed to by the formal parameter pVal) PNODE r = pS>pTop; *pVal = r>data; pS>pTop = r>pNext; free(r); r = NULL; return true; } }
3. Stack pressing
pushStack() implementation
void pushStack(PSTACK pS,int val){ PNODE pNew = (PNODE)malloc(sizeof(NODE)); pNew>data = val; pNew>pNext = pS>pTop; //PS  > top cannot be changed to PS  > bottom pS>pTop = pNew; return; }
4. traverse traversal
void traverse(PSTACK pS){ PNODE p = pS>pTop; while (p!=pS>pBottom) { printf("%d ",p>data); p = p>pNext; } printf("\n"); return; }
5. Clear
//Empty stack void clear(PSTACK pS){ if (empt(pS)) { return ; }else{ PNODE p = pS>pTop; PNODE q = NULL; while (p != pS>pBottom) { q = p>pNext; free(p); p = q; } pS>pTop = pS>pBottom; // Results after emptying } }
Complete code and implementation of custom stack
#include<stdio.h> #include<mm_malloc.h> /** Stack implementation */ typedef struct Node{ int data; struct Node *pNext; }NODE,*PNODE; typedef struct Stack{ PNODE pTop; //Top PNODE pBottom; // Top }STACK,*PSTACK; void initStack(PSTACK); // Initialization stack void pushStack(PSTACK,int); // Stack pressing void traverse(PSTACK); // Traversal output bool popStack(PSTACK,int *);// Out of stack bool empt(PSTACK); // Is it empty void clear(PSTACK); //empty int main(){ STACK S; // Equivalent to struct Stack S; initStack(&S); // Initialization stack: creates an empty stack pushStack(&S,1); // Stack pressing pushStack(&S,2); pushStack(&S,3); // Stack pressing pushStack(&S,4); pushStack(&S,5); // Stack pressing pushStack(&S,6); traverse(&S); // Traversal output /* printf("\n\n"); int val; if (popStack(&S,&val)) { printf("Successfully stack. The stack elements are:% d\n",val); }else { printf("Stack out failed! \ n ""); } */ //Test empty function clear(&S); traverse(&S); // Traversal output return 0; } void initStack(PSTACK pS){ pS>pTop = (PNODE)malloc(sizeof(NODE)); if (NULL == pS>pTop) { printf("Dynamic memory allocation failed"); exit(1); }else{ pS>pBottom = pS>pTop; pS>pTop>pNext = NULL; // pS>pBottom>pNext = NULL; } } void pushStack(PSTACK pS,int val){ PNODE pNew = (PNODE)malloc(sizeof(NODE)); pNew>data = val; pNew>pNext = pS>pTop; //PS  > top cannot be changed to PS  > bottom pS>pTop = pNew; return; } void traverse(PSTACK pS){ PNODE p = pS>pTop; while (p!=pS>pBottom) { printf("%d ",p>data); p = p>pNext; } printf("\n"); return; } bool empt(PSTACK pS){ if (pS>pBottom == pS>pTop) { return true; }else{ return false; } } // Take the stack pointed to by pS out of the stack once, and store the out of stack element in the variable pointed to by the formal parameter pVal. If the out of the stack fails, return false, otherwise return true; bool popStack(PSTACK pS,int *pVal){ if (empt(pS)) { return false; }else{ // Stack out = = = (delete and save the value of the deleted node to the variable pointed to by the formal parameter pVal) PNODE r = pS>pTop; *pVal = r>data; pS>pTop = r>pNext; free(r); r = NULL; return true; } } //Empty stack void clear(PSTACK pS){ if (empt(pS)) { return ; }else{ PNODE p = pS>pTop; PNODE q = NULL; while (p != pS>pBottom) { q = p>pNext; free(p); p = q; } pS>pTop = pS>pBottom; // Results after emptying } }
(3) Application binary conversion
thinking
(4) Application  Verification of expression bracket matching
Stack rule: the parentheses that are put on the stack first and then matched, and the parentheses that are put on the stack later are matched first
(5) Application  expression evaluation
4. Queue
(1) Definition:
It is a storage structure that can realize "first in, first out"! Similar to: queue up to buy tickets
(2) Related terms
(3) Implementation of sequential queue
During initialization:
There are elements in the team:
Some elements are out of the team:
Introduce circular queue
Solve the problem of false overflow during insertion
Solve the problem of false overflow during deletion
Similar to the effect of implementing circular queues
How to judge whether the team is empty or full
Method 1: set another flag to judge whether the team is empty or full
Method 2: set another count to count the number
Method 3: use less one element space
The third method is as follows:
Code implementation:
0. Structure
1. Initialization operation
2. Find the length of the queue
3. Queue entry algorithm for circular queue
4. Out of queue algorithm for cyclic queue
a,First judge whether it is empty. If it is empty, you cannot exit the queue b,Keep deleted elements c,Header pointer+1
5. Take out the header element
a,Premise: the queue cannot be empty b,Direct extraction front Value of location
(4) Implementation of chain queue
1. Initialization of chained queues
2. Destruction of chained queues
Method 1: define another pointer variable p for receiving
Mode 2: directly receive with Q.rear to save space
3. Queue up of chain queue
4. Outgoing of chain queue
5. Gets the queue element of the chain queue
Static queues must be circular queues
analysis:
1. Why must a static queue be a circular queue?
Because static queues are implemented based on arrays, if circular queues are not used, the space used by deleted elements will not continue to be used, resulting in a waste of space
2. The circular queue requires several parameters to determine
A: two parameters are needed to determine. These two parameters have different meanings on different occasions (remember them first, and then experience them slowly)
front
rear
3. Meaning of parameters of circular queue
These two parameters have different meanings on different occasions (remember them first, and then experience them slowly)
a. initialization: the values of front and rear are both zero
b. the queue is not empty: front represents the first element of the queue, and rear represents the next element of the last valid element of the queue
c. empty queue: the values of front and rear are equal but not necessarily zero
4. Explanation of pseudo algorithm of circular queue inclusion
Two steps:
(1) Store the value in the position represented by r
(2) . wrong writing: rear=rear+1
Correct writing: rear=(rear + 1)% length of array
5. Explanation of pseudo algorithm for out of queue of circular queue
(1) . save the outgoing value first
(2) , front = (front+1)% array length
6. How to determine whether the circular queue is empty
If (front == rear), the queue must be empty
7. How to determine whether the circular queue is full
There are two ways
(1) . add one more flag parameter, len used to record the length
(2) . use one less element. If front and rear are next to each other, the queue is full
if(front ==(rear+1)%Array length){ already expired }else{ Not full }
Implementation of queue
#include<stdio.h> #include<mm_malloc.h> /* queue */ typedef struct Queue{ int * pBase; int front; int rear; }QUEUE; // statement void init(QUEUE *pQ); // initialization bool en_queue(QUEUE *pQ,int val); //Join the team bool out_queue(QUEUE *pQ,int *pVal); //Dequeued * pVal is used to save the dequeued value void traverse_queue(QUEUE *pQ); // ergodic bool full_queue(QUEUE *pQ); //Judge whether it is full int main(){ QUEUE Q; // Structure variable init(&Q); en_queue(&Q,1); en_queue(&Q,2); en_queue(&Q,3); en_queue(&Q,4); en_queue(&Q,5); en_queue(&Q,6); en_queue(&Q,7); en_queue(&Q,8); traverse_queue(&Q); return 0; } void init(QUEUE *pQ){ pQ>pBase = (int *)malloc(sizeof(int)*4); // Represents an array pQ>front = 0; pQ>pBase = 0; } bool full_queue(QUEUE *pQ){ if ((pQ>rear+1) % 6 == pQ>front) { return true; }else { return false; } } bool en_queue(QUEUE *pQ,int val){ if(full_queue(pQ)){ return false; }else { pQ>pBase[pQ>rear] = val; // Put val in the rear position pQ>rear = (pQ>rear+1) % 6; // Move the rear one position back return true; } } void traverse_queue(QUEUE *pQ){ // Traverse from the head. As long as you don't point to r, traverse back int i = pQ>front; printf("1111"); while (i!= pQ>rear) { printf("2222"); printf("%d ",pQ>pBase[i]); i = (i+1)%6 ; } return; }
(6) Application  partner problem
5. Recursion
1, Recursive principle analysis
(1) Definition of recursion
(2) Divide and conquer
(3) Function call procedure
(4) Recursion and stack
Analyzing recursion and stack with hierarchical problem
2, Related applications
(1) Seeking stratum
#include<stdio.h> // Class seeking n long getJC(long n){ if(n==1){ return 1; }else { return getJC(n1) * n; } } int main(){ printf("result=%ld",getJC(20)); return 0; }
(2) Sum of 1 + 2 + 3 +... + 100
#include<stdio.h> // Find the sum of 1 to 100 long getSum(long n){ if(n==1){ return 1; }else { return getSum(n1) + n; } } int main(){ printf("sum=%ld",getSum(100)); return 0; }
(3) Maze
(4) Hanoi Tower
Function call
When another function is called during the operation of one function, the system needs to complete three things before running the backtone function:
1) Send all the actual parameters, return address and other information to the called function
2) Allocate memory space for local variables (including formal parameters) of the called function
3) Move the control switch to the entrance of the called function and allocate space
When returning the calling function from the called function, the system also needs to complete three things:
1) . save the return result of the called function
2) . release the storage space occupied by the called function
3) Transfer the control to the place of the calling function according to the return address saved by the called function
Application of recursion
Numbers and forests are defined recursively
Many algorithms of numbers and graphs are implemented by recursion
Many mathematical formulas are defined recursively
6. String
String  a finite sequence of zero or more arbitrary characters
Terms about strings
Substring, true substring, main string, character position, substring position, space string, string equality
Case introduction
Definition, storage structure, algorithm and operation of string
structural analysis
(1) Storage mode of string
1. Sequential storage structure of string
2. Chain storage structure of string
The improved method is to place multiple characters in one node. To overcome its shortcomings
(2) Pattern matching algorithm of string
Algorithm purpose: determine the position (location) of * * substring (mode string) * * contained in the main string for the first time
**Algorithm application: * * search engine, spell check, language translation, data compression
Algorithm type:
 BF algorithm (brute force, also known as classical, classical, simple and exhaustive)
 KMP algorithm (feature: high speed)
(3) BF algorithm
Find the code implementation from scratch
Find the code implementation from the specified location
[the external chain image transfer fails. The source station may have an antitheft chain mechanism. It is recommended to save the image and upload it directly (imgr1gw9kup1636095678706) (/ users / ouyangyansong / library / Application Support / typera user images / image20211101195124408. PNG)]
(4) KMP algorithm
I don't understand
(5) Case  virus detection
7. Array
Definition: a collection of data elements of the same type arranged in a certain format
(1) One dimensional array
(2) Two dimensional array
Extremely special: it can be regarded as either linear structure or nonlinear structure
(3) Sequential storage of arrays
Row order is the main order
Column order is the main order
1. Compressed storage of special matrix
2. Symmetric matrix
3. Triangular matrix
4. Sparse matrix
Triple sequence table
Linked storage structure  cross linked list
8. Generalized table
Basic operations of generalized tables
4, Nonlinear structure
1. Tree
To learn:
B tree and B + tree
Stop B and take the course of the chapter on trees taught by Mr. Geng of Northwestern University
1) Definition of tree
Definition: 1. There is only one node called root
2. There are several disjoint subtrees, which are also a tree
Popular definitions: 1. A tree is composed of nodes and edges
2. Each node has only one parent node, but can have multiple child nodes
3. Except for one node, which has no parent node, this node is called the root node
Technical Term

node
 Parent node
 Child node

descendants
 male cousins

Depth: the number of floors from the root node to the bottom node is called depth  similar floors

**Leaf node: * * node without child nodes

Non terminal node: actually, it is a non leaf node

Root node

**Degree: * * the number of child nodes is called degree
2) Tree classification
1. General tree: the number of any child node is unlimited
2. Binary tree: the maximum number of child nodes of any node is 2, and the position of child nodes cannot be changed!
Classification of binary tree: 1,General binary tree 2,Full binary tree:On the premise of not increasing the number of layers of the tree, a binary tree that cannot add one more node is a full binary tree 3,Complete binary tree: if the knowledge deletes several consecutive nodes at the bottom and right of the full binary tree, the binary tree formed in this way is a complete binary tree
3. Forest: a collection of n disjoint trees
3) Storage of and trees
Storage of trees: nonlinear – > linear
(1) Storage of binary tree:

Continuous storage (full binary tree)

Linked Storage
(2) Storage of general tree
 Parental representation
It's easier to find parents than children

Child representation

Parent child representation
It is convenient to find both parent and child nodes

Binary tree representation
Convert an ordinary tree into a binary tree pair for storage
Specific conversion method:
Try to ensure that the left pointer field of any node points to its first child and the right pointer field points to its brother. As long as this condition can be met, an ordinary number can be transformed into a binary tree
3) , forest
Convert tree to binary tree
Pithy formula:
Binary tree into tree
The forest turned into a binary tree
Binary tree into forest
Forest storage
First convert the forest into a binary tree, and then store the binary tree
4) Traversal of binary tree
1. Preorder traversal
Access the root node first
Then access the left subtree first
Then access the right subtree first
2. Medium order traversal
Middle order traversal of left subtree
Accessing the root node
Then traverse the right subtree in middle order
3. Postorder traversal
Middle order traversal of left subtree
Middle order traversal right subtree
Accessing the root node
4. Two traversal sequences are known to solve the original binary tree
A binary tree can be uniquely restored by first order + middle order or middle order + subsequent
The binary tree cannot be restored through preorder + subsequent
5. Preorder + inorder  > restore binary tree
Priority: ABCDEFGH
Middle order: BDCEAFHG
Follow up?
Example 1:
Example 2:
5. Middle order + post order  > restore binary tree
Middle order: BDCEAFHG
Later: BECBHGFA
For continuation?
5) Application of and tree
 Tree is an important form of data organization in database
 The operating system child parent process relationship itself is a tree
 The inheritance relationship of classes in objectoriented language is itself a tree
 huffman tree
6) Code implementation of chain binary tree traversal
#include<stdio.h> #include<mm_malloc.h> struct BTNode { int data; struct BTNode *pLchild; // p is the pointer L is the left child is the child struct BTNode *pRchild; // p is the pointer, R is the right child, and child is the child }; struct BTNode * CreateBTree(){ struct BTNode *pA = (struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode *pB = (struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode *pC = (struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode *pD = (struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode *pE = (struct BTNode *)malloc(sizeof(struct BTNode)); pA>data = 'A'; pB>data = 'B'; pC>data = 'C'; pD>data = 'D'; pE>data = 'E'; pA>pLchild = pB; pA>pRchild = pC; pB>pLchild = pB>pRchild =NULL; pC>pLchild =pD; pC>pRchild =NULL; pD>pLchild = NULL; pD>pRchild = pE; pE>pLchild = pE>pRchild = NULL; return pA; } void PreTraverseBTree(struct BTNode *pT){ if (NULL != pT) { /* Pseudo algorithm 1,First root node: pT 2,Then start with the left subtree: Pt  > plchild represents a left subtree 3,Right subtree first */ // 1. First root node: pT printf("%c\n",pT>data); // 2. Then start with the left subtree if (NULL != pT>pLchild) { PreTraverseBTree(pT>pLchild); } // 3. Right subtree first if (NULL != pT>pRchild) { PreTraverseBTree(pT>pRchild); } } } void InTraverseBTree(struct BTNode *pT){ if (NULL != pT) { //1. First order traversal of left subtree if (NULL != pT>pLchild) { InTraverseBTree(pT>pLchild); } //2. Access root node printf("%c\n",pT>data); //3. Middle order traversal right subtree if (NULL != pT>pRchild) { InTraverseBTree(pT>pRchild); } } } void PostTraverseBTree(struct BTNode *pT){ if (NULL != pT) { //1. First order traversal of left subtree if (NULL != pT>pLchild) { PostTraverseBTree(pT>pLchild); } //2. Middle order traversal right subtree if (NULL != pT>pRchild) { PostTraverseBTree(pT>pRchild); } //3. Access root node printf("%c\n",pT>data); } } int main(){ struct BTNode *pT = CreateBTree(); // Create binary tree // The nonlinear call can only be output when it is converted to linear, and it can be output in sequential mode // PreTraverseBTree(pT); // InTraverseBTree(pT); PostTraverseBTree(pT); return 0; }
7) Application of binary tree traversal algorithm
Duplicate binary tree
Depth of computer binary tree
Calculate the total number of nodes in the binary tree
Calculate the total number of leaf nodes of binary tree
8) Clue binary tree
(1) . definition
(2) . case demonstration
(3) . flag field
Exercises
To solve the problem of pointing to null, a header node is added
9) , Huffman tree
Introduction
(1) Basic concepts
route
Path length of node
[the external chain image transfer fails. The source station may have an antitheft chain mechanism. It is recommended to save the image and upload it directly (imgw5cpy8cy1636095678842) (/ users / ouyangyansong / library / Application Support / typera user images / image20211104205500558. PNG)]
Path length of tree
Note: complete binary tree is not necessarily the shortest path, and incomplete binary tree can also be the shortest path
Weight
Weighted path length of node
Weighted path length of tree
Calculation of weighted binary tree
(2) Definition
Conclusion:
1. A full binary tree is not necessarily a Huffman tree
2. Huffman trees with the same weighted nodes are not unique
(3) Constructing Huffman tree
(4) Implementation of Huffman tree algorithm
Using sequential storage structure  onedimensional structure array
initialization
Merge to generate a new node
example
(5) Huffman coding
Examples
Implementation of Huffman coding algorithm
(6) Encoding and decoding of files
code
decode
example
2. Figure
(1) Concept
chart
Undirected graph
Directed graph
Complete graph
Sparse graph
Dense graph
network
Adjacency
Association (attachment)
Degree of fixed point
route
path length
route
path length
loop
Simple path
Simple return path (simple loop)
Connected graph (strongly connected graph)
Power and network
Subgraph
Connected component
Strongly connected component
Minimal connected subgraph
Spanning tree
Generative forest
5, Sorting and finding
(1) . classification
Quick sort
#include <stdio.h> /* Quick sort */ //Function declaration void sort(int *a, int low, int high); int FindPos(int *a, int low, int high); int main() { int a[6] = {2, 1, 0, 5, 4, 3}; sort(a, 0, 5); // 0 represents the subscript of the first element and 5 represents the subscript of the last element // Output results for (int i = 0; i < 6; i++) { printf("%d ", a[i]); } } void sort(int *a, int low, int high) { int pos; if (low<high) { FindPos(a,low,high); sort(a,low,pos1); sort(a,pos+1,high); } } int FindPos(int *a, int low, int high){ int val = a[low]; while(low<high){ while(low<high && a[high]>=val){ high; } // assignment a[low] = a[high]; while(low<high && a[low]<=val){ low++; } // assignment a[high] = a[low]; } a[low] = val; return low; // Low and high are OK. After termination, low and high must be equal }