Go Book / 5 Data Structure & Algorithms / 02 基本数据结构:队列与栈

02 基本数据结构:队列与栈

一、队列

队列是一种受限的线性表,一般由链表实现(也可以用数组实现,链表队列性能较高),因为它只允许表头进入表尾推出,顺序为先进先出。

队列的常见操作:

  • enqueue(element) 向队尾添加一个或多个项
  • dequeue(): 移除队列的第一(即趴在队列最前面的)项,并返回被移除的元素
  • front():返回队列中的第一个元素——即最先被添加,也将是最先被移除的元素,队列不做任何变动(不移除元素,只返回元素值)
  • isEmpty():如果队列中不包含任何元素,返回true,否则返回false
  • size():返回队列包含的元素个数,与数组的length类似
  • toString():将队列的内容转成字符串输出

队列操作.png

顺序队列:由数组切片实现

顺序队列.png

以下为Go代码实现:

type element struct {
	value interface{}
}

type ArrayQueue struct {
	list []element // 内部由数组切片维护
	size int       // 队列长度
	sync.Mutex     // 锁
}

func NewArrayQueue(n int) *ArrayQueue {
	queue := new(ArrayQueue)
	list := make([]element, 0, n)
	queue.list = list
	queue.size = n
	return queue
}

// 队列管理:进队,从0号开始追加
func (q *ArrayQueue) Enqueue(items ...interface{}) bool {
	q.Lock()
	for _, item := range items {
		if len(q.list) < q.size {
			q.list = append(q.list, element{item})
		} else {
			q.Unlock()
			return false
		}
	}
	q.Unlock()
	return true
}

// 队列管理:出队,从0号位开始弹出,并移位后续元素
func (q *ArrayQueue) Dequeue() interface{} {
	q.Lock()
	e := q.list[0]
	l := len(q.list)
	for i := 0; i < l-1; i++ {
		q.list[i] = q.list[i+1]
	}

	q.Unlock()
	return e.value
}

// 获取队头
func (q *ArrayQueue) Front() interface{} {
	return q.list[0]
}

func (q *ArrayQueue) IsEmpty() bool {
	return len(q.list) == 0
}

func (q *ArrayQueue) Size() int {
	return len(q.list)
}

func (q *ArrayQueue) ToString() string {

	return fmt.Sprintf("len:%d,cap:%d,Print:%v", len(q.list), cap(q.list), q.list)
}

链式队列:由链表实现

链式队列.png

以下为Go代码实现


/*
以链表实现队列,从链表头进队,链表尾出队,并提供一些基于链表操作的队列元素管理方法
*/

type LinkQueue struct {
	list *containerList.List // 内部由双向循环链表维护
	size int                 // 队列长度
	sync.Mutex               // 锁
}

func NewLinkQueue(n int) *LinkQueue {
	queue := new(LinkQueue)
	queue.list = containerList.New()
	queue.size = n
	return queue
}

// 队列管理:进队,每次都从链表尾插入
func (q *LinkQueue) Enqueue(items ...interface{}) bool {
	q.Lock()
	for _,item := range items {
		if q.list.Len() < q.size {
			q.list.PushBack(item)
		}else {
			q.Unlock()
			return false
		}
	}
	q.Unlock()
	return true
}

// 队列管理:出队,每次都从链表头移出
func (q *LinkQueue) Dequeue() interface{} {
        if q.Size() == 0 {
		return nil
	}
	q.Lock()
	back := *q.list.Front()
	q.list.Remove(q.list.Front())
	q.Unlock()
	return back.Value
}

// 获取队头,及链表尾部元素
func (q *LinkQueue) Front() interface{} {
	return q.list.Back().Value
}


func (q *LinkQueue) IsEmpty() bool {
	return q.list.Len() == 0
}

func (q *LinkQueue) Size() int {
	return q.list.Len()
}

func (q *LinkQueue) ToString() string {
	var content []interface{}
	next := q.list.Front()
	if next == nil {
		return ""
	}
	content = append(content, next.Value)
	for {
		next = next.Next()
		if next == nil {
			break
		}
		content = append(content, next.Value)
	}
	return fmt.Sprintf("%v", content)
}

二、栈

栈也是一种受限的线性表,一般用数组实现(也可以用链表实现,性能差不多),因为它只允许表头进入,表头弹出,顺序为先进后出;

栈常见操作:

  • push(element): 添加一个新元素到栈顶位置
  • pop():移除栈顶元素,同时返回被移除的元素
  • peek():返回栈顶的元素,不对栈做任何修改(不移除栈顶,只返回栈顶值)
  • isEmpty():如果栈里没有任何元素就返回true,否则false
  • size():返回栈的元素个数,这个方法和数组的length类似
  • toString():将栈结构的内容以字符形式返回

顺序栈:由数组切片实现


// 自定义栈类型,底层为切片数组
type element struct {
	value interface{}
}

type ArrayStack struct {
	list []element
	size int
	sync.Mutex
}

// 栈工厂方法
func NewArrayStack(n int) *ArrayStack {
	stack := new(ArrayStack)
	stack.list = make([]element, 0, n)
	stack.size = n
	return stack
}

// 计算长度;
func (s *ArrayStack) Len() int {
	return len(s.list)
}

// 是否为空
func (s *ArrayStack) isEmpty() bool {
	return len(s.list) == 0
}

// 压栈:追加到切片尾部
func (s *ArrayStack) Push(items ...interface{}) bool {
	s.Lock()
	for _, item := range items {
		if len(s.list) < s.size {
			s.list = append(s.list, element{item})
		}else {
			s.Unlock()
			return false
		}
	}
	s.Unlock()
	return true
}

// 出栈:切片尾部出栈
func (s *ArrayStack) Pop() interface{} {
	l := len(s.list)
	if l == 0 {
		return nil
	}
	s.Lock()
	tail := s.list[l-1]
	s.list = s.list[:l-1]
	s.Unlock()
	return tail.value
}

// 返回栈顶
func (s *ArrayStack) Peek() interface{} {
	len := len(s.list)
	return s.list[len-1].value
}

// 字符串
func (s *ArrayStack) ToString() string {
	return fmt.Sprintf("len:%d,cap:%d,Print:%v",len(s.list),cap(s.list), s.list)
}

链式栈:由链表实现


// 链式栈
type LinkListStack struct {
	stack *containerList.List // 内部维护一个双向链表
	size  int
	sync.Mutex
}

// 栈工厂方法
func NewLinkListStack(n int) *LinkListStack {
	stack := new(LinkListStack)
	stack.stack = containerList.New()
	stack.size = n
	return stack
}

// 计算长度;
func (l *LinkListStack) Len() int {
	return l.stack.Len()
}

// 计算长度;
func (l *LinkListStack) isEmpty() bool {
	return l.stack.Len() == 0
}

// 压栈:从链表头部进栈
func (l *LinkListStack) Push(items ...interface{}) bool {

	l.Lock()
	for _, item := range items {
		if l.stack.Len() < l.size {
			l.stack.PushFront(item)
		} else {
			l.Unlock()
			return false
		}
	}
	l.Unlock()
	return true
}

// 出栈:从链表头部出栈
func (l *LinkListStack) Pop() interface{} {
	l.Lock()
	front := l.stack.Front()
	popEle := *front
	l.stack.Remove(front)
	l.Unlock()
	return popEle.Value
}

// 返回栈顶
func (l *LinkListStack) Peek() interface{} {
	return l.stack.Front()
}

// 字符串
func (l *LinkListStack) ToString() string {
	var content []interface{}
	next := l.stack.Front()
	if next == nil {
		return ""
	}
	content = append(content, next.Value)
	for {
		next = next.Next()
		if next == nil {
			break
		}
		content = append(content, next.Value)
	}
	return fmt.Sprintf("%v", content)
}