Data structure-stacks and queues __ data structures

Source: Internet
Author: User


1. Stack

1.1 the definition of the stack

Stacks are a kind of special linear table. The peculiarity is that the operation of inserting and deleting data elements can only be done at one end of the linear table. As shown below:


Conclusion: LIFO (last in first), abbreviated as the LIFO linear table.

The basic operation of the stack is six kinds:

Constructed empty stack: Initstack (S),

Stack empty: Stackempty (S),

Stack full: Stackfull (S),

Into the stack: Push (s,x), can be visualized as indentation, when the stack will be more than one element

Back stack: Pop (S), can be visualized as a pop-up, pop-up after the stack does not have this element.

Take the top element of the stack: Stacktop (S), different and pop-up, just use the value of the top element of the stack, the element is still on the top of the stack will not change.

Because the stack is also a linear table, the storage structure of the linear table is also applicable to the stack, usually the stack has a sequential stack and chain stacks two storage structures, the two storage structures, which makes the basic operation of the stack algorithm is also different.

What we want to know is that there are "overflow" and "underflow" concepts in the order stack. Sequential stacks like a box, we put a stack of books in it, and when we want to use the book, we can only start with the first one. (Will you turn the box over?) really smart ^ ^), then when we put the book in this stack over the top of the box is not put down (not counted, hem), then is "overflow", "overflow" That is, the top of the stack pointing to the outside of the stack, is obviously a mistake. On the contrary, when there is no book in the stack, we go to take, see no books, take the box to look at the bottom of the box, or not, this is "underflow." The underflow itself can indicate that the stack is an empty stack, so it can be used as a condition for controlling the transfer.

The chain stack has no overflow limit, it's like a fixed chain, you can freely increase the chain (node) at the end of the activity without overflow, the chain stack does not need to attach head nodes in the head, because the stack is operating in the head, if the addition of the head node, is equal to the node after the first node to operate, Instead of making the algorithm more complex, so long as there is a list of the head pointer can be.

1.2 sequential storage of stacks

Object-oriented encapsulation using C + +:

Test.cpp:Defines the entry point for the console application.
#include "stdafx.h" #include <iostream> using namespace std; 
	#define MAX//MAXIMUM stack CONTENT class Stack {private:int Arr[max]; 
int top; 
	Public:stack () {initstack ();                                                                     }/************************************************************************//* initialization stack *//************************************************************************/void inIt 
	Stack () {top=-1;                                                                     }/************************************************************************//* into stack *//************************************************************************/void push (
		int a) {top++; 
		if (Top < MAX) {arr[top]=a; else {cout<< "STACK full!!"   
		<<top; }   
	}   
	/***************************************************************//////* out Stack//*******************************
			/int Pop () {if (IsEmpty ()) {cout<< "STACK is EMPTY";   
		return NULL; 
			else {int data=arr[top]; 
			Arr[top]=null;
			top--; 
		return data;                                                                     }/************************************************************************//* is empty
	*/
	/************************************************************************/
		BOOL IsEmpty () {if (top = 1) return true;
	else return false;   
}
};   
	int main () {stack A;   
	A.push (3);   
	A.push (10);   
	A.push (1);      
	cout<< "Pop:" <<a.pop ();   
return 0;
 }
Conclusion: Because the stack inserts and deletes the operation to have its particularity, therefore uses the sequential storage structure to represent the stack does not have to insert deletes the data element to need to move the problem, but the stack capacity difficult to expand the weakness still not to get rid of.

1.3-Stack chain storage
If the number of elements in the stack changes to a larger range or does not know the number of stack elements, you should consider using a chain-type storage structure. The stacks that people will represent with chained storage structures are called "chain stacks." Chain stacks are usually represented by a single linked list of headless nodes. As shown in the figure:


The operation of Stack is a special case of linear table operation.

Simple in C implementation:

Test.cpp:Defines the entry point for the console application.
#include "stdafx.h" #include <stdio.h> #include "stdlib.h" #include <iostream> using namespace std; Macro definition #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE-1 #define Overf  
LOW-2 #define STACKEMPTY-3 #define LT (A,b) ((a) < (b)) #define N = typedef int Status;  

typedef int ELEMTYPE;               
	typedef struct lnode{elemtype data;     
struct Lnode *next; 

}lnode, *linklist; typedef struct stack{linklist top;}


STACK; /************************************************************************//* Interface: *//*****************************
/void Initstack (STACK &s);
void Push (STACK &s,elemtype e);
void POPs (STACK &s, Elemtype *e);
Elemtype GetTop (STACK s,elemtype *e);

int Stackempty (STACK S); /****************************************************************/////////*//************************************************************************/void Initstack (STACK

&s) {s.top=null;} /************************************************************************//* into the stack * */******************************
	/void Push (STACK &s,elemtype e) {linklist p;
	p = (linklist) malloc (sizeof (Lnode));
	if (!p) exit (OVERFLOW);
	P->data = e;
	P->next = S.top;
S.top = p; }/************************************************************************//* out stack * */*****************************
	/void POPs (STACK &s, Elemtype *e) {linklist p;
	if (Stackempty (S)) exit (Stackempty);
	*e = s.top->data;
	p = s.top; 
	S.top = p->next;
Free (p); /************************************************************************//* Get top element content of the stack * */*********************** /Elemtype GetTop (STACK S, Elemtype *e) {if (Stackempty (S)) exit (Stackempty);
*e = s.top->data; /************************************************************************//* Determine if stack s is empty//************************
	/int Stackempty (STACK S) {if (s.top==null) return TRUE;
return FALSE;
	} void Main () {STACK S;
	Initstack (S);
	Push (S, 3);
	Push (S, 4);
	Elemtype e;
	Pop (s,&e);  
 cout<< "Pop elem:" <<e;}

1.4 Application of Stack

1) Conversion of the numbering

2) Grammatical lexical analysis

3) expression evaluation, etc.


recursive and implementation of 1.5 stacks

Hanoi's Problem:

Solve:

1 if there is a plate, move directly from X to Z.
2 If there are n plates to be moved from X to Z,y as auxiliary. The problem can be converted to, first, move the top n-1 from X to Y,z as a secondary, then move nth from X to Z, and finally move the remaining n-1 from Y to z,x as a secondary.

Complete implementation of the code, including the implementation of the stack:

Test.cpp:Defines the entry point for the console application.
#include "stdafx.h" #include <stdio.h> #include "stdlib.h" #include <iostream> using namespace std; Macro definition #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE-1 #define Overf  
LOW-2 #define STACKEMPTY-3 #define LT (A,b) ((a) < (b)) #define N = typedef int Status;  

typedef int ELEMTYPE;               
	typedef struct lnode{elemtype data;     
struct Lnode *next; 

}lnode, *linklist; typedef struct stack{linklist top;}


STACK; /************************************************************************//* Interface: *//*****************************
/void Initstack (STACK &s);
void Push (STACK &s,elemtype e);
void POPs (STACK &s, Elemtype *e);
Elemtype GetTop (STACK s,elemtype *e);

int Stackempty (STACK S); /****************************************************************/////////*//************************************************************************/void Initstack (STACK

&s) {s.top=null;} /************************************************************************//* into the stack * */******************************
	/void Push (STACK &s,elemtype e) {linklist p;
	p = (linklist) malloc (sizeof (Lnode));
	if (!p) exit (OVERFLOW);
	P->data = e;
	P->next = S.top;
S.top = p; }/************************************************************************//* out stack * */*****************************
	/void POPs (STACK &s, Elemtype *e) {linklist p;
	if (Stackempty (S)) exit (Stackempty);
	*e = s.top->data;
	p = s.top; 
	S.top = p->next;
Free (p); /************************************************************************//* Get top element content of the stack * */*********************** /Elemtype GetTop (STACK S, Elemtype *e) {if (stackemptY (S)) exit (Stackempty);
*e = s.top->data;
	} void Printstack (STACK S) {linklist p;
	p = s.top;
	printf ("stack:");
		while (p) {printf ("%d", p->data);
	p = p->next;
}/************************************************************************//* If there is a plate, move directly from X to Z. If there are n plates to be moved from X to Z,y as auxiliary.
The problem can be converted to, first, move the top n-1 from X to Y,z as a secondary, then move nth from X to Z, and finally move the remaining n-1 from Y to z,x as a secondary. *//************************************************************************/void Move (STACK &sa,stack &Sb
	) {Elemtype E;
	Pop (sa,&e);
Push (Sb, E);		} void Hanoi (int n,stack &x,stack &y,stack &z) {if (n==1) return Move (X, Z);				The disc 1th is moved directly to Z Hanoi (N-1,x,z,y);						Move the 1 large n-1 discs on the X to y,z as auxiliary tower moves (x, Z);			    Shift the disk number N to Z Hanoi (N-1,Y,X,Z); Move the 1 large n-1 discs on Y to the z,x as the Auxiliary tower}/************************************************************************//* To determine if the stack s is empty */* /int Stackempty (STACK S) {if (s.top==null)
	return TRUE;
return FALSE; }

void Main () {STACK Sx, Sy,sz;
	Initstack (SX);
	Initstack (Sy);
	Initstack (SZ);
	int i, n = 10;
	for (i =; i>=1; i--) {Push (Sx, i);
	Printstack (SX);
	Hanoi (n, Sx,sy,sz);
Printstack (SZ);  
 }


1. Queues

1.1 Queue Definition

Queues (queue) is also a linear table with limited operation, which has a different operation limit than a stack. There is a limit at both ends, the insertion can only be done at one end of the table (only), while deletions can only be made at the other end of the table (only out), allowing the end of the deletion to be called the tail (rear), which allows the inserted end to be called the team head ( Front)

, the operation principle of the queue is FIFO, so the queue is also called the first-out table

There are also six basic operations for queues:

Empty team: Initqueue (Q)

Team null: Queueempty (Q)

Team full: Queuefull (Q)

Team: EnQueue (q,x)

Out team: dequeue (Q)

Take the team head element: Queuefront (Q), different from the team, the team head element is still retained.

Queues also have sequential storage and chained storage structures, the former being called sequential queues, and chain teams.

For sequential queues, we want to understand the phenomenon of false overflow.

Our real queues, like the crowds lining up to buy tickets, can go in and out from the other side, unless the place is not enough, there will be no "overflow" phenomenon, similarly, when the elements of the queue is completely filled with this vector space, then the team will naturally overflow, if there is no element in the queue, then will also be out of the line overflow.

What about "fake overflow"?

Because here, our queues are stored in a vector space, in this contiguous storage space, the queue is represented by a queue head pointer and a trailing pointer, when the top pointer and tail pointer point to the same position, the queue is empty, that is, the queue is composed of elements in the middle of two pointers. In the queue, the team and the teams are not like reality, the elements move forward one by one, the end is gone, but the pointer is moving, when the team operation, the head pointer forward (that is, the tail of the vector space) to add a position, team, the tail pointer to increase a position, in some cases, such as into a one out, Two pointers move forward continuously, until the queue is the end of the vector space, then the team, the tail pointer will run to the vector space outside, only the tube then the entire vector space is empty, the queue is empty, but produced a "overflow" phenomenon, this is false overflow.

To overcome the space waste caused by this phenomenon, we introduce the concept of cyclic vectors, it is like bending a vector space to form a ring with a tail-end, so that when the queue's trailing pointer is moved to the upper bound (the tail) of the vector space, the addition of a 1 operation (team or out) causes the pointer to point to the lower bound of the vector, Which is starting from scratch. At this point the queue is called the loop queue.

Most of the applications we use are circular queues. Because of the cycle, the light to see the tail pointer overlap together we can not determine whether the queue is empty or full, then we need to deal with some boundary conditions to distinguish whether the queue is empty or full. There are at least three kinds of methods, one is to set another Boolean variable to judge (is to ask others to look at, is empty or full by his decision), the second is to use less than an element space, when the team, first test the rear pointer is not equal to the head pointer, if equal even if the teams are full, not to join. The third is to use a counter to record the total number of elements in the queue, so you can always know the length of the queue, as long as the number of elements in the queue is equal to the length of the vector space, is the team full.
2.2 Sequential storage of queues

sequential storage as shown:


Because the storage space of the sequential storage structure is statically allocated, it is possible to have no space left when the data is added.

To resolve this "fake overflow" situation, use a looping queue . in C language, the loop queue cannot be implemented by dynamically allocating one-dimensional arrays. If you use a loop queue, you must set the maximum queue length, and if you cannot estimate the maximum length, use a chained queue.

C Implementation:

Test.cpp:Defines the entry point for the console application.
#include "stdafx.h" #include <stdio.h> #include "stdlib.h" #include <iostream> using namespace std; Macro definition #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE-1 #define Overf  
LOW-2 #define QUEUEEMPTY-3 #define The maximum number of data elements for the Max_queue 10//queue typedef int STATUS;  

typedef int ELEMTYPE;     typedef struct queue{elemtype Elem[max_queue];		Assuming that the team is full int front when only one cell is left in the array;		Team head pointer int rear; 


Team tail pointer}queue;
/************************************************************************//* The basic operation algorithm.
* */************************************************************************/void Initqueue (QUEUE *&Q);
void EnQueue (QUEUE *q,elemtype elem);
void Dequeue (QUEUE *q,elemtype *elem);

int Queueempty (QUEUE Q); /************************************************************************//* Initialization directly using the structure pointer variable, you must first allocate the memory address, that is, the address of the pointer//void Initqueue (queue *&q) {Q = (queue *
	) malloc (sizeof (QUEUE));

Q->front = Q->rear =-1;                                                              
}/************************************************************************//* Team * */************************************************************************/void EnQueue (QU
	Eue *q, Elemtype elem) {if ((q->rear+1)% Max_queue = = Q->front) exit (OVERFLOW);
	Q->rear = (q->rear + 1)%max_queue; 
Q->elem[q->rear] = Elem;                                                               
}/************************************************************************//* out Team * */************************************************************************/void dequeue (QUE
	UE *q,elemtype *elem) {if (Queueempty (*Q)) exit (Queueempty);
	Q->front = (q->front+1)% Max_queue;
*elem=q->elem[q->front]; }
/**************************/////////* Get the team header element 
* */************************************************************************/void Getfront (QUEUE Q,ElemType *elem)
	{if (Queueempty (Q)) exit (Queueempty);
*elem = q.elem[(q.front+1)% max_queue];                                                             
/************************************************************************//* To determine if queue Q is empty * */************************************************************************/int queueemp
	Ty (QUEUE Q) {if (q.front==q.rear) return TRUE;
else return FALSE;
	} void Main () {QUEUE *q;
	Initqueue (Q);
	EnQueue (Q, 1);
	EnQueue (Q, 2);
	Elemtype e;
	Dequeue (q,&e);  
 cout<< "De queue:" <<e;}

Note: initqueue (QUEUE *&q) is the address of the pointer.


2.3-Chained queues:

Test.cpp:Defines the entry point for the console application.
#include "stdafx.h" #include <stdio.h> #include "stdlib.h" #include <iostream> using namespace std; Macro definition #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE-1 #define Overf  
LOW-2 #define QUEUEEMPTY-3 typedef int STATUS;  

typedef int ELEMTYPE;			The node structure of the typedef struct LNODE {//chained queues elemtype elem;		 The data element type of the queue struct Lnode *next;

Pointer to subsequent nodes}lnode, *linklist;		typedef struct queue{//chained queues linklist front;		Team head pointer linklist rear; 

Team tail pointer}queue;
/************************************************************************//* The basic operation algorithm.
* */************************************************************************/void Initqueue (QUEUE *Q);
void EnQueue (QUEUE *q,elemtype elem);
void Dequeue (QUEUE *q,elemtype *elem);
void Getfront (QUEUE q,elemtype *elem);

BOOL Queueempty (QUEUE Q); /*************************************************/* Initialize queue Q/void Initqueue (queue *q) {Q->front = (linklist) malloc (sizeof (Lnode));
	if (q->front==null) exit (ERROR);
Q->rear= q->front;
	}/* Team/void EnQueue (QUEUE *q,elemtype elem) {linklist s;
	s = (linklist) malloc (sizeof (Lnode));
	if (!s) exit (ERROR);
	S->elem = Elem;
	S->next = NULL;
	Q->rear->next = s;
Q->rear = s;
	} * * out team/void Dequeue (QUEUE *q,elemtype *elem) {linklist s;
	if (Queueempty (*Q)) exit (ERROR);
	*elem = q->front->next->elem;
	s = q->front->next;
	Q->front->next = s->next;
Free (s);
	/* Get team head element content/void Getfront (QUEUE q,elemtype *elem) {if (Queueempty (Q)) exit (ERROR);
*elem = q.front->next->elem;
    }/* Determine if queue q is null/bool Queueempty (queue Q) {if (Q.front = = q.rear) return TRUE;
return FALSE;
	} void Main () {QUEUE Q;
	Initqueue (&AMP;Q);
	EnQueue (&q, 1);
	EnQueue (&q, 2);
	Elemtype e;
	Dequeue (&q,&e);  
 cout<< "De queue:" <<e;}


2.4 . The application of the queue
"Example 1" bank queuing
"Example 2" simulates the printer buffer.
When a host outputs data to a printer, the problem is that the host speed does not match the printer's print speed. Then the host will stop to wait for the printer. Obviously, this can reduce the efficiency of the host's use. To this end people have conceived a way: To set a print data buffer for the printer, when the host needs to print data, first write the data into the buffer, after the host to turn to do other things, and the printer from the buffer in accordance with the principle of FIFO in order to read the data and print, This is to ensure the correctness of the printed data, but also improve the use of the efficiency of the host. This shows that the printer buffer is actually a queue structure.
Example 3 CPU time-sharing system
in a computer system with multiple terminals, and multiple users need to use CPU to run their own applications, they respectively through their terminals to the operating system to use the CPU request, the operating system usually in accordance with each request in the order of time, Line them up in a queue, each time allocating the CPU to the requesting user at the top of the current team, the user's application will be put into operation, when the program is finished or after the prescribed time slice, the operating system to allocate the CPU to the new team first request users, so that can meet each user's request, but also to make the CPU normal work.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.