Chapter 3 stack and queue
Chapter 2 introduces the concept of linear table. From the perspective of data structure, stack and queue are also linear tables, just two special linear tables. The stack only allows insert or delete operations at one end of the table, while the queue only allows insert operations at one end of the table and delete operations at the other end. Thus, stacks and queues can also be called operation constrained linear tables. From the perspective of data types, stacks and queues are abstract data structures different from linear tables.
3.1 application examples
Application example - maze problem solving
This is a classic problem in experimental psychology. Psychologists make a "maze" with a large box without a top cover, and then drive a mouse into the maze from the entrance. Many partitions are set in the maze, which pose many obstacles to the direction of the mouse. A piece of cheese is placed at the only exit of the maze to attract the mouse to find the right way to reach the exit.
A square matrix of mxn can be used to represent the maze, and 0 and 1 represent the paths and obstacles in the maze respectively. Design
A program, for any set maze, find a path from inlet to outlet, or get the conclusion that there is no path.
When solving the maze by computer, the method of "exhaustive solution" is usually adopted, that is, starting from the entrance, exploring in a certain direction, and continuing to move forward if it can pass; Otherwise, return along the original road and continue to explore in another direction until all possible paths are explored. In order to ensure that you can return along the original path at any position, it is obvious to use a stack with last in first out feature to save the path from the entrance to the current position.
Application example 2 "horse" stepping on the chessboard
Place the chess piece "horse" randomly in a square on the Board[8][8] of the international chess 8x8 board. The "horse" moves according to the rules of chess. It is required that each square only enters once and walks through all 64 squares on the board. Write (non) recursive program to find out the walking route of "horse", and fill the numbers 1, 2,..., 64 into an 8x8 square matrix according to the calculated walking route and output.
When solving, the data structure of the stack can be adopted, that is, the walking sequence of the "horse" can be pressed into the stack. Each time, select one of the multiple walkable positions for exploration, and the other walkable positions that have not been explored must be properly managed with an appropriate structure for "backtracking" (repentance chess) when the exploration fails.
The analysis and implementation of the above examples will be described in detail in Section 3.4.
3.2 stack
3.2.1 concept and operation of stack
Stack is a linear table that only allows inserting and deleting operations at one end
A linear table with limited operation.
The end of a table that allows insertion and deletion is called the "top" and the other end is called the "bottom".
The insertion operation of stack is usually called "stacking" or "pushing",
The stack deletion operation is called "out of stack" or "out of stack" (pop).
When there are no data elements in the stack, it is called "empty stack".
Stack has the feature of last in first out, so it is also called "last in first out (LIFO) table".
Schematic diagram of stack
The basic operations of stack are as follows. ① InitStack(S) initialization:Initialize a new stack. ② Empy(S )Non empty judgment of stack:If stack S Not empty,Then return TRUE;otherwise,return FALSE. ③ Push(S.x) Enter the building:On the stack S Insert element at the top of x,If the stack is full,Then return FALSE;otherwise,return TRUE ④ Pop(S) Out of stack:If stack S Not empty,The stack top element is returned,And delete the element from the top of the stack;otherwise,Returns an empty element ⑤ GetTop(S) Get stack top element:If stack S Not empty,The stack top element is returned;Otherwise, an empty element is returned NULL. ⑥ SetEmpty(S) Stack empty operation:Stack S Empty stack.
Stack is a special linear table, so the stack can be stored in sequential storage structure or chain storage structure.
3.2.2 sequential storage structure of stack
1. Sequence stack
The stack realized by sequential storage is called "sequential stack". Similar to the definition of sequential table, the data elements in the stack use a A preset one-dimensional array of sufficient length:ElemType elem[MAXSIZE]. The bottom position of the stack can be set anywhere in the array One endpoint,The top of the stack changes with insertion and deletion. use int top As a pointer to the top of the stack,Indicates the top of the current stack position,At the same time elem and top Encapsulated in a structure. The types of sequential stacks are described below.
#Define maxsize < Max stack elements > typedef struct{ ElemType elem[MAXSIZE]; int top; }SeqStack;
Define a pointer to the sequential stack:
SeqStack *s;
The subscript end of 0 is often set to the bottom of the stack, so that when the stack is empty, the top pointer s - > Top = - 1; When entering the stack, the pointer at the top of the stack increases by 1, that is, s - > Top + +; When leaving the stack, the stack top pointer is minus 1, that is, s - > top –.
The basic operation of stack is as follows
#include<stdio.h> #include<stdlib.h> //Define sequential stack #define MAXSIZE 10 typedef int ElemType; typedef struct{ ElemType elem[MAXSIZE]; int top; }SeqStack; //(1) Empty stack //First establish the stack space, and then initialize the stack top pointer. SeqStack * InitStack(){ SeqStack *s; s=(SeqStack * ) malloc(sizeof( SeqStack)); s->top=-1; return s; } //(2) Empty stack int Empty(SeqStack *s){ if(s->top==-1) return 1; //Represents empty else return 0; } //(3) Stack int Push(SeqStack *s, ElemType x){ if(s->top==MAXSIZE-1) return 0;//The stack cannot be loaded when it is full, otherwise it will cause "overflow" else {s->top++; s->elem[s->top]=x; return 1; } } //(4) Out of stack int Pop( SeqStack *s, ElemType *x){ if(Empty(s)) return 0; //Stack empty cannot be out of stack else { *x=s->elem[s->top];//Stack top elements are stored in * x and returned s->top--; return 1; } } //(5) Get stack top element ElemType GetTop(SeqStack *s){ if(Empty(s)) return 0;//Stack empty else return (s->elem[s->top]); } int main(){ SeqStack *s=InitStack(); printf("%d",Empty(s));//1 int x1=1; Push(s,x1); int x2=2; Push(s,x2); printf("%d",Empty(s));//0 int x3; Pop(s,&x3); printf("%d",x3);//2 int t=GetTop(s); printf("%d",t);//1 }
2. Multi stack shared adjacent space
The most common stack sharing is two stack sharing.
Assuming that two stacks share a one-dimensional array elem[MAXSIZE], you can take advantage of the stack's "constant stack bottom position and dynamic change of stack top position". The two stack bottoms are - 1 and MAXSIZE respectively, and their stack tops extend to the middle direction. Therefore, as long as the entire array elem[MAXSIZE] is not full, no stack will overflow.
The data structure shared by the two stacks can be defined as follows.
typedef struct{ ElemType elem[ MAXSIZE]; int lefttop;//Left stack top position indicator int righttop;//Right stack top position indicator } Dupsqstack;
The schematic diagram of two stacks sharing adjacent space is shown in Figure 3-4. When the left stack enters the stack, the stack top pointer increases by 1, and when the right stack enters the stack, the stack top pointer decreases by 1. Because the two stack tops can extend to the middle and complement each other, the maximum space of each stack is greater than MAXSIZE/2.
In order to identify the left and right stacks, additional flags must be set:
char status; status ='L'; //Left stack status ='R';//Right stack
During stack operation, you need to specify the stack number status=L 'as the left stack and status='R' as the right stack; The conditions to judge whether the stack is full are as follows:
s->lefttop+1=s->righttop;
The basic operations of shared stack are as follows
#include<stdio.h> #include<stdlib.h> #define FALSE 0 #define TRUE 1 //Define sequential stack #define MAXSIZE 10 typedef int ElemType; typedef struct{ ElemType elem[MAXSIZE]; int lefttop;//Left stack top position indicator int righttop;//Right stack top position indicator } Dupsqstack; //(1) Initialization operation int InitDupStack(Dupsqstack *s){ //An empty stack that creates two shared contiguous spaces is indicated by the pointer s if ((s=(Dupsqstack * )malloc(sizeof(Dupsqstack)))==NULL) return FALSE; s->lefttop=-1; s->righttop=MAXSIZE; return TRUE; } //(2) Stack operation int PushDupSrack(Dupsqstack *s,char status, ElemType x){ //Put the data element x. Push in left stack or right stack if(s->lefttop+1==s->righttop)return FALSE;//Stack full if(status=='L') s->elem[++s->lefttop]=x;//Left stack in stack if(status=='R') s->elem[--s->lefttop]=x;//Right stack in stack else return FALSE;//Parameter error return TRUE; } //(3) Out of stack operation ElemType PopDupStack(Dupsqstack * s,char status){ //Exit the stack top element from the left floor (satus='L ') or the right stack (status='R') if(status=='L'){ if(s->lefttop<0) return 999;//Left stack is empty else return (s->elem[s->lefttop--]);//Left stack out of stack }else if(status=='R'){ if(s->righttop>MAXSIZE-1) return 999;//Right stack is empty else return (s->elem[s->righttop++]);//Right stack out of stack }else return 999;//Parameter error } // De stack top element ElemType GetDupsqTop(Dupsqstack * s,char status){ if(status=='L'){ if(s->lefttop<0) {return 999;}//Left stack is empty else return (s->elem[s->lefttop]);//Take the top element of the left stack }else if(status=='R'){ if(s->righttop>MAXSIZE-1) return 999;//Right stack is empty else return (s->elem[s->righttop]);//Take the right stack top element } } int main(){ Dupsqstack* d; InitDupStack(d); int l0=1; int r0=2; PushDupSrack(d,'L',l0); PushDupSrack(d,'R',r0); int l=GetDupsqTop(d,'L'); int r=GetDupsqTop(d,'R'); printf("%d",l); printf("%d",r); }
3.2.3 chain storage structure of stack
The stack can also be represented by a chain storage structure, which is called "chain stack" for short.
In a chain stack, the bottom of the stack is the last node of the list, and the top of the stack is always the first node of the list. The single linked list of the leading node is used to realize the stack. Because the insertion and deletion of the stack are limited to the header position, the header pointer top of the linked list is used as the stack top pointer. Top always points to the header node in front of the current stack top element, that is, top - > next is the stack top element. When top - > next = = null, it means that the stack is empty.
1) Chain stack definition and (2) operation
#include<stdio.h> #include<stdlib.h> #define FALSE 0 #define TRUE 1 //The C language of chain stack is defined as follows. typedef int DataType; typedef struct Stacknode{ DataType data; struct Stacknode * next; }slStacktype; // initialization slStacktype* Init(){ slStacktype *p; if((p=(slStacktype * )malloc(sizeof( slStacktype)))==NULL) return NULL; return p; } //(1) Stack operation //Push the element x into the top of the chain stack int PushLstack(slStacktype * top, DataType x){ slStacktype *p; //Apply for a node if((p=(slStacktype * )malloc(sizeof( slStacktype)))==NULL) return FALSE; p->data=x; p->next=top->next; top->next=p; return TRUE; } //(2) Out of stack operation //Delete stack top element from chain stack top DataType PopLstack(slStacktype * top){ slStacktype * p; DataType x; if(top->next==NULL){//Empty stack printf("This stack is empty!"); return; } p=top->next; top->next=p->next; x=p->data; free(p); return x; } //Get stack top element DataType GetLsPop(slStacktype * top){ if(top->next==NULL){//Empty stack printf("This stack is empty!"); return; } DataType x=top->next->data; return x; } int main(){ slStacktype *sl=Init(); int x=1; PushLstack(sl,x); int y=GetLsPop(sl); printf("%d",y);//1 int z=PopLstack(sl); printf("%d",z);//1 }
(3) Operation of multiple chain stacks
The stack top pointers of multiple single chain stacks can be placed in a one-dimensional array for unified management.
Set one-dimensional array top[M]:
slStacktype* top[M]
Among them, top [0], top [1],..., top[i],..., top[M-1] points to m different chain stacks, which are the top pointers of M chain stacks. In this way, you only need to determine the chain stack number I, and then use top[i] as the top pointer for stack operation to realize various price operations. The schematic diagram of multiple chain stacks is shown in Figure 3-6.
Basic operations of multiple chain stacks
#include<stdio.h> #include<stdlib.h> #define FALSE 0 #define TRUE 1 #define M 10 //The C language of chain stack is defined as follows. typedef int DataType; typedef struct Stacknode{ DataType data; struct Stacknode * next; }slStacktype; // initialization void Init(slStacktype * top[M],int i){ if((top[i]=(slStacktype * )malloc(sizeof( slStacktype)))==NULL) printf("Initialization error"); return; } //① Stack operation //Press element x into the chain stack top[i] int PushDupLs(slStacktype * top[M],int i, DataType x){ Init(top,i); slStacktype * p; //Apply for a node if((p=(slStacktype *)malloc(sizeof(slStacktype)))==NULL){ return FALSE; } p->data=x; p->next=top[i]->next; top[i]->next=p; return TRUE; } //② Out of stack operation //Delete the stack top element from the chain stack top[i] DataType PopDupLs(slStacktype * top[M],int i){ slStacktype *p; DataType x; if(top[i]->next==NULL){//Empty stack printf("This stack is empty!"); return; } p=top[i]->next; top[i]->next=p->next; x=p->data; free(p); return x; } //Get stack top element DataType GetTopDupLs(slStacktype * top[M],int i){ slStacktype *p; DataType x; if(top[i]->next==NULL){//Empty stack printf("This stack is empty!"); return; } p=top[i]->next; x=p->data; free(p); return x; } int main(){ slStacktype * top[M]; int x1=1; PushDupLs(top,1,x1); int x11=GetTopDupLs(top,1); printf("%d",x11);//1 int x2=2; PushDupLs(top,2,x2); int x22=GetTopDupLs(top,2); printf("%d",x22);//2 }
In the above two algorithms, when the stack number i (0 < = i < = m-1) is specified, only the ith chain stack will be operated and other chain stacks will not be affected.
3.2.4 application of stack
0. Bracket matching
Judge whether the strings composed of brackets correspond to each other one by one
#include<stdio.h> #include<stdlib.h> #include<string.h> //Define sequential stack #define MAXSIZE 10 typedef char ElemType; typedef struct{ ElemType elem[MAXSIZE]; int top; }SeqStack; //(1) Empty stack //First establish the stack space, and then initialize the stack top pointer. SeqStack * InitStack(){ SeqStack *s; s=(SeqStack * ) malloc(sizeof( SeqStack)); s->top=-1; return s; } //(2) Empty stack int Empty(SeqStack *s){ if(s->top==-1) return 1; //Represents empty else return 0; } //(3) Stack int Push(SeqStack *s, ElemType x){ if(s->top==MAXSIZE-1) return 0;//The stack cannot be loaded when it is full, otherwise it will cause "overflow" else { s->top++; s->elem[s->top]=x; return 1; } } //(4) Out of stack int Pop( SeqStack *s, ElemType *x){ if(Empty(s)) return 0; //Stack empty cannot be out of stack else { *x=s->elem[s->top];//Stack top elements are stored in * x and returned s->top--; return 1; } } //(5) Get stack top element ElemType GetTop(SeqStack *s){ if(Empty(s)) return 0;//Stack empty else return (s->elem[s->top]); } int Match(char x,char y){ if(x=='('){ if(y==')'){ return 1; } } if(x=='['){ if(y==']'){ return 1; } } if(x=='{'){ if(y=='}'){ return 1; } } return 0; } void BracketMatch(char *str){ SeqStack* _S=InitStack(); SeqStack S=*_S; int i; char ch; for(i=0;str[i]!='\0';i++){ switch(str[i]){ case'(': case'[': case'{': Push(&S,str[i]); break; case ')': case ']': case '}': if(Empty(&S)){ printf("The right bracket is redundant!"); return; }else{ ch=GetTop(&S); if(Match(ch,str[i])){ Pop(&S,&ch); }else{ printf("The corresponding left and right parentheses are different classes!"); return; } } } } if(Empty(&S)) printf("parenthesis matching!"); else printf("Left parenthesis redundant!"); } int main(){ char str[10]; gets(str); printf("%s",str); BracketMatch(str); }
1. Arithmetic expression evaluation (on computer)
Expression evaluation is a basic problem in programming language compilation
It is a typical application example of stack,
In a computer, any expression is composed of operands, operators, and delimiters. Where the operand can be a constant or a
Solution of expression
Identifier of variable or constant; Operators can be arithmetic operators, relational operators, and logical operation value problems
Symbol; The delimiter is the left and right parentheses and the terminator that identifies the end of the expression. In this section, we only discuss simple
Evaluation of arithmetic expressions. Suppose that this expression contains only four operations: addition, subtraction, multiplication and division, and all the operation objects are
Integer constant. The ending character of the expression is "#", that is, it only contains the symbols +, one,, /, (,) and #.
The rules of the four arithmetic operations are as follows,
Seed Liao calculation
① Multiply and divide first, then add and subtract.
Red sagittal plate
② Left before right in sibling operation.
often
③ First in parentheses, then outside parentheses.
For example, for any expression x+yz#, when calculating the value, scan the expression from left to right, instead of entering it when encountering any operator
For line calculation, if the "+" sign is encountered first, xy cannot be performed at this time, but it can be determined only by comparing with the priority of the adjacent next operator
The next operator is' ', which has higher priority than "+", and then continue to read the next operator "#", which has lower priority than' '
At this time, yz can be calculated, and then x+(yz) can be done. The implementation of expression counting can be completed by setting two stacks.
First set the following two stacks.
3.3 queue
3.3.1 concept and operation of queue
Queue is another limited linear table. It only allows inserting people at one end of the table, while deleting people at the other end of the table. The end that allows inserting people is called rear, and the end that allows deleting is called front.
The insertion operation of the queue is usually "in" or "in", while the deletion operation of the queue is called "out of line" or "out of line". When there are no data elements in the queue, the queue is "empty".
According to the definition of queue, the queue head element is always the most advanced queue and the first out of the queue; the queue tail element is always the last in the queue, so it is also the last out of the queue. This table organizes data according to the principle of first in first out (FIFO). Therefore, the queue is also called "first in first out" table.
The basic operations on the queue are as follows.
①Queue initialization:InitQutoe(ql Phase start condition:queue q non-existent, Operation results:An empty queue is constructed: ②Team operation:InQuene(q.x) initial condition :queue q Presence. Operation results:For existing queues q,Insert an element x To the end of the queue. Operation succeeded,The return value is TRUE,Otherwise, the return value is FALSE ③Out of line operation:OutQueue(q.x) initial condition :queue g Exists and is not empty. Operation results:Delete team leader element,And return its value. The operation was successful,The return value is TRUE,Otherwise, the return value is FALSE ④Read team header element:FrontQueue(q,x) initial condition :queue q Exists and is not empty. Operation results:Read team header element,And return its value,Queue unchanged. Operation succeeded,The return value is TRUE,Otherwise, the return value is FALSE. ⑤Team air operation:EmptyQueue(q) initial condition :queue q existence Operation results:if q If the queue is empty, it returns TRUE,Otherwise, return as FALSE.
The sequential storage structure of the queue can be called "sequential queue" for short. In addition, two indicators are set up: one is the indicator front pointing to the position of the queue head element, and the other is the indicator rear pointing to the position of the queue tail element.
In C language, the subscript of the array starts from 0. Therefore, for the convenience of algorithm design, it is agreed here that when initializing the queue, the front=rear=-1 of the empty queue, when inserting a new data element, the tail indicator rear plus 1, and when the queue head element leaves the queue, the head indicator front plus 1. In addition, it is also agreed that in the non empty queue, the head indicator front always points to the front of the actual queue head element in the queue The tail indicator rear always points to the tail element (this setting is for the convenience of some operations, not the only method).
The types of sequential queues are defined as follows
define MAXSIZE<Maximum number of elements>//Maximum capacity of the queue vypedef struct{ ElemType elem[MAXSIZE];//Storage space for queue elements int rear,front;//Tail and head pointer }SeQueue;
Define a pointer variable to the queue: SeQueue *sq;
Apply for storage space of a sequential queue: sq=(SeQueue*)malloc(sizeof(SeQueue));
There is a problem of "false overflow"
3.3.2 circular queue
One of the ways to solve the false overflow is to regard the data area elem[0~MAXSIZE-1] of the queue as a cyclic structure with head and tail connected, that is, to specify the last cell as the second cell, so that the whole data area is like a ring, which we vividly call cyclic queue
When joining the queue, the operation of adding 1 to the end of the queue pointer is modified to
sq->rear=(sq->rear+1)%MAXSIZE
When leaving the queue, the operation of adding 1 to the end of the queue pointer is modified to
sq->rear=(sq->front+1)%MAXSIZE
Another new problem arises. The conditions for team empty and team full are the same. Both are front==rear
One of the solutions is to use less element space and treat it as full as shown in the figure.
The condition of full queue is (rear+1)%MAXSIZE==front
Can be distinguished from the air force.
Another method is to attach a variable that stores the number of elements in the queue, such as num. when num == 0, the queue is empty, and when num==MAXSIZE, the queue is full
Another is in exercise (8)
The following circular queues and operations are implemented with less than one element space.
Type definition and basic operation of circular queue
#include<stdio.h> #include<stdlib.h> #define FALSE 0 #define TRUE 1 #define MAXSIZE 10 //The following loop is implemented with fewer element spaces based on columns and operations //The type definition and basic operation of circular queue are as follows. typedef int ElemType; typedef struct{ ElemType elem [MAXSIZE];//Storage area of the queue //Head and tail pointer int front, rear; }CSeQueue;//Circular queue //(1) Empty team CSeQueue * IniseQueue(){ CSeQueue * q=(CSeQueue *)malloc(sizeof(CSeQueue)); q->front=q->rear=MAXSIZE-1; return q; } //(2) Join the team int InSeQueue( CSeQueue * q,ElemType x){ if((q->rear+1)%MAXSIZE==q->front){//The team is full printf("Team full"); return FALSE; }else{ q->rear=(q->rear+1)%MAXSIZE; q->elem[q->rear]=x; return TRUE;//Team complete } } //(3) Out of the team int OutSeQueue( CSeQueue *q , ElemType *x){ if(q->front==q->rear){ printf("Team air"); return FALSE; }else{ q->front=(q->front+1)%MAXSIZE; *x=q->elem[q->front];//Read team head element return TRUE;//Team out complete } } //(4) Judge team empty int EmptySeQueue(CSeQueue *q){ if(q->front==q->rear) return TRUE; else return FALSE; } int main(){ CSeQueue *cs=IniseQueue(); int x=1; InSeQueue(cs,x); printf("%d",EmptySeQueue(cs));//0 int x0; OutSeQueue(cs,&x0); printf("%d",x0);//1 printf("%d",EmptySeQueue(cs));//1 }
3.3.3 chain queue
A queue stored in a chain is called a chain queue
The single linked list of the leading node can be used to represent the queue.
The head pointer always points to the head node, and the tail pointer points to the current last element node
Basic operation of chain queue
#include<stdio.h> #include<stdlib.h> #define FALSE 0 #define TRUE 1 #define MAXSIZE 10 typedef int DataType; //The data types of chain queues are described below. typedef struct node{ DataType data; struct node * next; }QNode; //Type of chain queue node typedef struct{ QNode * front; QNode * rear; } LQueue;//A chain queue that encapsulates head and tail pointers //(1) Create an empty team of leading nodes LQueue * Init_LQueue(){ LQueue *q; QNode*p; q=(LQueue*)malloc( sizeof(LQueue));//Application header and footer pointer node p=(QNode*)malloc( sizeof(QNode));//Application chain queue header node p->next=NULL; q->front=q->rear=p; return q; } //(2) Join the team void InLQueue(LQueue *q , DataType x){ QNode *p; p=(QNode*)malloc(sizeof(QNode));//Apply for a new node p->data=x; p->next=NULL; q->rear->next=p; q->rear=p; } //(3) Judge the team empty int Empty_LQueue(LQueue *q){ if(q->front==q->rear) return 1;//Represents empty else return 0; } //(4) Out of the team int Out_LQueue(LQueue *q, DataType *x){ QNode *p; if(Empty_LQueue(q)){ printf("Team air"); return FALSE; } else{ p=q->front->next; q->front->next=p->next; *x=p->data;//Put the team head element in x free(p); if(q->front->next==NULL)//When there is only one element, the queue is empty after leaving the queue, and the tail pointer is modified q->rear=q->front; return TRUE; } } int main(){ LQueue *lq=Init_LQueue(); printf("%d",Empty_LQueue(lq));//1 int x=1; InLQueue(lq,x); printf("%d",Empty_LQueue(lq));//0 int x0; Out_LQueue(lq,&x0); printf("%d",x0);//1 printf("%d",Empty_LQueue(lq));//0 }
3.4 example analysis and Implementation
Application example maze solution
slightly
Application example: two horses stepping on the chessboard
//The horse steps on the chessboard; #include <stdio.h> //Chessboard, where i=0,1,11,12 and j=0,1,11,12 represent the fence, and the horse can step on it, but it is not counted in the count; int M[12][12]={0}; int cnt=0; //Mark the number of squares the horse has walked; int sum=0; //Mark the number of specific schemes for the horse to complete the whole journey; int move[8][2]= //The offset of the current position of the initial horse to the X and y of the eight adjacent Japanese characters around it, that is, there are eight positions where the horse can walk; { { 2, 1}, { 1, 2}, {-1, 2}, {-2, 1}, {-2,-1}, {-1,-2}, { 1,-2}, { 2,-1} }; //Solution of output Horse Stepping on chessboard void PrintChess() { int i; for(i=2;i<10;i++) { int j; for(j=2;j<10;j++) printf("%3d",M[i][j]); printf("\n"); } printf("\n\n\n"); } //Judge where the horse can go; void Horse(int x,int y) //The horse always steps on the position of X and y, not a and B; { if(cnt==64) //At the critical value, the horse steps all the Japanese characters and successfully solves the problem; { sum++; //Number of solutions; printf("The first%d Group solution:\n",sum); PrintChess(); //Output; return ; } int i; for(i=0;i<8;i++) { int a=x+move[i][0]; //Get the x coordinates of the 8 Japanese characters adjacent to the current horse position; int b=y+move[i][1]; //Get the y coordinates of 8 Japanese characters adjacent to the current horse position; if(M[a][b]==0) //Judge whether the Japanese character adjacent to the current horse position has been accessed; { M[a][b]=++cnt; //Flag has been accessed; Horse(a,b); //Continue to visit from the current position of the horse; cnt--; //Back here, the value of the count --; M[a][b]=0; //And clear this position for the next cycle or jump out of the cycle; } } } int main(void) { printf("***The horse steps on the chessboard left and right***\n\n"); //Add two layers to the outer layer of 8 * 8 to ensure that each grid in 8 * 8 square has 8 different choices of Japanese characters; int i; for(i=0;i<12;i++) { int j; for(j=0;j<12;j++) { if(i==0||i==1||i==10||i==11||j==0||j==1||j==10||j==11){ M[i][j]=-1; } } } //All solutions are obtained from the starting position; //Coordinate (2,2) the horse can step on, and the obtained position solution will be + +; M[2][2]=++cnt; //Recursively call 8 days near the current position to see if the conditions are met; //The horse starts from coordinates (2,2); Horse(2,2); return 0; }
Application example 3 calculator
slightly
3.5 algorithm summary - recursive and divide and conquer algorithms
Exercise 3
(2) Palindromes are character sequences that are the same in both forward and reverse reading. For example, "abba" and "abdba" are palindromes, but "good" is not a palindrome. Try to write an algorithm to determine whether a given string is a palindrome.
#include<stdio.h> #include<stdlib.h> #include<string.h> //Define sequential stack #define MAXSIZE 10 typedef char ElemType; typedef struct{ ElemType elem[MAXSIZE]; int top; }SeqStack; //(1) Empty stack //First establish the stack space, and then initialize the stack top pointer. SeqStack * InitStack(){ SeqStack *s; s=(SeqStack * ) malloc(sizeof( SeqStack)); s->top=-1; return s; } //(2) Empty stack int Empty(SeqStack *s){ if(s->top==-1) return 1; //Represents empty else return 0; } //(3) Stack int Push(SeqStack *s, ElemType x){ if(s->top==MAXSIZE-1) return 0;//The stack cannot be loaded when it is full, otherwise it will cause "overflow" else { s->top++; s->elem[s->top]=x; return 1; } } //(4) Out of stack int Pop( SeqStack *s, ElemType *x){ if(Empty(s)) return 0; //Stack empty cannot be out of stack else { *x=s->elem[s->top];//Stack top elements are stored in * x and returned s->top--; return 1; } } //(5) Get stack top element ElemType GetTop(SeqStack *s){ if(Empty(s)) return 0;//Stack empty else return (s->elem[s->top]); } int Match(char x,char y){ if(x==y){ return 1; } return 0; } void BracketMatch(char *str){ SeqStack* _S=InitStack(); SeqStack S=*_S; int i; char ch; int len=strlen(str); int mid=len/2; for(i=0;str[i]!='\0';i++){ if(i==mid&&len%2==1){ continue; } if(i<mid){ Push(&S,str[i]); }else{ if(Empty(&S)){ printf("Right character redundant!"); return; }else{ ch=GetTop(&S); if(Match(ch,str[i])){ Pop(&S,&ch); }else{ printf("The corresponding left and right characters are different!"); return; } } } } if(Empty(&S)) printf("Palindrome!"); else printf("Left character redundant!"); } int main(){ char str[10]; gets(str); printf("%s",str); BracketMatch(str); }
(6) Assuming that the queue is represented by the circular linked list of the leading node, and only one pointer is set to point to the element node at the end of the queue, try to write the corresponding algorithms for setting the empty queue, judging the empty queue, entering the queue and leaving the queue.
#include<stdio.h> #include<stdlib.h> #define FALSE 0 #define TRUE 1 #define MAXSIZE 10 typedef int DataType; //The data types of chain queues are described below. typedef struct node{ DataType data; struct node * next; }QNode; //Type of chain queue node typedef struct{ QNode * rear; } XQueue;//A chain queue that wraps tail pointers together //(1) Create an empty team of leading nodes XQueue * Init_XQueue(){ XQueue *q; QNode*p; q=(XQueue*)malloc(sizeof(XQueue));//Application tail pointer node p=(QNode*)malloc(sizeof(QNode));//Application circular queue header node p->next=p; q->rear=p; return q; } //(2) Join the team void InXQueue(XQueue *q , DataType x){ QNode *p; p=(QNode*)malloc(sizeof(QNode));//Apply for a new node p->data=x; p->next=q->rear->next; q->rear->next=p; q->rear=p; } //(3) Judge the team empty int Empty_XQueue(XQueue *q){ if(q->rear->next==q->rear) return 1;//Represents empty else return 0; } //(4) Out of the team int Out_XQueue(XQueue *q, DataType *x){ QNode *p; if(Empty_XQueue(q)){ printf("Team air"); return FALSE; } else{ p=q->rear->next->next;//Q - > rear - > next is equivalent to Q - > front q->rear->next->next=p->next; *x=p->data;//Put the team head element in x free(p); if(q->rear->next->next==NULL)//When there is only one element, the queue is empty after leaving the queue, and the tail pointer is modified q->rear=q->rear->next; return TRUE; } } int main(){ XQueue *lq=Init_XQueue(); printf("%d",Empty_XQueue(lq));//1 int x1=1; InXQueue(lq,x1); printf("%d",Empty_XQueue(lq));//0 int x2=2; InXQueue(lq,x2); int y1; Out_XQueue(lq,&y1); printf("%d",x1);//1 int y2; Out_XQueue(lq,&y2); printf("%d",y2);//2 printf("%d",Empty_XQueue(lq));//0 }
(8) In the circular queue, you can set a flag field tag to distinguish whether the queue status is "empty" or "full" (the value of tag is 0, which means "empty", and the value of tag is 1, which means "full") when the tail pointer and head pointer are equal. Write the corresponding queue initialization, queue in and queue out algorithms of this structure.
#include<stdio.h> #include<stdlib.h> #define FALSE 0 #define TRUE 1 #define MAXSIZE 2 //The following loop is implemented with fewer element spaces based on columns and operations //The type definition and basic operation of circular queue are as follows. typedef int ElemType; typedef struct{ ElemType elem [MAXSIZE];//Storage area of the queue //Head and tail pointer int front, rear; int flag; }CSeQueue;//Circular queue //(1) Empty team CSeQueue * IniseQueue(){ CSeQueue * q=(CSeQueue *)malloc(sizeof(CSeQueue)); q->front=q->rear=MAXSIZE-1; q->flag=0; return q; } //(2) Join the team int InSeQueue( CSeQueue * q,ElemType x){ if(ManSeQueue(q)){//The team is full printf("Team full"); return FALSE; }else{ q->rear=(q->rear+1)%MAXSIZE; q->elem[q->rear]=x; q->flag=1; return TRUE;//Team complete } } //(3) Out of the team int OutSeQueue( CSeQueue *q , ElemType *x){ if(EmptySeQueue(q)){ printf("Team air"); return FALSE; }else{ q->front=(q->front+1)%MAXSIZE; *x=q->elem[q->front];//Read team head element q->flag=0; return TRUE;//Team out complete } } //(4) Judge team empty int EmptySeQueue(CSeQueue *q){ if(q->front==q->rear&&q->flag==0) return TRUE; else return FALSE; } //Judge team full int ManSeQueue(CSeQueue *q){ if(q->front==q->rear&&q->flag==1) return TRUE; else return FALSE; } int main(){ CSeQueue *cs=IniseQueue(); printf("%d",EmptySeQueue(cs));//1 int x1=1; InSeQueue(cs,x1); int x2=2; InSeQueue(cs,x2); printf("%d",ManSeQueue(cs));//1 int y1; OutSeQueue(cs,&y1); printf("%d",y1);//1 printf("%d",EmptySeQueue(cs));//0 int y2; OutSeQueue(cs,&y2); printf("%d",y2);//2 printf("%d",EmptySeQueue(cs));//1 }