# 1, Linear table

## 1. Sequence table and its algorithm implementation

### (1) Design of abstract types

```Const int MAXSIZE = Capacity of sequence table
typedef struct
{
datatype data[MAXSIZE];
int last;
}SeqList;
```

### (2) . initialization of sequence table

```SeqList * init_SeqList(){
SeqList *L;
L = malloc(sizeof(SeqList));
L->last = -1;
return L;
}
```

### (3) . insert operation

```/*
@Param L:Linear table to operate on
@Param i:Where to insert the element
@Param x:Element value to insert
@Return:1 is returned if the insertion is successful, and other information is returned if the insertion is failed
*/
int Insert_SeqList(SeqList *L,int i,datatype x){
//Table full
if(L->last = MAXSIZE-1){
return (-1);
}
//Incorrect insertion position
if(i < 1||i > L->last+2){
return 0;
}
for(int j = L->last;j > i-1;j--){
L->data[j+1] = L->data[j];
}
datatype[i-1] = x;
L->last++;
return 1;
}
```

### (4) . delete operation

```/*
@Param L:Linear table to operate on
@Param i:The location of the element to delete
@Return:1 is returned for successful deletion and 0 is returned for failed deletion
*/
int Delete_SeqList(SeqList *L,int i){
//The table is empty or the location does not exist
if(i < 1||i > L->next+1){
return 0;
}
for(j = i;j <= L->last;j++){
L->data[j-1] = L->data[j];
L->last--;
return 1;
}
}
```

### (5) . find the position according to the value

```/*
@Param L:Linear table to operate on
@Param x:Value to find
@Return:Where to find the value
*/
int Location_SeqList(SeqList *L,datatype x){
int i = 0;
while(i <= L->last&&L->data[i]!=x){
i++;
}
//Can't find
if(i > L->Last){
return -1;
}
//eureka
else{
return i;
}
}
```

Single linked list of leading nodes ### (1) Design of abstract types

```typedef struct node
{
datatype data;
node *next;
```

```/*
@Var s:New node
@Return:Create a good single linked list
*/
LNode *s;
int x;//The data type of the storage element is int
scanf("%d",&x);
//Enter 9999 to end the entry
while(x != 9999){
s = malloc(sizeof(LNode));
s->data = x;
s->next = L;
L = s;
scanf("%d",&x);
}
return L;
}
```

### (3) . tail interpolation method to establish a single linked list

```/*
@Var s:New node
@Var r:Always point to tail node
@Return:Create a good single linked list
*/
LNode *s,*r=NULL;
int x;
scanf("%d",&x);
while(x != 9999){
s = malloc(sizeof(LNode));
s->data = x;
if(L == NULL){
L = s;
}else{
r->next = s;
}
r = s;
scanf("%d",&x);
}
if(r!=NULL){
r->next = NULL;
}
return L;
}
```

### (4) 1. Find the table length

```/*
@Param L:Single linked list to operate on
@Var count:Record the length of the linked list
*/
LNode *p = L;
int count = 0;
while(p->next){
count++;
p = p->next;
}
return count;
}
```

```/*
@Param L:Single linked list to operate on
@Var count:Record the length of the linked list
*/
LNode *p = L;
int count = 0;
if(p==NULL){
return count;
}
count = 1;
while(p->next){
count++;
p = p->next;
}
return count;
}
```

### (5) . find operation

```/*
@Param i:Find location
@Return:Found node
*/
LNode *p = L;
int count = 0;
while(p->next!=NULL&&count < i){
p = p->next;
count++;
}
if(count==i){
return p;
}
return null;
}
```

### (6) . locate by value

```/*
@Param x:Elements to find
@Return:The location of the found element
*/
LNode *p = L->next;
while(p!=NULL&&p->data!=x){
p = p->next;
}
return p;
}
```

### (7) . insert operation

```/*
@Param i:Insert location
@Param x:Inserted element
@Return:1 is returned for successful insertion and 0 is returned for failure
@Var s:New node inserted
@Var p:Precursor node
*/
LNode *p,*s;
//Find precursor element
if(p == NULL){
return 0;
}
s = malloc(sizeof(LNode));
s->data = x;
s->next = p->next;
p->next = s;
return 1;
}
```

### (8) . delete operation

```/*
@Param i:Deleted location
@Return:1 is returned for successful deletion and 0 is returned for failure
@Var s:Nodes to be deleted
@Var p:Precursor node
*/
if(p==NULL||p->next==NULL){
return 0;
}
s = p->next;
p = next = s->next;
free(s);
return 1;
}
```

Definition: Based on the single linked list, the next field of the last node connects the upper node to form a single circular linked list. ### (1) . connection of two single cycle linked lists identified by tail pointer

```/*
@Param R1:Tail pointer to single loop linked list L1
@Param R2:Tail pointer to single loop linked list L2
*/
if(R1 == NULL){
return R2
}
if(R2 == NULL){
return R1;
}
LNode *p = R1->next;//Save the head node pointer of R1
free(R2->next);//Release the header of the second table
R2->next = p;//Form a new circular linked list
return p;
}
```

## 4. Two way linked list ### (1) Design of abstract types

```typedef struct
{
datatype data;
struct dlnode *prior,*next;
```

### (2) . insertion of bidirectional linked list

```(Similar to the single linked list, only the core operations are displayed)
//*s is the new node, * p is the back node of the position to be inserted
s->prior = p->prior;//Assign the previous node of the inserted previous p to the precursor of the new node s
s->next = p;//The subsequent assignment of the new node is p
p->prior->next = s;//The subsequent value of the previous node before p insertion is assigned as a new node
p->prior = s;//The precursor of p is assigned as the new node s
```

### (3) . delete bidirectional linked list

```(Similar to the single linked list, only the core operations are displayed)
//*p is the node to delete
p->prior->next = p->next;//Let the successor of the precursor element of p point to the successor of p
p->next->prior = p->prior;//Let the precursor of the subsequent element of p point to the precursor of p
free(p);
```

## 5. Single linked list classical algorithm

### (1) . linked list inversion

Create a new linked list operation

Algorithm idea: take each node in the original linked list at one time and insert it into the new linked list as the first node. The pointer P is used to point to the current node. When p is empty, it ends.

```void reverse(LinkList H){
LNode *p,*q;
*p = H->next;
H->next = NULL;
while(p){
q = p;
p = p->next;
q->next = H->next;
H->next = q;
}
}
```

Operate in the original linked list ```LNode* reverse(LNode* head) {
struct LNode* prev = NULL;
while (curr) {
LNode* next = curr->next;//Define the next pointer to the header node
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
```

Recursive version (backtracking idea)

```struct LNode* reverse(struct LNode* head) {
}
}
```

### (2) . delete duplicate nodes

Algorithm idea: point to the first data node with pointer P, start from its successor node to the end of the table, find and delete the node with the same value, and P points to the next; By analogy, when p points to the last node, the algorithm ends.

```/*
@Var p:Always point to the first node
@Var q:Traversal pointer
@Var r:Store nodes to delete
*/
LNode *p,*q,*r;
p = H->next;
if(p==NULL) return;
while(p->next){
q = p;
while(q->next){
if(q->next->data==p->data){
r = q->next;
q->next = r->next;
free(r);
}
else{
q = q->next;
}
}
p = p->next;
}
}
```

## 6. Comparison between sequential storage and chain storage

Sequential storage:

I. The method is simple. There are arrays in major high-level languages, which is easy to implement.

III. The sequence table has the characteristics of random access according to the element serial number. O(1)

Ⅳ. The efficiency is low when inserting and deleting in the sequence table. O(n)

V. sufficient storage space needs to be allocated in advance. If it is estimated that it is too large, it will cause a large number of idle at the back of the sequence table; If the pre allocation is too small, it will cause overflow.

Chained storage:

I. the linear table can be programmed without determining the length of the linear table.

II. The length of linear table is allowed to have strong variability.

III. The linked list program can easily insert and delete internal elements. O(1)

## 7. Sequential stack (stack implemented by array)

Introduction to stack data structure:

A data structure based on the first in last out (FILO) principle. ### (1) Design of abstract types

```#define MAXSIZE 1024
typedef struct
{
datatype data[MAXSIZE];//An array of elements in the storage stack
int top;//Pointer to the top of the stack
}SeqStack;
```

### (2) . establish sequence stack

```SeqStack * Init_SeqStack(){
SeqStack * s;
s = malloc(sizeof(SeqStack));
s->top = -1;//Point the top of the stack to - 1 (usually the 0 subscript is set to the bottom of the stack)
return s;
}
```

### (3) . empty stack

```/*
@Param *s:Pointer to the stack being manipulated
@Return:If it is empty, 1 will be returned; otherwise, 0 will be returned
*/
int Empty_SeqStack(SeqStack *s){
if(s->top == -1){
return 1;
}
return 0;
}
```

### (4) . element stacking

```/*
@Param *s:Pointer to the stack being manipulated
@Param x:Elements to stack
@Return:If the stack is successfully loaded, 1 will be returned; otherwise, 0 will be returned
*/
int Push_SeqStack(SeqStack *s,datatype x){
//The stack cannot be put into the stack when it is full
if(s->top == MAXSIZE-1){
return 0;
}
s->top++;//Add one to the top of the stack
s->data[s->top] = x;//The stack top element is assigned x
return 1;
}
```

### (5) . element out of stack

```/*
@Param *s:Pointer to the stack being manipulated
@Param *x:Store the elements out of the stack for subsequent operations
@Return:If the stack is successfully out, it returns 1; otherwise, it returns 0
*/
int Pop_SeqStack(SeqStack *s,datatype *x){
//The stack cannot be left empty
if(Empty_SeqStack(s)){
return 0;
}
*x = s->data[s->top];
s->top--;
return 1;
}
```

### (6) . get stack top element

```/*
@Param *s:Pointer to the stack being manipulated
@Return:Return stack top element value
*/
Datatype Top_SeqStack(SeqStack *s){
if(Empty_SeqStack(s)){
return 0;
}
return s->data[s->top];
}
```

## 8. Chain stack (stack implemented by linked list)

### (1) Design of abstract types

```Typedef struct Node
{
datatype data;
struct Node *next;
```

### (2) . create chain stack

```LinkStack Init_LinkStack(){
top = NULL;
}
```

### (3) . empty stack

```/*
@Param top:Pointer to the top of the stack
@Return:When the stack is empty, it returns 1, otherwise it returns 0
*/
if(top==NULL){
return 1;
}
return 0;
}
```

### (4) . element stacking

```/*
@Param top:Pointer to the top of the stack
@Param x:Elements to stack
*/
StackNode * s;
s = malloc(sizeof(StackNode));
s->data = x;//Assign x to the data field of the new pointer
s->next = top;//The pointer field of the new pointer becomes the top of the original stack
top = s;//Replace new stack top
}
```

### (5) . element out of stack

```/*
@Param top:Pointer to the top of the stack
@Param x:Store the elements to be out of the stack for other operations
*/
StackNode *p;//Pop up the pointer of the stack element to facilitate the memory release operation
return NULL;
}
*x = top->data;
p = top;
top = top->next;//Replace new stack top
free(p);
}
```

## 9. Application examples of stack

### (1) . decimal conversion of numbers:

Title Requirements: convert decimal number N to R-ary number.

Basic principle: N=(N/R) × R+N%R, use rolling division, take N=3467, R=8 as an example.

Chestnuts:

3467÷8 = 433...3

433÷8 = 54...1

54÷8 = 6...6

6÷8 = 0...6

‡ (3467) 10 = (6613) 8. The reverse order of the remainder is the number after conversion, so the stack data structure is adopted.

```void conversion(int N,int R){
SeqStack *s;
datatype *x;//Pointer that stores the value of the popped element
s = Init_SeqStack();
while(N!=0){
Push_SeqStack(s,N%R);
N = N/R;
}
while(!Empty_SeqStack(s)){
Pop_SeqStack(s,x);
printf("%d",x);
}
}
```

### (2) 2. Maze algorithm

Topic requirements: psychologists drive a mouse into the maze from the entrance of a large box without a top cover. Many walls are set in the maze, which forms a variety of obstacles to the forward direction. Psychologists place a piece of cheese at the only exit of the maze to attract mice to find a channel in the maze to reach the exit.

Topic idea: the idea of backtracking is adopted. Backtracking is a search method that constantly explores and corrects errors. When one path fails, return to the previous node for another path.

In the process of solving, in order to return to the previous point correctly, a stack needs to be used to store the subscript and forward direction of each point that can be reached.

Maze design: when the maze is m rows and N columns, design a maze [m+2] [n+2] to represent the maze, maze [i] [j] is 0 or 1, 0 represents the path, and 1 represents no connection. The redundant two rows and two columns around are all 1. (from (1,1) to (m,n) Trial direction design: each point has eight directions to test: up, down, left, left, right, up and down. It is represented by a structure array move. In the move array, each element consists of two fields, namely x-axis increment and y-axis increment. For example, "bottom right" can be expressed as move  .

To design an incremental array (0 from due east): Stack design: X and y are used to represent the position coordinates of a point, and a member variable d is needed to represent the direction.

Prevent repeated passing through a point: when a point is reached, change the point array value to - 1 to distinguish the unreachable points.

```//Maze design
#define m 6
#define n 8
int maze[m+2] [n+2];

//Direction design
typedef struct
{
int x,y;
}item;
item move;

//Stack design
typedef struct
{
int x,y,d;
}datatype;

//Algorithm design
/*
@Param maze:Maze array
*/
int path(int maze[][]){
SeqStack *stack;//Create a sequential stack pointer
datatype temp;//position information
int x,y,d,i,j;
temp.x = 1,temp.y = 1,temp.d = -1;//Set start information
Push_SeqStack(stack,temp);
while(!Empty_SeqStack(stack)){
Pop_SeqStack(stack,&temp);
x = temp.x;
y = temp.y;
d = temp.d+1;//Change the direction and test whether there is a path in each direction
while(d < 8){
i = x+move[d].x;
j = y+move[d].y;//Move one bit in the specified direction
//If you go to the passage
if(maze[i][j] == 0){
temp = {x,y,d};//Store location information
Push_SeqStack(stack,temp);//Store the location information in the stack
x = i,y = j;//Update location information
maze[x] [y] = -1;
if(x==m&&y==n){
return 1;
}
//If you don't reach the end, return the direction to zero
d = 0;
}
//If you come to a dead end, change direction and continue the search
else{
d++;
}
}
}
return 0;
}

```

### (3) . suffix expression

Title Requirements: according to Inverse Polish representation , find the calculation result of the suffix expression.

Valid operators include +, -, *, /. Each operand can be an integer or another inverse expression.

For example, tokens = ["2", "1", "+", "3", "*"], which is transformed into a common infix arithmetic expression: ((2 + 1) * 3) = 9.

Algorithm idea: traverse the character array. When traversing the symbol, two values pop up from the stack for corresponding symbol operation. When traversing other characters, push them into the stack. When the stack is empty, the final calculation result can be obtained.

```/*
@Param *A:Pointer to the first bit of the character array
@Return:Returns the final calculation result
@Var aint,bint:Stores the integer form of the characters a,b
@Var *result:Pointer to result
@Var *ch:Pointer to traversal array
*/
double evalRPN(char *A){
char *a,*b;//Points to the pop-up numeric element
double *result;
//Create and initialize stack
SeqStack *stack = Init_SeqStack();
char * ch = *A++;//Stores the element at the index 0 of the array and moves the pointer back one bit
//If no terminator is found
while(ch!='#'){
switch(ch){
case '+':
Pop_SeqStack(stack,a);
Pop_SeqStack(stack,b);
bd = (double)*b;
break;
case '-':
Pop_SeqStack(stack,a);
Pop_SeqStack(stack,b);
bd = (double)*b;
break;
case '*':
Pop_SeqStack(stack,a);
Pop_SeqStack(stack,b);
bd = (double)*b;
break;
case '/':
Pop_SeqStack(stack,a);
Pop_SeqStack(stack,b);
bd = (double)*b;
break;
case '^':
Pop_SeqStack(stack,a);
Pop_SeqStack(stack,b);
bd = (double)*b;
break;
default:
Push_SeqStack(stack,ch);
}
ch = *A++;
}
Pop_SeqStack(stack,result);
return *result;
}
```

## 10. Sequential cyclic queue (queue implemented by array)

Introduction to queue data structure:

A data structure based on first in first out (FIFO) principle. ### (1) Design of abstract types

```define MAXSIZE 1024
typedef struct
{
datatype data[MAXSIZE];
}SeQueue;
SeQueue *sq;
sq = malloc(sizeof(SeQueue));
```

Detailed explanation of head pointer and tail pointer:

Queue header pointer: SQ - > front, set it to point to a position in front of the queue header element.

End of queue pointer: SQ - > rear, set it to point to the end of queue element.

Empty queue idea: SQ - > front = SQ - > rear = - 1

The idea of entering the queue without considering overflow: SQ - > rear + +; sq->data[sq->rear] = x;

The idea of leaving the queue without considering the empty queue: SQ - > front + +; x = sq->data[sq->front];

Number of elements in the queue: M = (SQ - > rear) - (SQ - > front);

False overflow line image: with the entry and exit of queue elements, the queue moves backward as a whole, resulting in false full population, that is, stack overflow. In order to avoid this phenomenon, circular queue is introduced.

Introduction to related operations of circular queue:

Circular queue: a circular structure with head and tail connected.

For a circular queue, its related operations can be changed as follows:

Queue entry idea: SQ - > rear = (SQ - > rear + 1)% maxsize;

Out of queue idea: SQ - > front = (SQ - > front + 1)% maxsize;

Full and empty conditions: front = rear

Counters can be used to distinguish between full and empty queues. When the counter is 0, it is empty, otherwise it is full.

Final design:

```typedef struct
{
datatype data[MAXSIZE];
int front,rear;
int num;//Number of elements in the queue
}c_SeQueue;
```

### (2) . sequential queue initialization

```/*
@Return:Returns the established queue
*/
c_SeQueue* Init_SeQueue(){
c_SeQueue q = malloc(sizeof(c_SeQueue));
q->front = q->rear = MAXSIZE-1;
q->num = 0;
return q;
}
```

### (3) 2. Elements join the team

```/*
@Param *q:Point to the queue to operate on
@Param x:Elements that need to be queued
@Return:If the queue is successfully entered, 1 will be returned; otherwise, 0 will be returned
*/
int In_SeQueue(c_SeQueue *q,datatype x){
//Queue full
if(q->num == MAXSIZE){
return 0;
}
q->rear = (q->rear+1)%MAXSIZE;
q->data[q->rear] = x;
num++;
return 1;
}
```

### (4) . element out of the team

```/*
@Param *q:Point to the queue to operate on
@Param *x:Point to the element that needs to be dequeued
@Return:1 will be returned if the queue is out successfully; otherwise, 0 will be returned
*/
int Out_SeQueue(c_SeQueue *q,datatype *x){
//When the queue is empty
if(q->num == 0){
return 0;
}
q->front = (q->front+1) % MAXSIZE;
*x = q->data[q->front];
num--;
return 1;
}
```

### (5) . empty queue

```/*
@Param *q:Point to the queue to operate on
@Return:If the queue is empty, return 1, otherwise return 0
*/
int Empty_SeQueue(c_SeQueue *q){
if(q->num == 0){
return 1;
}
return 0;
}
```

### (1) Design of abstract types

```typedef struct node
{
datatype data;
struct node * next;
}QNode;
typedef struct
{
QNode *front,*rear;
}LQueue;
```

The head pointer points to the head node and the tail pointer points to the last node.

Therefore, the judgment condition of empty queue is that the head and tail pointers point to the head node.

### (2) . chain queue initialization:

```/*
Return:Returns the created chain queue
*/
LQueue * Init_LQueue(){
LQueue *q;
QNode *p;
q = malloc(sizeof(LQueue));//Head and tail pointer
p->next = NULL;
q->front = q->rear = p;
return q;
}
```

### (3) 2. Elements join the team

```/*
@Param *q:Point to the queue to operate on
@Param x:Elements that need to be queued
*/
void In_LQueue(LQueue *q,datatype x){
QNode *p;
p = malloc(sizeof(QNode));
p->data = x;
p->next = NULL;
q->rear->next = p;
q->rear = p;
}

```

### (4) . the judgment queue is empty

```/*
@Param *q:Point to the queue to operate on
@Return:If the queue is empty, 1 will be returned; otherwise, 0 will be returned
*/
int Empty_LQueue(LQueue *q){
if(q->front == q->rear){
return 1;
}
return 0;
}
```

### (5) . element out of the team

```/*
@Param *q:Point to the queue to operate on
@Param *x:Point to the element that needs to be dequeued
@Return:1 will be returned if the queue is out successfully; otherwise, 0 will be returned
*/
int Out_LQueue(LQueue *q,datatype *x){
QNode *p;
//Team air condition
if(Empty_LQueue(q)){
return 0;
}
p = q->front->next;//Get the node to be out of the queue
q->front->next = p->next;
*x = p->data;
free(p);
//If the queue has only one node, you still need to modify the end of queue pointer
if(q->front->next == NULL){
q->rear = q->front;
return 1;
}
}
```

## 12. Some examples of linear tables

b. If the single linked list head of the leading node is empty, the judgment condition is [head - > next = = null].

c. If the most common operation of a table is to insert a node after the last node or delete the last node, the storage method of [double cycle linked list of leading node] will save the calculation time.

Detailed explanation: the double cycle linked list of the leading node can directly access the last node through the precursor of the head node, and then insert or delete it.

d. Large space needs to be allocated to insert and delete linear tables that do not need to move elements. Its storage structure is static linked list.

e. The operation of inserting the node indicated by s before the node indicated by p in the double loop linked list is [S - > next = p, s - > prior = p - > prior, p - > prior - > next = s, p - > prior = s].

f. If the input sequence of a stack is a,b,c,d,e, the impossible output sequence of the stack is [dceab].

a can't be taken out in front of b unless it is taken out at the beginning.

g. The condition for judging that a circular queue Qu (maxsize at most) is empty is [Qu - > rear = = Qu - > front].

h. If a circular queue is implemented with a value of 6, and the current value of rear and front are 0 and 3 respectively, when an element is deleted from the queue and two elements are added, the values of rear and front are [2, 4] respectively.

Detailed explanation: delete an element and add 1 to the team head pointer; Add an element and add 1 to the tail pointer.

Posted on Wed, 01 Dec 2021 11:04:13 -0500 by mverrier