"Copyright Declaration" Reproduced please indicate the source (please respect the original, bloggers retain the right to investigate)
http://blog.csdn.net/javazejian/article/details/53362993
From "Zejian's blog."
Related articles:
Design and implementation analysis of sequence table and link list of Java Data structure and algorithm
Design and implementation of two-link list of Java Data structure and algorithm
Java data structure and algorithm of improved sequence table and double linked list similar to ArrayList and LinkedList (with iterator iterator and fast-fail mechanism)
Design and implementation of Java data structure and algorithm stack (stack)
Design and implementation of queues (queue) for Java data structure and algorithms
Recursive thinking of Java Data structure and algorithm (let's understand recursion more commonly)
Java data structure and algorithm tree basic concept and binary tree (BinaryTree) design and implementation
Design and implementation of a balanced binary lookup tree (AVL tree) for Java data structure and algorithm
This is the Java data structure and algorithm 4th, from the beginning of this article we will understand the design and implementation of the stack, the following is the relevant knowledge points:
Design and implementation of sequential stack of abstract data types for stacks the design and implementation of chain stack and application of stack
abstract data types for stacks
A
Stack is a simple data structure that is used to store information. A bit like a linked list or a sequential table (collectively, a linear table), the biggest difference between a stack and a linear table is the operation of data access, and we can think of stack (stack) as a special linear table whose insert and delete operations allow only one end of a linear table, Generally speaking, the one end of the allowable operation is called the top, the Bottom end is called the Stack Bottom (the), and the operation of the insert element is called the stack (push), and the operation of the deletion element is called the stack (POP). If there is no element in the stack, it is called an empty stack, the structure of the stack is as follows:
from the graph we can be seen as stacks can only access elements from the top of the stack, while the first entry is the latter, and the top of the stack will always point to the top of the upper A formal definition of the stack can be given here: stack is an orderly and special linear table that can only be inserted and deleted at one end of the table (called the top of the stack, always pointing to the top of the stack), and the last inserted element will be deleted first, so the stack is also called LIFO LIFO) or a linear table of advanced out (FILO). Stack of basic operations to create stacks, NULL, into the stack, out of the stack, get the top of the stack elements, note that the stack does not support the deletion of the specified location, insert, its interface stack declared as follows:
Package com.zejian.structures.Stack;
/**
* Created by Zejian on 2016/11/27.
* blog:http://blog.csdn.net/javazejian/article/details/53362993 [Original address, please respect original]
* Stack interface abstract data type * * Public
Interface Stack<t> {
/**
* Stack is empty
* @return *
*
Boolean isempty ();
/**
* Data elements into the stack
* @param data *
/void push (T data);
/**
* Returns the top element of the stack, not out of Stack
* @return
/T peek ();
/**
* out Stack, return the top element of the stack, and remove the element from the stack
* @return
/T pop ();
design and implementation of sequential stack
The sequential stack, as the name implies, is the stack implemented by the sequential table, the internal sequence of the stack on the basis of sequential table, to achieve access to the elements of the operation, of course, we can also use the internal array to implement the order stack, where we use the internal data group to implement the stack, as the basis of sequential table implementation, will be provided by source code. Here we first declare a sequence stack with its code as follows, implementing stack and Serializable interfaces:
/**
* Created by Zejian on 2016/11/27.
* blog:http://blog.csdn.net/javazejian/article/details/53362993 [Original address, please respect original]
* The implementation of the sequential stack * * Public
Class Seqstack<t> implements stack<t>,serializable {
private static final long Serialversionuid =- 5413303117698554397L;
/**
* Stack top pointer,-1 on behalf of the empty stack *
* *
private int top=-1;
/**
* Capacity size defaults to a
/private int capacity=10;
/**
* Storage elements of the array * *
private t[] array;
private int size;
public seqstack (int capacity) {
array = (t[]) new object[capacity];
Public Seqstack () {
array= (t[]) new object[this.capacity];
//....... Omit other code
}
The peek operation process that gets the value of the top element of the stack is as follows (no deletion only gets the value):
The code is as follows:
/**
* Gets the value of the top element of the stack without deleting
* @return/
@Override public
T Peek () {
if (IsEmpty ())
new Emptystackexception ();
return array[top];
}
The process of adding elements from the stack is as follows (pointing to the top of the update stack):
The code is as follows:
/**
* add element, insert from top of stack (array tail)
* capacity is insufficient, need to enlarge
* @param data
/@Override public
void push (T data) {
Determine if capacity is sufficient
if (array.length==size)
ensurecapacity (size*2+1);//enlarge
/add element array[++top]=data from top of stack
;
}
The stack pops up the top element of the stack as follows (deletes and gets the value):
The code is as follows:
/**
* Remove from top of stack (sequence table tail)
* @return/
@Override public
T pop () {
if (IsEmpty ())
new Emptystackexception ();
size--;
return array[top--];
}
To this end, the main operation of the sequential stack has been implemented, is not found to be very simple, indeed, the main operation of the stack so, of course, we can also through the introduction of the myarraylist as the basis for the implementation of the order stack, this is relatively simple, the back will also provide with code, here is not too verbose. The overall implementation code for the sequential stack is given below:
Package com.zejian.structures.Stack;
Import java.io.Serializable;
Import java.util.EmptyStackException;
/** * Created by Zejian on 2016/11/27. * blog:http://blog.csdn.net/javazejian/article/details/53362993 [Original address, please respect original] * the implementation of the sequential stack * * public class Seqstack<t> ;
Implements Stack<t>,serializable {private static final long serialversionuid = -5413303117698554397l;
/** * Stack top pointer,-1 on behalf of the empty stack * * * private int top=-1;
/** * Capacity size defaults to a/private int capacity=10;
/** * Storage elements of the array * * private t[] array;
private int size;
public seqstack (int capacity) {array = (t[]) new object[capacity];
Public Seqstack () {array= (t[]) new object[this.capacity];
public int size () {return size;
@Override public Boolean IsEmpty () {return this.top==-1; /** * add element, insert from top (array tail) * @param data/@Override public void push (T data) {//AwardWhether the broken capacity is sufficient if (array.length==size) ensurecapacity (size*2+1);//enlarge/add element from top of stack Array[++top]=d
Ata
size++;
/** * Gets the value of the top element of the stack and does not delete * @return * * @Override public T Peek () {if (IsEmpty ())
New Emptystackexception ();
return array[top];
/** * Remove from top of stack (end of sequence table) * @return/@Override public T Pop () {if (IsEmpty ())
New Emptystackexception ();
size--;
return array[top--]; /** * Expansion Method * @param capacity */public void ensurecapacity (int capacity) {//If you need to expand the capacity ratio
Now that the size of the array is small, there is no need to enlarge the IF (capacity<size) return;
T[] old = array;
Array = (t[]) new object[capacity];
copy element for (int i=0; i<size; i++) array[i]=old[i];
public static void Main (string[] args) {seqstack<string> s=new seqstack<> ();
S.push ("A"); S.push ("B");
S.push ("C");
System.out.println ("size->" +s.size ());
int l=s.size ();//size is decreasing, you must first record for (int i=0;i<l;i++) {System.out.println ("s.pop->" +s.pop ());
} System.out.println ("S.peek->" +s.peek ()); }
}
design and implementation of chain-type stack
After we know the sequence stack, we'll look at the chain stack, the so-called chain-type stack (linked stack), is the use of chain-type storage structure of the stack, because we operate the top end of the stack, so here to use a single linked list (not the lead node) as the basis for direct implementation of the stack add, get, delete and other major operations can be. The operation process is as follows:
As can be seen from the diagram, whether the insertion or deletion of the direct operation of the linked list is the head is the top of the stack, so we only need to use a single linked list without the lead node. Code implementation is as follows, relatively simple, but more analysis:
Package com.zejian.structures.Stack;
Import Com.zejian.structures.LinkedList.singleLinked.Node;
Import java.io.Serializable;
/** * Created by Zejian on 2016/11/27. * blog:http://blog.csdn.net/javazejian/article/details/53362993 [Original address, please respect original] * The chain implementation of the stack * * public class Linkedstack<t
> Implements stack<t>, serializable{private static final long serialversionuid = 1911829302658328353L;
Private node<t> top;
private int size;
Public Linkedstack () {this.top=new node<> ();
public int size () {return size;
@Override public Boolean IsEmpty () {return Top==null | | top.data==null; @Override public void push (T data) {if (data==null) {throw new Stackexception ("Data can\" t
be null ");
} if (This.top==null) {//Call pop () the top may be null this.top=new node<> (data);
}else if (this.top.data==null) {this.top.data=data; }else {node<t> p=new node<> (data,this.top);
top=p;//update stack top} size++;
@Override Public T Peek () {if (IsEmpty ()) {throw new Emptystackexception ("Stack empty");
return top.data;
@Override public T Pop () {if (IsEmpty ()) {throw new Emptystackexception ("Stack empty");
} T Data=top.data;
Top=top.next;
size--;
return data;
}//test public static void main (string[] args) {linkedstack<string> sl=new linkedstack<> ();
Sl.push ("A");
Sl.push ("B");
Sl.push ("C");
int length=sl.size ();
for (int i = 0; i < length; i++) {System.out.println ("sl.pop->" +sl.pop ()); }
}
}
Finally, we take a look at the sequence stack and the chain stack in each operation of the algorithm complexity (time and space) contrast, sequential stack complexity is as follows:
Operation |
Complexity of Time |
Seqstack space complexity (for n times push) |
O (N) |
Push () Time complexity |
O (1) |
Pop () Time complexity |
O (1) |
Peek () Time complexity |
O (1) |
IsEmpty () Time complexity |
O (1) |
The complexity of the chain stack is as follows:
Operation |
Complexity of Time |
Seqstack Space Complexity Creation (for n-time push) |
O (N) |
Push () Time complexity |
O (1) |
Pop () Time complexity |
O (1) |
Peek () Time complexity |
O (1) |
IsEmpty () Time complexity |
O (1) |
So the main operation of the stack can be completed in constant time, mainly because the stack is only one end of the operation, and the operation is only the top of the stack element. Application of Stack
Stack is a very important data structure, in the computer has a very wide range of applications, the following operations are applied to the stack. Symbol matching infix expression conversion to suffix expression compute suffix expression implementation function nesting call HTML and tags in XML file match history of visited pages in Web browser
Next, we make a simple analysis to match the matching, infix expression to suffix expression to deepen our understanding of the stack.
Symbol Matching
In the process of writing a program, we often encounter such things as parentheses "()" and curly braces "{}". These symbols must be left-and-right matching, which is what we call the matching type, of course, not only the number of matches need to be equal, but also the need to first left and then in turn to appear in sequence, otherwise it does not conform to matching rules, such as "", Obviously the wrong match, and "()" is the correct match. Sometimes it fits like parentheses and it's nested, such as "9-(5+ (5+1)"), and the nested matching principle is a closing parenthesis matching the nearest bracket, in fact, the compiler to help me check the syntax error is to perform the same matching principle, and this series of operations need to use the stack to complete, Next we use the stack to implement the detection of whether bracket "()" matches.
The principle of judgment is as follows (str= "((5-3) *8-2)"): A. Set STR is an expression string that is syntactically instrumented for each character char in string Str from left to right, if Char is, the left parenthesis is on the stack, or if char is a closing parenthesis ( A pair of matches can be matched to an opening parenthesis, therefore, if the stack character char is an opening parenthesis, this pair of parentheses matches normally, if the stack is empty or the stack character is not an opening parenthesis, then the left parenthesis that matches the char is missing, which is not complete at this time. B. Repeat a operation until STR detection is complete, and if the stack is empty, all parentheses match, and if there is a left parenthesis in the stack, the closing parenthesis is missing.
The execution flow of the whole detection algorithm is as follows:
Then we use the stack as a storage container through the code to implement this process, the code is relatively simple, as follows:
package com.zejian.structures.Stack;
/** * Created by Zejian on 2016/11/27. * Blog:http://blog.csdn.net/javazejian [Original address, please respect original] * expression detection/public class Checkexpression {public static String is
Valid (String expstr) {//create stack linkedstack<string> stack = new linkedstack<> ();
int i=0;
while (I<expstr.length ()) {char ch=expstr.charat (i);
i++;
Switch (CH) {case ' (': Stack.push (ch+ ");//left parenthesis directly into stack break;
Case ') ': if (stack.isempty () | |!stack.pop (). Equals ("("))//Meet right parenthesis left parenthesis directly out stack return "(";
}///Final detection is NULL, NULL to detect through if (Stack.isempty ()) return "Check pass!";
else return "Check exception!";
public static void Main (string args[]) {string expstr= "((5-3) *8-2)";
System.out.println (expstr+ "" +isvalid (EXPSTR)); }
}
infix expression converted to suffix expression
Let's take a look at what is infix expression, commonly seen in the calculation of expressions are infix expression, such as the following expression:
1+3* (9-2) +9---> infix expressions (no different from everyday expressions)
Learn about infix expressions and then look at their definition: An expression that writes an operator in the middle of two operands is called an infix expression. In infix expression, operators have different precedence, but also can use parentheses to change the order of operations, because of these two points, the use of infix expression operation rules are more complex, the process can not be evaluated from left to right, of course, this is also relative to the computer, After all, we use the calculation of daily life is infix expression. Since the computer feels complex, then we need to convert the infix expression into a computer easy to compute and not complex expression, this is the suffix expression, in the suffix expression, operators are not priority, the entire calculation is followed from left to right in order to calculate, We will convert infix expressions to suffix expressions as follows:
1+3* (9-2) +9 before conversion of infix expression
//1 3 9 2-* + 9 + converted suffix expression
The
infix suffix conversion process requires a stack, where we assume that stack a is used to assist the conversion, and that using array B to store the converted suffix expression is as follows:
1 If the operand is encountered, we put it directly into array B.
2) If an operator is encountered, we put it into stack a and we also put it in stack a when we encounter the opening parenthesis.
3) If a closing parenthesis is encountered, the stack element is ejected, the ejected operator is exported and stored in array B until the opening parenthesis is encountered. Note that the opening parenthesis only pops out and does not save the array.
4) If any other operator is encountered, such as ("+", "*", "("), etc., pops the element from the stack into array B until it encounters an element that finds a lower priority (or the stack is empty). After these elements are ejected, the operator that is encountered is pressed into the stack. One thing to be aware of is that we only eject "(") when we Encounter "" ("), we will not pop" ("".
5) If we read the end of the input, all the elements in the stack are then popped into array B.
6) To this infix expression to complete the suffix expression, the sequence of elements stored in the array represents the converted suffix expression. The
execute the diagram process as follows:
A simple analysis of the process, when the operand is encountered (rule 1), directly into the array B, when i=1 (Rule 2), at this time the operator is +, directly into the stack, when i=3 (rule 2) again encountered operator *, because the stack operator + priority than * low, so directly into the stack, when i=4, encountered operator ' (', Directly into the stack, when I=6, when the operator-, directly into the stack, when i=8 (Rule 3), encounter ',-and ' (' direct out stack, where operator--in suffix array b, when i=9 (Rule 5), because * priority ratio + high, and + + with + peer, so and + out stack, save array b, and the back of the + Again into the stack, when i=10 (rule 5), end, + direct out of the stack into the array b, then the element order of array B is 1 3 9 2-* + 9 +, this is the process of infix suffix.
Then, after turning into a suffix, let's take a look at how the computer uses the suffix expression to perform the result operation, and we know from the previous analysis that the suffix expression is without parentheses, and that the calculation process is done in sequence from left to right, so when the operator is encountered in the evaluation of the suffix expression, You only need to take the first two operands to calculate directly, and when encountered operand can not be evaluated immediately, at this time must first save the operands wait to get to the operator, and then calculate, if there are more than one operand, the operation order is the number of operations that appear after first operation, that is, LIFO first operation, Therefore, we also need to use the stack to do the calculation of the suffix expression, which is used to store operands, the calculation of the suffix expression and its diagram as follows:
Using the stack of program calculation process:
The simple analysis explains:
1 if CH is a number, first converts it to an integer and then into the stack
2 If it is an operator, two operands are counted out of the stack, and the results are then put into the stack
3) Repeat 1 and 2 until the suffix expression ends, the element within the final stack is the result of the calculation.
Overall overall rendering implementation is as follows:
Package com.zejian.structures.Stack;
/** * Created by Zejian on 2016/11/28.
* Blog:http://blog.csdn.net/javazejian [Original address, please respect original] * infix suffix, and then calculate the suffix expression value * * public class Calculateexpression {/** * infix suffix * @param expstr infix expression String * @return/public static string Topostfix (String expstr) {//create stack, for saving
Storage operator Seqstack<string> stack = new seqstack<> (Expstr.length ());
String postfix= "";//storage of the suffix expression of the strings int i=0;
while (I<expstr.length ()) {char ch=expstr.charat (i); Switch (CH) {case ' + ': Cases '-'://When the stack is not empty or the top element of the stack is not a left parenthesis, the stack is directly out, so this time only can be
Can be */+-four operators (according to rule 4), otherwise the into stack while (!stack.isempty () &&!stack.peek (). Equals ("())" {
Postfix + + stack.pop ();
}//Into stack Stack.push (ch+ "");
i++;
Break
Case ' * ': Case '/': Encountered operator/while (!stack.isempty () && (Stack.peek). Equals ("*") | | stack.peek (). Equa
LS ("/")) {postfix + = Stack.pop ();
} Stack.push (ch+ "");
i++;
Break
Case ' ('://Left parenthesis directly into stack Stack.push (ch+ "");
i++;
Break
Case ') '://encountered closing parenthesis (rule 3) String out = Stack.pop ();
while (Out!=null &&!out.equals ("()) {postfix + = out;
out = Stack.pop ();
} i++;
Break
Default://operand directly into stack while (ch>= ' 0 ' && ch<= ' 9 ') {
Postfix + = ch;
i++;
if (I<expstr.length ()) Ch=expstr.charat (i);
else ch= ' = ';
}//separator postfix + = "";
Break
}//Finally put all operators out of stack (rule 5) while (!stack.isempty ()) Postfix + = Stack.pop ();
return postfix; /** * Computes the value of the suffix expression * @param postfix incoming suffix expression * @return/public static int Calculatepostfixvalue (String po
Stfix) {//stack is used to store operands, assist operations linkedstack<integer> stack = new linkedstack<> ();
int i=0, result=0;
while (I<postfix.length ()) {char ch=postfix.charat (i);
if (ch>= ' 0 ' && ch<= ' 9 ') {result=0; while (ch!= ') {//Converts an integer number character to an integral value ch=90 result = result*10 + Integer.parsein
T (ch+ "");
i++;
ch = postfix.charat (i);
} i++; Stack.push (Result)//operand into stack} else {//ch is operator, top two element int y= St on Stack stack
Ack.pop ();
int x= stack.pop ();
Switch (CH) {//To calculate case ' + ': result=x+y; Case '-': result=x-y;
Break Case ' * ': result=x*y;
Break Case '/': result=x/y; Break Note that this is not the case for whether the divisor is 0}//The result of the operation into the stack Stack.push (