8-stack

Features : Linear tables with limited operations, only allowing data to be inserted and deleted at one end, last in first out.

Arrays or linked lists can indeed replace stacks. However, specific data structures are abstractions of specific scenarios. Moreover, arrays or linked lists expose too many operating interfaces. The operation is indeed flexible and free, but it is relatively uncontrollable when used. Naturally It's more error-prone.

 

The stack mainly includes two operations, push-in and push-out.

The stack implemented with an array is called a sequential stack ;

The stack implemented with a linked list is called a chained stack ;

 

Time complexity O (1) , O (n) in individual cases, such as automatic expansion, complete data copy.

The space complexity is O (1) , and only one or two temporary variable storage spaces are needed for stacking and unstacking.

What we mean by time complexity is the additional storage space required for the algorithm to run in addition to the original data storage space.

 

Dynamically expanding stack

You only need the bottom layer to rely on an array that supports dynamic expansion. When the stack is full, we apply for a larger array and move the original data to the new array.

 

Time complexity analysis:

When the stack space is not enough, we re-apply for an array that is twice the original size;

In order to simplify the analysis, it is assumed that there are only stack operations and no stack operations;

Define a push operation that does not involve memory movement as a simple-push operation, time complexity O (1)

 

If the current stack size is K and it is full, when there is new data to be added to the stack, you need to reapply for twice the size of the memory, and do the move operation of K data, and then add to the stack. However, for the next K-1 stacking operations, we do not need to reapply for memory and move data, so these K-1 stacking operations only need a simple-push operation to complete.

These K stack operations involve a total of K data movements and K simple-push operations. The K data movements are evenly distributed to K stacking operations, and each stacking operation only requires one data movement and one simple-push operation. By analogy, the amortized time complexity of the stack operation is O (1).

Sequential stack implementation:

/*
基于数组实现的栈
*/

type ArrayStack struct {
	//数据
	data []interface{}
	//栈顶指针
	top int
}

func NewArrayStack() *ArrayStack {
	return &ArrayStack{
		data: make([]interface{}, 0, 32),
		top:  -1,
	}
}

func (this *ArrayStack) IsEmpty() bool {
	if this.top < 0 {
		return true
	}
	return false
}

func (this *ArrayStack) Push(v interface{}) {
	if this.top < 0 {
		this.top = 0
	} else {
		this.top += 1
	}

	if this.top > len(this.data)-1 {
		this.data = append(this.data, v)
	} else {
		this.data[this.top] = v
	}
}

func (this *ArrayStack) Pop() interface{} {
	if this.IsEmpty() {
		return nil
	}
	v := this.data[this.top]
	this.top -= 1
	return v
}

func (this *ArrayStack) Top() interface{} {
	if this.IsEmpty() {
		return nil
	}
	return this.data[this.top]
}

func (this *ArrayStack) Flush() {
	this.top = -1
}

func (this *ArrayStack) Print() {
	if this.IsEmpty() {
		fmt.Println("empty statck")
	} else {
		for i := this.top; i >= 0; i-- {
			fmt.Println(this.data[i])
		}
	}
}

Chain stack implementation:

/*
基于链表实现的栈
*/
type node struct {
	next *node
	val  interface{}
}

type LinkedListStack struct {
	//栈顶节点
	topNode *node
}

func NewLinkedListStack() *LinkedListStack {
	return &LinkedListStack{nil}
}

func (this *LinkedListStack) IsEmpty() bool {
	if this.topNode == nil {
		return true
	}
	return false
}

func (this *LinkedListStack) Push(v interface{}) {
	this.topNode = &node{next: this.topNode, val: v}
}

func (this *LinkedListStack) Pop() interface{} {
	if this.IsEmpty() {
		return nil
	}
	v := this.topNode.val
	this.topNode = this.topNode.next
	return v
}

func (this *LinkedListStack) Top() interface{} {
	if this.IsEmpty() {
		return nil
	}
	return this.topNode.val
}

func (this *LinkedListStack) Flush() {
	this.topNode = nil
}

func (this *LinkedListStack) Print() {
	if this.IsEmpty() {
		fmt.Println("empty stack")
	} else {
		cur := this.topNode
		for nil != cur {
			fmt.Println(cur.val)
			cur = cur.next
		}
	}
}

application:

1. Browser forward and backward;

2. Function call;

3. Expression evaluation;

4. Matching brackets;

 

 

 

Published 127 original articles · Likes 24 · Visits 130,000+

Guess you like

Origin blog.csdn.net/Linzhongyilisha/article/details/99557411