8 piles

Caractéristiques : Tableaux linéaires avec des opérations limitées, permettant uniquement l'insertion et la suppression de données à une extrémité, du dernier entré au premier sorti.

Les tableaux ou les listes liées peuvent en effet remplacer les piles. Cependant, des structures de données spécifiques sont des abstractions de scénarios spécifiques. De plus, les tableaux ou les listes liées exposent trop d'interfaces de fonctionnement. Le fonctionnement est en effet flexible et gratuit, mais il est relativement incontrôlable lorsqu'il est utilisé. Naturellement C'est plus sujet aux erreurs.

 

La pile comprend principalement deux opérations, push-in et push-out.

La pile implémentée avec un tableau est appelée une pile séquentielle ;

La pile implémentée avec une liste chaînée est appelée pile chaînée ;

 

Complexité temporelle O (1) , O (n) dans des cas individuels, tels que l'expansion automatique, copie complète des données.

La complexité de l'espace est O (1) , et seuls un ou deux espaces de stockage variables temporaires sont nécessaires pour l'empilement et le désempilage.

Ce que nous entendons par complexité temporelle est l'espace de stockage supplémentaire requis pour que l'algorithme s'exécute en plus de l'espace de stockage de données d'origine.

 

Pile à expansion dynamique

Vous n'avez besoin que de la couche inférieure pour compter sur une matrice qui prend en charge l'expansion dynamique. Lorsque la pile est pleine, nous demandons un tableau plus grand et déplaçons les données d'origine vers le nouveau tableau.

 

Analyse de la complexité temporelle:

Lorsque l'espace de pile n'est pas suffisant, nous réappliquons pour un tableau qui est deux fois la taille d'origine;

Afin de simplifier l'analyse, il est supposé qu'il n'y a que des opérations de pile et aucune opération de pile;

Définir une opération push qui n'implique pas de mouvement de mémoire comme une opération simple push, complexité temporelle O (1)

 

Si la taille actuelle de la pile est K et qu'elle est pleine, lorsqu'il y a de nouvelles données à ajouter à la pile, vous devez réappliquer pour deux fois la taille de la mémoire, effectuer l'opération de déplacement des données K, puis ajouter à la pile. Cependant, pour les prochaines opérations d'empilement K-1, nous n'avons pas besoin de réappliquer pour la mémoire et de déplacer les données, donc ces opérations d'empilement K-1 n'ont besoin que d'une simple opération push pour se terminer.

Ces opérations de pile K impliquent un total de K mouvements de données et K opérations de simple pression. Les K mouvements de données sont répartis uniformément sur K opérations d'empilement, et chaque opération d'empilement ne nécessite qu'un seul mouvement de données et une seule opération push. Par analogie, la complexité temporelle amortie de l'opération de pile est O (1).

Implémentation de pile séquentielle:

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

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])
		}
	}
}

Mise en œuvre de la pile de chaînes:

/*
基于链表实现的栈
*/
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. Navigateur en avant et en arrière;

2. Appel de fonction;

3. Évaluation de l'expression;

4. Supports correspondants;

 

 

 

A publié 127 articles originaux · Aime 24 · Visites 130 000+

Je suppose que tu aimes

Origine blog.csdn.net/Linzhongyilisha/article/details/99557411
conseillé
Classement