Data structure of the Go language: stacks and queues

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. In [Previous posts] (https://studygolang.com/articles/12686), we explored the list and how to apply it to the actual application. In this article, we will continue to explore two similar and powerful data structures. # # Modeling Operations and history Let's take a look at Excel or Google docs, they are the most popular constituent files of human inventions application. We've all used them. As you might know, these applications have a variety of operations on text. For example, add colors, underscores, various fonts and sizes to the text, or organize the content in a table. This list is long and we expect to get a common feature from these tools-the ability to "undo" and "redo" the actions that have already been performed. Have you ever thought about letting you do, how would you plan for such a feature? Let's explore a data structure that will help us accomplish such a task. [] (Https://raw.githubusercontent.com/studygolang/gctt-images/master/data-structures/excel.png) Let's try to figure out how to model the operations of these applications. In addition, we'll see how to save the history of the actions and "undo" them later. A simple ' Action struct ' looks like this: ' Gotype action struct {name Stringmetadata meta//Probably Some other data here...//here may also There are some other data}//translator Note: The action struct needs to add a next field, otherwise the following code does not have a partial operation of type action struct {name Stringmetadata meta//There may be some other data next *ac tion} "We now only store names, and there are relatively many more elements in the actual application. Now, when the user of the editor applies a function to a pile of text, we want to store the action in a collection so that we can "undo" it later. "' Gotype actionhistory struct {top *actionsize int} ' ' This ' actionhistory ' data structure, we store a pointer to ' Action ' at the top of the stack and the size of the stack. Whenever an action is executed, we will link it to the ' top ' operation. Therefore, when you apply an action to a document, it can be run in the background."' Gofunc (History *actionhistory) Apply (newaction *action) {if history.top! = Nil {oldtop: = History.topnewAction.next = Oldtop}history.top = newactionhistory.size++} ' Add ' function (the translator Note: The ' Apply ' in the above section will add the latest ' Action ' to the top of ' actionhistory '). If the historical structure has an action at the top, it will press it down by linking it to the new action. Otherwise, it attaches the new action to the top of the list. Now, if you know the list (or read my recent article about linked lists), you might find similarities. So far, what we have used here is basically still a linked list. What about the undo operation? The following is an implementation of the ' Undo ' function: ' Gofunc (History *actionhistory) Undo () *action {topaction: = history.topif topaction! = Nil {History . top = Topaction.next} else if Topaction.next = = Nil {history.top = Nil}historyaction.size--//historyaction not defined, it should be the author's clerical error R Eturn topaction}//--------------------//Translator Note: There is a problem with the code here, it is recommended to modify the following. "'" Gofunc (*actionhistory) Undo () *action {topaction: = new (Action) if history.size > 0 {topaction = history. Tophistory.top = Topaction.nexthistory.size--}return Topaction} "Thanks for [no smell] (Https://github.com/Unknwon) suggestions. If you look at it carefully, you'll notice that it's a little different from deleting a node from the list. Because of the nature of a ' actionhistory ', we hope that the last action executed is the first to be revoked, which is what we want to achieve. This isThe basic behavior of the stack. A stack is a data structure that you can only insert or delete elements at the top of the stack. Think of it as a bunch of papers, or a bunch of plates in your kitchen drawer. If you want to get the bottom plate out of that pile of plates, it's pretty hard. But it's simple to take the top one. The stack is also considered a ' LIFO ' structure-meaning LIFO, which we explained earlier. This is basically what our ' Undo ' function is dealing with. If the stack (or ' actionhistory ') has more than one ' Action ', it sets the top link for the second item. Otherwise, it will empty ' actionhistory ' and set the ' top ' element to ' nil '. From the ' Big-o ' notation, the complexity of searching the stack is ' O (n) ', but inserting and deleting in the stack is a very quick complication of ' O (1) '. This is because the entire stack is traversed, and in the worst case, all the ' n ' items are still executed, while the time complexity of inserting and deleting elements is constant time, because we always insert and delete from the top of the stack. You can use the working version of the code in [* here *] (Https://play.golang.org/p/Eu8_-HTDBY_A). # # Baggage Control most of us travel by air and know that all personnel must pass through security to get on the plane. Of course, this is for our safety, but sometimes it is not necessary to do all the scanning, checking and testing. A common scenario at airport security checkpoints is a long queue of security personnel, with luggage on the X-ray machine and people passing through metal detectors. Maybe we don't know much about this, but let's focus on the X-ray machines that scan our bags. Have you ever wondered how you would simulate the interaction that happens on this machine? Of course, these are at least visible. Let's take a look at the idea. We must somehow use the baggage as a collection of items, and the X-ray machine scans one piece of baggage at a time. The ' luggage ' structure is as follows: ' gotype luggage struct {weight Intpassenger string} ' at the same time, we add a simple constructor for the ' luggage ' type: ' Gofunc Newluggage (weight int, passenger string) *luggage {L: = Luggage{weight:weight,passenger:passenger,//Just as an identif Ier}return &l} "and then we create a ' Belt ' (pipelining), let ' LuggagE ' is placed above and detected by X-ray. "' Gotype Belt []*luggage ' is not what you want? What we create is a ' Belt ' type, which is actually part of the ' luggage ' pointer. This is the so-called conveyor belt--just a bunch of bags that are scanned individually. So now we need to add a function that knows how to add ' luggage ' to ' Belt ': ' Gofunc (Belt *belt) Add (Newluggage *luggage) {*belt = append (*belt, Newlugga GE)} ' since ' Belt ' is actually a slice, then we can add ' newluggage ' to ' Belt ' using the Go language built-in function ' append '. The fascinating part of this implementation is the complexity of time-because we use the built-in function of ' append ', so the time complexity of the insert operation is O (1). Of course, there is a certain waste of control, which is caused by the working principle of a go language slice. When ' Belt ' starts moving and takes ' luggage ' to the X-ray machine, we need to take the baggage down and put it in the machine for inspection. Given the natural properties of ' Belt ', the first baggage to be placed on the conveyor belt is the first one to be scanned for monitoring. Naturally, the last one on the conveyor belt is the last one to be scanned. So we can say that ' Belt ' is a FIFO (first-in-one-out) data structure body. Please note the above details and see the following ' Take ' function implementation: ' Gofunc (Belt *belt) take () *luggage {First, rest: = (*belt) [0], (*belt) [1:]*belt = Restretur N First} ' ' This function takes the element away and returns it, and it assigns everything else in the collection to its beginning, so its second element becomes the first, and so on. You will find that the time complexity of taking the first element from a queue is ' O (1) '. Using our new types and functions, we can do the following: "' Gofunc main () {belt: = &belt{}belt. Add (Newluggage (3, "Elmer Fudd")) belt. ADD (Newluggage (5, "Sylvester")) belt. Add (Newluggage (2, "Yosemite Sam")) belt. ADD (Newluggage (10, "Daffy Duck")) belt. ADD (Newluggage (1, "Bugs Bunny")) fmt. Println ("Belt:", Belt, "Length:", Len (*belt)) First: = Belt. Take () fmt. Println ("First luggage:", first) fmt. Println ("Belt:", Belt, "Length:", Len (*belt))} "the output of the" main "function is roughly as follows:" ' Belt: &[0x1040a0c0 0x1040a0d0 0x1040a0e0 0x1040a100 0x1040a110] length:5first luggage: &{3 Elmer fudd}belt: &[0x1040a0d0 0x1040a0e0 0x1040a100 0x1040a110 ] Length:4 "Basically, we added 5 different ' luggage ' on ' Belt ', and then we took the first element and it showed up on the second line of the screen. You can use the instance code in [* here *] (https://play.golang.org/p/DTFUkWeZ4H8). # # Passengers in first class? Well, yes, they are. Yes, what about them? I mean, they've spent so much money on tickets, and it's unreasonable for them to wait for luggage in the economy class line. So, how do we prioritize these passengers? If their luggage has some sort of priority, the higher the priority, the quicker they get through the queue. Let's modify the ' luggage ' structure as follows: ' gotype luggage struct {weight intpriority intpassenger string} ' ' Of course, we use ' newluggage ' function to create ' Luggage ' will add ' priority ' as the parameter. "' Gofunc newluggage (weight int, priority int, passenger string) *luggage {L: = luggage{weight:weight,priority:priority, Passenger:passenger,}return &l} "Let's Think again." Basically, when a new ' luggage ' is placed on ' Belt ', we needCheck its ' priority ' and put it at the front of ' Belt ' based on ' the priority '. We are modifying the ' Add ' function: ' Gofunc (Belt *belt) Add (Newluggage *luggage) {if Len (*belt) = = 0 {*belt = append (*belt, newluggage)} E LSE {added: = FalseFor I, placedluggage: = Range *belt {if newluggage.priority > placedluggage.priority {*belt = append ((*belt) [: i], append (Belt{newluggage}, (*belt) [I:] ...) ...) Added = Truebreak}}if!added {*belt = append (*belt, Newluggage)}} "is quite complex compared to the previous implementation. There are a number of situations to deal with, the first being relatively simple. If the belt is empty, we can put the new luggage on the conveyor belt. There is only one thing on ' Belt ', the first one to take away. The second case is that there is an unknown element on ' Belt ', and we want to traverse all the baggage on ' Belt ' and prioritize the baggage that will be added in. When you find a piece of baggage that has a lower priority than it is, it bypasses the priority small bag and puts the new luggage in front of it. This means that the higher priority luggage will be in the ' Belt ' forward position. Of course, if the traverse does not find such luggage, it will attach it to the end of ' Belt '. The time complexity of our new ' Add ' function is ' O (N) ', because in the worst case we are inserting a new element into the ' luggage ' structure that might traverse the entire slice. In essence, any item in the search and access queue is the same complexity ' O (n) '. To demonstrate the new Add feature, we can run the following code: "' Gofunc main () {belt: = make (belt, 0) belt. Add (Newluggage (3, 1, "Elmer Fudd")) belt. Add (Newluggage (3, 1, "Sylvester")) belt. Add (Newluggage (3, 1, "Yosemite Sam")) belt. Inspect () belt. Add(Newluggage (3, 2, "Daffy Duck")) belt. Inspect () belt. Add (Newluggage (3, 3, "Bugs Bunny")) belt. Inspect () belt. Add (Newluggage (2, "Wile E. Coyote")) belt. Inspect ()} "First we create a ' Belt ' with three ' luggage ', these ' luggage ' priorities are 1: ' 0. &{3 1 Elmer fudd}1. &{3 1 sylvester}2. &{3 1 Yosemite Sam} ' then we add a ' luggage ' with a priority of 2 ': ' 0. &{3 2 Daffy Duck}1. &{3 1 Elmer fudd}2. &{3 1 sylvester}3. &{3 1 Yosemite Sam} "You see, the new luggage with the highest priority is promoted to the first position on the ' Belt '. Next, we add a new element with a higher priority (3): ' 0. &{3 3 Bugs bunny}1. &{3 2 Daffy Duck}2. &{3 1 Elmer fudd}3. &{3 1 sylvester}4. &{3 1 Yosemite Sam} ' as expected, the highest priority was placed in the first position of ' Belt '. Finally, we add one more piece of luggage, its priority is 2: ' 0. &{3 3 Bugs bunny}1. &{3 2 Daffy Duck}2. &{100 2 Wile E. coyote}3. &{3 1 Elmer fudd}4. &{3 1 sylvester}5. &{3 1 Yosemite Sam} ' new ' luggage ' will be added to the same priority ' luggage ' after, of course, not ' Belt ' start position. In general, when we add ' luggage ' to ' Belt ' it will be sorted. If you have a certain understanding of the queue, you might think that these are not the most effective ways to implement a priority queue, and you are absolutely right. Implementing a priority queue can use the heap more efficiently, and we'll be in another blog postIn the discussion. We can explore more interesting knowledge about the priority queue. You can view the [Wiki] (Https://en.wikipedia.org/wiki/Priority_queue) page of the priority queue. If you have a certain understanding of the queue, you might think that these are not the most effective ways to implement a priority queue, and you are absolutely right. Implementing a priority queue makes it more efficient to use the heap, which we'll cover in a separate article, especially the implementation section. You can view and use the sample code [here] (Https://play.golang.org/p/Eu8_-HTDBY_A).

Via:https://ieftimov.com/golang-datastructures-stacks-queues

Author: Ilija Eftimov Translator: Sergeychang proofreading: Unknwon

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

642 reads ∙1 likes

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.