用链表实现栈和队列

205 阅读1分钟

用链表实现栈

package main

import (
	"fmt"
	"sync"
)

type Stack struct {
	top      *node
	length   int
	lock     *sync.RWMutex
}
type node struct {
	value   interface{}
	prev    *node
}

func NewStack() *Stack  {
	return &Stack{
		top:    nil,
		length: 0,
		lock:   &sync.RWMutex{},
	}
}

func(s *Stack)Len() int  {
	return s.length
}

func(s *Stack)Top() interface{} {
	if s.length == 0 {
		return  nil
	}
	return s.top.value
}

func(s *Stack)Push(v interface{}) {
	s.lock.Lock()
	defer s.lock.Unlock()
	n := &node{value: v, prev: s.top}
	s.top = n
	s.length++
}

func(s *Stack)Pop() interface{}{
	s.lock.Lock()
	defer s.lock.Unlock()
	if s.length == 0 {
		return nil
	}
	n := s.top
	s.top = s.top.prev
	s.length--
	return n.value
}

func main() {
	s := NewStack()
	s.Push("a")
	s.Push(2)
	fmt.Println(s.Top())
	fmt.Println(s.Pop())
	fmt.Println(s.Pop())
	s.Push("a")
	s.Push(2)
	fmt.Println(s.Pop())
	fmt.Println(s.Top())
}

为什么函数调用要用“栈”来保存临时变量呢?用其他数据结构不行吗?

其实,我们不一定要用栈来保存临时变量,只不过如果这个函数调用符合后进先出的特性,
用栈这种数据结构来实现,是最顺理成章的选择。
从调用函数进入被调用函数,对于数据来说,变化的是什么呢?是作用域。所以根本上,只
要能保证每进入一个新的函数,都是一个新的作用域就可以。而要实现这个,用栈就非常
方便。在进入被调用函数的时候,分配一段栈空间给这个函数的变量,在函数结束的时候,
将栈顶复位,正好回到调用函数的作用域内。