Golang实现栈和队列操作(切片实现和链表实现)

参考文章:golang数组实现栈(压栈,弹栈,取栈顶元素,获取栈中元素个数)
本文包含栈和队列的七种基本操作:

  1. 创建 new
  2. 判空 isEmpty
  3. 获取大小 getSize
  4. 获取栈顶 getTop 或者队头 getFront 元素
  5. 入队或者压栈 push
  6. 出队或出栈 pop
  7. 遍历 show

一、栈

1. 示意图:

在这里插入图片描述

  • 特点:
  1. 后入先出(LIFO)的顺序表
  2. 最先入栈的元素在栈底(Bottom),最后入栈的元素在栈顶(Top)
  3. 插入和删除操作只能在末端(栈顶 Top)进行
  • 以下分别使用切片和链表实现了栈:

2. 切片实现:

package main

import (
	"fmt"
)

//栈  通过切片实现
//实现栈模型的结构体
type sliceStack struct {
	dataStack []interface{} //存储栈数据的切片
	size      int           //栈中元素个数
}

//创建
func newSliceStack() *sliceStack {
	return &sliceStack{dataStack: make([]interface{}, 0)}
}

//判断栈是否为空
func (s *sliceStack) isEmpty() bool {
	return s.size == 0
}

//栈的大小
func (s *sliceStack) getSize() int {
	return s.size
}

//获取栈顶元素
func (s *sliceStack) getTop() interface{} {
	if s.isEmpty() {
		return nil
	}
	return s.dataStack[s.size-1]
}

//压栈 push
func (s *sliceStack) push(data interface{}) {
	s.dataStack = append(s.dataStack, data)
	s.size++
}

func (s *sliceStack) pushs(data ...interface{}) {
	for _, v := range data {
		s.push(v)
	}
}

//出栈 pop
func (s *sliceStack) pop() (data interface{}) {
	if s.isEmpty() {
		fmt.Println("空栈!")
		return nil
	}
	s.size--
	data = s.dataStack[s.size]
	s.dataStack = s.dataStack[:s.size]

	return data
}

//显示栈元素
func (s *sliceStack) showStack() {
	if s.isEmpty() {
		fmt.Print("空栈!")
		return
	}
	fmt.Println("当前栈元素如下:")
	for k := range s.dataStack {
		fmt.Println("index:", s.size-1-k, "val:", s.dataStack[s.size-1-k])
	}

}

func main() {
	var stack = newSliceStack()
	if stack.isEmpty() {
		fmt.Println("stack is empty!")
	} else {
		fmt.Println("stack size:", stack.size)
	}

	fmt.Println("压栈")
	stack.push("data1")
	stack.push("data2")
	stack.push("data3")
	stack.pushs(4, 5, "6")

	stack.showStack()
	fmt.Println("stack size:", stack.size)
	fmt.Println("stack top:", stack.getTop())

	fmt.Println("出栈:", stack.pop())
	stack.showStack()
	fmt.Println("stack size:", stack.size)
	fmt.Println("stack top:", stack.getTop())
}

结果:
在这里插入图片描述

3. 链表实现:

  • 入栈出栈需要移动top指针
  • 入栈同链表头插法
package main

import "fmt"

//栈  链表实现

type Node struct {
	data interface{}
	next *Node
}

type Stack struct {
	top  *Node //栈顶指针
	size int
}

//创建
func newLinkListStack() *Stack {
	return &Stack{}
}

//判断是否为空
func (s *Stack) isEmpty() bool {
	return s.size == 0
}

//栈的大小
func (s *Stack) getSize() int {
	return s.size
}

//获取栈顶元素
func (s *Stack) getTop() interface{} {
	if s.isEmpty() {
		return nil
	}
	return s.top.data
}

//压栈 push  操作同链表的 头插法
func (s *Stack) push(val interface{}) {
	node := Node{data: val, next: s.top} //第一次压栈时 s.top=nil 也就是说第一个元素的next指向nil
	s.top = &node
	s.size++
}

func (s *Stack) pushs(vals ...interface{}) {
	for _, v := range vals {
		s.push(v)
	}
}

//出栈 pop
func (s *Stack) pop() interface{} {
	if s.isEmpty() {
		fmt.Println("空栈!")
		return nil
	}
	val := s.top.data
	s.top = s.top.next
	s.size--

	return val
}

//显示栈元素
func (s *Stack) showStack() {
	if s.isEmpty() {
		fmt.Println("空栈!")
		return
	}
	fmt.Println("当前栈元素如下:")
	topTemp := s.top
	index := s.size
	for ; topTemp != nil; index-- {
		fmt.Println("index:", index, "val:", topTemp.data)
		topTemp = topTemp.next
	}
	return
}

func main() {
	var stack = newLinkListStack()
	if stack.isEmpty() {
		fmt.Println("stack is empty!")
	} else {
		fmt.Println("stack size:", stack.size)
	}

	fmt.Println("压栈")
	stack.push("data1")
	stack.push("data2")
	stack.push("data3")
	stack.pushs(4, 5, "6")

	stack.showStack()
	fmt.Println("stack size:", stack.size)
	fmt.Println("stack top:", stack.getTop())

	fmt.Println("出栈:", stack.pop())
	stack.showStack()
	fmt.Println("stack size:", stack.size)
	fmt.Println("stack top:", stack.getTop())
}

结果:
在这里插入图片描述

二、队列

1. 示意图:

在这里插入图片描述

  • 特点
  1. 先进先出(FIFO)的顺序表
  2. 只能从队尾(tear)入队
  3. 只能出队头(front)出队
  • 以下分别使用切片和链表实现了栈:

2. 切片实现:

package main

import "fmt"

//队列 切片实现
type sliceQueue struct {
	dataQueue []interface{} //存储队列数据的切片
	size      int           //队列中元素个数
}

//创建
func newSliceQueue() *sliceQueue {
	return &sliceQueue{}
}

//判空
func (s *sliceQueue) isEmpty() bool {
	return s.size == 0
}

//获取大小
func (s *sliceQueue) getSize() int {
	return s.size
}

//获取队头数据
func (s *sliceQueue) getFront() interface{} {
	if s.isEmpty() {
		fmt.Println("空队列!")
		return nil
	}
	return s.dataQueue[0]
}

//入队
func (s *sliceQueue) push(val interface{}) {
	s.dataQueue = append(s.dataQueue, val)
	s.size++
}

func (s *sliceQueue) pushs(vals ...interface{}) {
	for _, v := range vals {
		s.push(v)
	}
}

//出队
func (s *sliceQueue) pop() interface{} {
	if s.isEmpty() {
		fmt.Println("空队列!")
		return nil
	}
	s.size--
	val := s.dataQueue[0]
	s.dataQueue = s.dataQueue[1:]

	return val
}

//显示队列元素
func (s *sliceQueue) showQueue() {
	if s.isEmpty() {
		fmt.Println("空队列!")
		return
	}
	fmt.Println("当前队列元素如下:")
	for k := range s.dataQueue {
		fmt.Println("index:", k, "val:", s.dataQueue[k])
	}
}
func main() {
	var queue = newSliceQueue()
	if queue.isEmpty() {
		fmt.Println("queue is empty!")
	} else {
		fmt.Println("queue size:", queue.size)
	}

	fmt.Println("入队")
	queue.push("data1")
	queue.push("data2")
	queue.push("data3")
	queue.pushs(4, 5, "6")

	queue.showQueue()
	fmt.Println("queue size:", queue.size)
	fmt.Println("queue front:", queue.getFront())

	fmt.Println("出队:", queue.pop())
	queue.showQueue()
	fmt.Println("queue size:", queue.size)
	fmt.Println("queue front:", queue.getFront())
}

结果:
在这里插入图片描述

3. 链表实现:

  • 出队移动队头front
  • 入队移动队尾tear,同链表尾插法
package main

import "fmt"

//队列 链表实现

type Node struct {
	data interface{}
	next *Node
}

type Queue struct {
	front *Node //队头指针
	tear  *Node //队尾指针
	size  int
}

//创建
func newLinkListQueue() *Queue {
	return &Queue{}
}

//判空
func (q *Queue) isEmpty() bool {
	return q.size == 0
}

//获取队列大小
func (q *Queue) getSize() int {
	return q.size
}

//获取队头数据
func (q *Queue) getFront() interface{} {
	if q.isEmpty() {
		fmt.Println("空队列!")
		return nil
	}
	return q.front.data
}

//入队 链表尾插法
func (q *Queue) push(val interface{}) {
	node := Node{data: val}
	if q.isEmpty() {
		q.front = &node //队头
		q.tear = &node  //队尾
	}

	q.tear.next = &node
	q.tear = &node
	q.size++
}

func (q *Queue) pushs(vals ...interface{}) {
	for _, v := range vals {
		q.push(v)
	}
}

//出队
func (q *Queue) pop() interface{} {
	if q.isEmpty() {
		fmt.Println("空队列!")
		return nil
	}
	val := q.front.data
	q.front = q.front.next
	//释放出队节点的任务交给GC
	q.size--
	return val
}

//显示队列元素
func (q *Queue) showQueue() {
	if q.isEmpty() {
		fmt.Println("空队列!")
		return
	}
	tailTemp := q.front
	for i := 1; tailTemp != nil; i++ {
		fmt.Println("index:", i, "val:", tailTemp.data)
		tailTemp = tailTemp.next
	}
	return
}
func main() {
	var queue = newLinkListQueue()
	if queue.isEmpty() {
		fmt.Println("queue is empty!")
	} else {
		fmt.Println("queue size:", queue.size)
	}

	fmt.Println("入队")
	queue.push("data1")
	queue.push("data2")
	queue.push("data3")
	queue.pushs(4, 5, "6")

	queue.showQueue()
	fmt.Println("queue size:", queue.size)
	fmt.Println("queue front:", queue.getFront())

	fmt.Println("出队:", queue.pop())
	queue.showQueue()
	fmt.Println("queue size:", queue.size)
	fmt.Println("queue front:", queue.getFront())
}

结果:
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值