美文网首页程序员
Implementation of Some Commonly

Implementation of Some Commonly

作者: maxwellhertz | 来源:发表于2018-12-21 15:41 被阅读0次

    Some data structures are commonly used in our development, such as stack, queue, map, etc.. However, (I think) the philosophy of Go is as simple as possible. Go doesn't provide some data structures that I think it should have. Of course I know Go has slice and map but it's the unbox-and-use thing that makes our life simpler, isn't it?

    Sometimes I am super disappointed that the lack of stack, queue, set and sorted map in Go so here I am. I try to implement the four data structures I just mention.

    If there is something wrong, feel free to point it out and I, a newbie of Go, will be very thankful. :smiley:

    Stack

    // A simple implementation of stack.
    type Stack struct {
        // the data stored in stack
        elements []interface{}
    }
    
    // Construct a new stack.
    func NewStack() *Stack {
        return &Stack{make([]interface{}, 0)}
    }
    
    // Test if the stack is empty.
    func (s *Stack) Empty() bool {
        return len(s.elements) == 0
    }
    
    // Return the size of stack.
    func (s *Stack) Size() int {
        return len(s.elements)
    }
    
    // Push an item into the top of stack.
    func (s *Stack) Push(e interface{}) interface{} {
        s.elements = append(s.elements, e)
        return e
    }
    
    // Remove the top of stack and return it.
    func (s *Stack) Pop() interface{} {
        if s.Empty() {
            return nil
        }
        v := s.elements[len(s.elements)-1]
        s.elements = s.elements[:len(s.elements)-1]
        return v
    }
    
    // Retrieve the top of stack.
    func (s *Stack) Peek() interface{} {
        if s.Empty() {
            return nil
        }
        return s.elements[len(s.elements)-1]
    }
    

    Example

    func main() {
        s := NewStack()
        for i := 0; i < 10; i++ {
            s.Push(i)
        }
        fmt.Println(s.Size()) // output: 10
        top := s.Peek()
        fmt.Println(top)  // output: 9
        for !s.Empty() {
            fmt.Println(s.Pop())  // output: 9 8 7 6 5 4 3 2 1 0
        }
    }
    

    Notice that in the Popmethod, I use s.elements = s.elements[:len(s.elements)-1]to remove the last element from slice. Actually it's a trick as mentioned in this article.

    Queue

    // A simple implementation of Queue.
    type Queue struct {
        // the data stored in queue
        elements []interface{}
    }
    
    // Construct a new queue.
    func NewQueue() *Queue {
        return &Queue{make([]interface{}, 0)}
    }
    
    // Test if the queue is empty.
    func (q *Queue) Empty() bool {
        return len(q.elements) == 0
    }
    
    // Return the size of queue.
    func (q *Queue) Size() int {
        return len(q.elements)
    }
    
    // Add an item to the tail of queue.
    func (q *Queue) Add(e interface{}) interface{} {
        q.elements = append(q.elements, e)
        return e
    }
    
    // Remove the head of queue and return it.
    func (q *Queue) Poll() interface{} {
        if q.Empty() {
            return nil
        }
        v := q.elements[0]
        q.elements = q.elements[1:]
        return v
    }
    
    // Retrieve the head of queue and return it.
    func (q *Queue) Peek() interface{} {
        if q.Empty() {
            return nil
        }
        return q.elements[0]
    }
    

    Example

    func main() {
        q := NewQueue()
        for i:= 0; i < 10; i++ {
            q.Add(i)
        }    
        fmt.Println(q.Size()) // output: 10
        head := q.Peek()
        fmt.Println(head) // output: 0
        for !q.Empty() {
            fmt.Println(q.Poll()) // output: 0 1 2 3 4 5 6 7 8 9
        }
    }
    

    Set

    // A simple implementation of set.
    type Set struct {
        // key: data stored in set
        // value: whether data exists in set
        elements map[interface{}]bool
    }
    
    // Construct a new set.
    func NewSet() *Set {
        return &Set{make(map[interface{}]bool)}
    }
    
    // Return the size of set.
    func (s *Set) Size() int {
        return len(s.elements)
    }
    
    // Test if the set is empty.
    func (s *Set) Empty() bool {
        return len(s.elements) == 0
    }
    
    // Add an item that doesn't exist into set. 
    // If the set didn't contain the item, return true, 
    func (s *Set) Add(e interface{}) bool {
        if ok := s.elements[e]; !ok {
            s.elements[e] = true
            return true
        } else {
            return false
        }
    }
    
    // Remove the specific item if it exists in the set.
    // Return true if the set contained the specified item
    func (s *Set) Remove(e interface{}) bool {
        if ok := s.elements[e]; !ok {
            return false
        } else {
            delete(s.elements, e)
            return true
        }
    }
    
    // Test if a specific item exists in the set.
    func (s *Set) Contains(e interface{}) bool {
        return  s.elements[e]
    }
    
    // Return all items in the set.
    func (s *Set) Values() []interface{} {
        vals := make([]interface{}, 0, len(s.elements))
        for v, ok := range s.elements {
            if ok {
                vals = append(vals, v)
            }
        }
        return vals
    }
    

    Example

    func main() {
        set := NewSet()
        set.Add(1)
        set.Add(2)
        set.Add(3)
        set.Add(3)
        fmt.Println(set.Contains(1)) // output: true
        set.Remove(2)
        for e := set.values() {
            fmt.Println(e) // output: 1 3
        } 
    }
    

    I want to point out that the idea of implementing a set based on a map whose value type is boolis mentioned in Effective Go.

    Sorted Map

    I have to admit that one of the biggest disadvantage of Go is the lack of generics (another one may be the lack of a mature dependency management tool). I can't generalize the solution because I have to specify a sortable type as key type. Here I just implement the sorted map of intkey.

    // A simple implementation of sorted map.
    type SortedMapInt struct {
        // all key-value pairs
        pairs map[int]interface{}
        // keys in their natural order
        keys []int
    }
    
    // Construct a new sorted map.
    func NewSortedMapInt() *SortedMapInt {
        return &SortedMapInt{make(map[int]interface{}), make([]int, 0)}
    }
    
    // Test if the map is empty.
    func (m *SortedMapInt) Empty() bool {
        return len(m.pairs) == 0
    }
    
    // Put a new key-value pair into the map and return the old 
    // associated value of this key or nil if there was no mapping for key.
    func (m *SortedMapInt) Put(k int, v interface{}) interface{} {
        if _, ok := m.pairs[k]; !ok {
            m.keys = append(m.keys, k)
            sort.Ints(m.keys)
        }
        old := m.pairs[k]
        m.pairs[k] = v
        return old
    }
    
    // Return the associated value of a specific key if the key exists.
    func (m *SortedMapInt) Get(k int) interface{} {
        if v, ok := m.pairs[k]; ok {
            return v
        } else {
            return nil
        }
    }
    
    // Remove the associated value of a specific key if the key exists.
    func (m *SortedMapInt) Remove(k int) interface{} {
        if v, ok := m.pairs[k]; ok {
            delete(m.pairs, k)
            return v
        } else {
            return nil
        }
    }
    
    // Return the set of keys in their natural order.
    func (m *SortedMapInt) Keys() []int {
        return m.keys
    }
    
    // Return the set of associated values of sorted keys.
    func (m *SortedMapInt) Values() []interface{} {
        vals := make([]interface{}, 0)
        for _, k := range m.keys {
            if v, ok := m.pairs[k]; ok {
                vals = append(vals, v)
            }
        }
        return vals
    }
    

    Example

    func main() {
        sMap := NewSortedMapInt()
        sMap.Put(1, "a")
        sMap.Put(2. "b")
        sMap.Put(3, "c")
        sMap.Put(1, "d")
        fmt.Println(sMap.Keys()) // output: [1 2 3]
        sMap.Remove(2)
        fmt.Println(sMap.Values()) // output: ["d" "c"]
    }
    

    相关文章

      网友评论

        本文标题:Implementation of Some Commonly

        本文链接:https://www.haomeiwen.com/subject/fvzmkqtx.html