US Study Notes of Data Structures and Algorithms: Session Eight

First, the primer

Browser forward and backward function, I think you must be very familiar with it?

When you visit a bunch of pages in turn finished abc, page viewed before a b and click your browser's back button, you can view. When you back to the page a, click the forward button, you can view the page again b and c. However, if you back to the page b,
click on the new page d, it can no longer pass forward, backward feature to view the page c.

Suppose you are developing engineer Chrome browser, how will you achieve this function?

This use to "stack" such a data structure of our talk today. With this issue, we have to learn the content of today.

Second, how to understand the stack

1, the characteristics of the stack

1, last in, first out, who advanced after the out, this is a typical "stack" structure.
2, the stack is a "limited operation" linear form, insert and delete data only at one end.

Compare 2, and an array of linked lists

1, the relative arrays and linked lists, stacks to bring my only limit, and there is no advantage.
2, I directly use an array or list does not like it? Why use this "limited operation" and "stack" mean?

3. Why do we need a stack

In fact, from a functional point of array or linked list can really replace the stack, but you know, specific data structure is an abstraction of a particular scene,
and an array or list exposed too many user interface, flexible operation indeed free but the use of relatively uncontrollable, of course, more prone to error .
So when the characteristics of a data set only involves the insertion and deletion of data at one end, and to meet the LIFO, last-out, we should be preferred "stack" of this data structure.

Third, how to implement a stack

1, based on the array to achieve

// array-based sequence of stack implementation
public class ArrayStack {
  private String [] items; // array
  private int count; // number of elements in the stack
  private int n; // stack size

  // initialize the array, apply a spatial array of size n,
  public ArrayStack(int n) {
    this.items = new String[n];
    this.n = n;
    this.count = 0;
  }

  // push operation
  public boolean push(String item) {
    // Array space is not enough, direct returns false, the stack fails.
    if (count == n) return false;
    // put the item at index position count, and the count by one
    items[count] = item;
    ++count;
    return true;
  }
  
  // pop operations
  public String pop() {
    // stack is empty, then direct return null
    if (count == 0) return null;
    // returns the subscript array element count-1, and the number of elements in the stack count minus one
    String tmp = items[count-1];
    --count;
    return tmp;
  }
}

2, complexity analysis

Solutions and the definition of basic operation, that time its operations, space complexity is how much?

Whether the order of the stack or chain stack, we only need to store a data array of size n enough. In the process of pushing and popping, only one or two temporary variables memory
storage space, so the space complexity is O (1).

Note that this legislation requires a data storage array of size n, not to say the space complexity is O (n). Because the n space is required, it can not be dispensed with. So
we say that space complexity when, in addition to the original means of data storage space, run the algorithm also require extra storage space.

Space complexity analysis is not very simple? Time complexity is not difficult. Whether the order of the stack or chain stack, stack, stack pop operation involves only the individual data, the time complexity is O (1).

Fourth, support for dynamic expansion of the order of the stack

1, how to implement the order of the dynamic expansion of the stack

How to implement a dynamic array support the dynamic expansion of it?

When the array space is not enough, we have to re-apply for a bigger memory, the original copy of all data in the array past. This realization of a dynamic array expansion support.

So, if you want to achieve a dynamic support dynamic expansion of the stack, we only need to rely on an array of underlying dynamic expansion of support on it.

When the stack is full, we will apply for a larger array, will move the old data to the new array. I draw a diagram, you can understand it shining.

2, out of the stack complexity analysis

For pop operations, we will not involve moving to reapply for memory and data, so the stack time complexity is still O (1).

  1. However, for the incoming operation, the situation is different.
  2. When there is free space in the stack, the stack operation time complexity is O (1).
  3. But when space is not enough, you need to apply for data movement and memory, the time complexity becomes O (n).

3, amortization analysis

For a pop operation, the best case time complexity is O (1), the worst case time complexity is O (n). At that time complexity is how much the average case?

For analytical put it, we need to make some assumptions in advance and definitions:

  • When the stack space is not enough, we have to re-apply for the original one is twice the size of the array;
  • To simplify the analysis, we assume that the operation is not only push and pop operations;
  • The definition does not involve moving the memory stack operations for the START simple-push operation, the time complexity is O (1).

If the current stack size is K, and full, when no new data to the stack when:

1, it is necessary to re-apply twice the amount of memory, and the moving operation done K data, and then the stack.
2, however, the next time K-1 stack operation, we do not need to re-apply for memory and move data, so this K-1 times the stack operations require only a simple-push operation can be completed.
3, in order to make you more intuitive understanding of this process, I drew a picture.

You should be able to see it

1, which is K times the stack operation, involving a total of moving data K, and K times simple-push operation. Move the K data to be shared equally stack operation K times,
2, each push operation requires only that a data movement and a simple-push operation. So, amortized time complexity on the stacking operation is O (1).

By actual analysis of this example

1, but also confirms the mentioned front, amortized time complexity is generally equal to the best-case time complexity.
2, because in most cases, the time complexity is O O stack operation (. 1), only at specific times will be reduced to O (n-),
. 3, so the stack of multiple time consuming operation shared equally to other stack, time-consuming of the average case close to O (1).

V. Application in the function call stack

We know that the operating system to each thread is allocated a separate memory space, this memory is organized into a "stack" of such structures, used to store temporary variables of the function call.
Each entering a function, it will be a temporary variable as a stack frame on the stack, after completion of execution of the called function returns, the function corresponding to the stack frame of the stack.

To give you a better understanding, we have a look at the execution of this code:

int main () {
   int a = 1; 
   int ret = 0;
   int a = 0;
   K = add (3, 5);
   = a + pays nothing;
   printf("%d", res);
   reuturn 0;
}

you add (you get, you y) {
   int sum = 0;
   sum = x + y;
   return sum;
}

We can see from the code:

1, main () function calls the add () function, obtain the calculation result, and adding with a temporary variable, and finally print the values of res.
2, in order to allow you to clearly see the process corresponding to the function stack in the stack, the stack operation, I drew a picture. The figure shows that, when executed to add () function, where the function call stack.

Sixth, expression evaluation stack of application

In fact, the compiler is through two stacks achieved. Wherein a stack operand storage, and the other holding operator stack.
We traverse the expression from left to right, when faced with a number, we directly onto the operand stack; when the operator encountered, the more it is compared with the top element of the stack operator.

1, if a higher priority than the operator of the top element, will be pushed onto the stack current operators;
2, if a lower priority than the operator of the top element or the same, taken from the top of the stack operators in the operator stack,
3, the operand stack from the stack to take two operands and then calculated, and then the end of the calculation result onto the operand stack, comparison continues.

I will be 3 + 5 * 8-6 this calculation expression is drawn into a map, you can be understood in conjunction with FIG calculation of what I said.

 

Seven stack bracket matching application

In addition Using the stack to achieve expression evaluation, we can also check the expression in parentheses matches the aid stack.

We also simplify some background:

1, we assume that only three kinds of expression contains brackets, parentheses (), brackets [] and braces {}, and they may be arbitrarily nested.
2, for example, {[{}]} or [{()} ([])] so as legitimate format,
3, {[} ()] or [({)] is not legal format.

I now give you ⼀ a string expression contains three brackets, how to check if it is legal?

Here you can also use the stack to solve:

1, we use the stack to save unmatched left parenthesis, scanning the string from left to right. When scanning the left parenthesis, it is pushed onto the stack;
2, when the scan to the right bracket, a left parenthesis removed from the stack. If the pattern matches, such as "(" with ")" matches "[" with "]" matches, "{" with "}" match, proceed with the rest of the scan strings.
3, if the scanning process, right parenthesis encountered pairing, or the stack is no data, then the format is illegal.

When all the brackets are scanned, if the stack is empty, then the string is legal format; otherwise, indicating a left parenthesis not match, illegal format

Eight, the answer begins

Well, I think now you have fully understood the concept of the stack. We come back to see the opening of the reflection questions, how to move forward browser back function?

In fact, you can stack Using two perfect solution to this problem.

1, we use two stacks, X and Y, we put you first browse the pages turn pushed onto the stack X,
2, when you click the Back button, then turn the stack from the stack X, and the data is sequentially into the stack stack Y.
3, when we click the forward button, we turn out Y data from the stack, the stack is placed in X. When the stack X, there is no data, it shows that no pages can continue to browse back.
4, when the stack Y no data, it shows no side can click the button to browse forward.

For example, you see a sequence a, b, c three pages, we turn to a, b, c pushed onto the stack, this time, two stacks of data like this

When you retreat from page to page c through a browser's Back button, we turn to c and b pop from the stack X, and turn into the stack Y. This time, two stacks of data like this:

This time they want to see you b page, then click on the Forward button you return to the page b, b and then we put popped from the stack in the Y, X, placed on the stack. At this point two stacks of data like this:

This time, you have to jump through the page to a new page d b, and c can not page through the forward and backward buttons to see repeated, so the need to empty the stack Y. At this point two stacks of data like this

Nine, content summary

Let's review today about the contents:

1, the operation is a stack data structure that is limited only supports push and pop operations. LIFO is its greatest feature.
2, the stack may be achieved through the array, it can also be achieved by a linked list.
3, regardless of the array or linked list based, stack, the stack are time complexity of O (1).
4, in addition, we also talked a sequential dynamic expansion of support stack, you need to focus on mastering its amortized time complexity analysis.

Ten, after-school thinking

1. We are talking about the application stack, talked about the call stack to store temporary variables, function calls Why use the "stack" to save the temporary variables? With other data structures can not I?

Because the execution order of function calls in line with latecomers, first-out, last-out of those features.
For example, the length of the life cycle of the function of local variables is to define a long life cycle, after the definition of short life cycle;
as well as function calls the function, too, began to function only until the execution of other functions perform internal call is completed, this function can perform end.
It is because of these characteristics function calls, according to the data structure is a specific application scenario of abstract principles, our priority stack structure.

2. We all know that, JVM memory management in the concept of a "stack" of. Stack memory is used to store local variables and method calls, heap memory is used to store objects in Java.
That JVM inside the "stack" with us here to say "stack" Is not it all about? If not, then why is it called a "stack" of it

JVM inside the stack and we are here to say is one thing, are called methods stack. Effect of previous function calls is the same for local variable storage method.

Guess you like

Origin www.cnblogs.com/luoahong/p/11812840.html