一个数组实现双栈

357 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第15天,点击查看活动详情

栈的概念

栈是一个数据结构,特色是"先入先出"。这种数据结构特别适合用来实现函数。所以我们一般说,函数栈,函数栈。

用一个数组来实现栈

我们假设现在的数据类型只有int,也就是说,我们存取的都是整数。那么就可以用一个数组来实现栈。

一开始的时候,数组是空的,我们还用到一个额外的变量top来存储当前栈顶在哪里。

  • 对于push操作,我们存入数据之后,我们就将栈顶变量top++
  • 对于pop操作,我们取出数据之后,我们就将栈顶变量top--
  • push操作之前,需要判断栈是否已经满了
  • pop操作之间,需要判断栈是否已经空了

根据上面的逻辑,很容易就能用一个数组来实现栈。

双栈的概念

双栈就是两个独立的栈,两个栈的 push pop, 互不影响。

这种数据结构可以用来实现一个队列数据结构

用一个数组来实现双栈

简单实现

我们知道一个数组可以用来实现一个栈,那么思路就是:

  • 将这个数组分成前后两个部分,前面实现一个栈,后面实现一个栈

缺点:

不能充分利用空间。

比如说,一个长度是6的数组,本来总的可以存储6个元素的。

现在往第一个栈里只能存三个,当我继续push第一个栈的时候,就出错了。

而此时,数组还剩三个空闲位置,所以不能充分利用空间。

优化实现

两个栈各自有自己的栈顶变量top1和top2

  • 第一个栈从数组开头往中间push,top1++
  • 第二个栈从数组结尾往中间push,top2--

两个栈push的时候,可以计算top1和top2之间的空余,来判断栈是否满了。

优化实现示例代码(Golang)

type DualStack struct {
	arr        []int
	top1, top2 int
	length     int
}

func NewDualStack(length int) *DualStack {
	ds := new(DualStack)
	ds.arr = make([]int, length)
	ds.length = length
	ds.top1 = -1
	ds.top2 = ds.length
	return ds
}

// 往第一个栈 push value
func (dualStack *DualStack) push1(value int) {
	if dualStack.top1 < dualStack.top2-1 {
		dualStack.top1++
		dualStack.arr[dualStack.top1] = value
	} else {
		panic("stack 1 over flow")
	}
}

// 往第二个栈 push value
func (dualStack *DualStack) push2(value int) {
	if dualStack.top1 < dualStack.top2-1 {
		dualStack.top2--
		dualStack.arr[dualStack.top2] = value
	} else {
		panic("stack 2 over flow")
	}
}

// 第一个栈的 pop 操作
func (dualStack *DualStack) pop1() int {
	if dualStack.top1 >= 0 {
		var value = dualStack.arr[dualStack.top1]
		dualStack.top1--
		return value
	} else {
		panic("stack 1 under flow")
	}
}

// 第二个栈的 pop 操作
func (dualStack *DualStack) pop2() int {
	if dualStack.top2 < dualStack.length {
		var value = dualStack.arr[dualStack.top2]
		dualStack.top2++
		return value
	} else {
		panic("stack 1 under flow")
	}
}