Pilha
A pilha é uma tabela linear com Last In Fast Out. É limitada a inserir e excluir tabelas lineares no final da tabela.A extremidade que permite a inserção e exclusão é chamada de topo da pilha.
Diagrama de pilha
Variação stack-in e out-of-stack
Os elementos da pilha mais avançada não são necessariamente removidos por último, porque a pilha restringe as posições de inserção e exclusão da tabela linear e não limita o tempo para os elementos entrarem e saírem, ou seja, quando nem todos os elementos são colocados na pilha , O elemento que vai primeiro também pode ser exibido, desde que seja o elemento do topo da pilha.
Por exemplo, os elementos de número inteiro 1, 2 e 3 são colocados na pilha, por sua vez, e a ordem de empilhamento pode ser:
- O primeiro tipo, 1, 2, 3 dentro, então 3, 2, 1, fora, a ordem de empilhamento 321
- O segundo tipo, 1 entra, 1 sai, 2 entra, 2 sai, 3 entra, 3 sai, fora da ordem de pilha 123
- O terceiro tipo, 1 dentro, 2 dentro, 2 fora, 1 fora, 3 dentro, 3 fora, fora da ordem de pilha 213
- O quarto tipo, 1 entra, 1 sai, 2 entra, 3 entra, 3 sai, 2 sai, fora da ordem da pilha 132
- O quinto tipo, 1 dentro, 2 dentro, 2 fora, 3 dentro, 3 fora, 1 fora, empilhar sequência 231
Existem 5 ordens de empilhamento para 3 elementos
Estrutura de armazenamento sequencial da pilha
A pilha é um caso especial da tabela linear. A estrutura de armazenamento sequencial da pilha é, na verdade, uma simplificação do armazenamento sequencial da tabela linear, chamada pilha sequencial. A estrutura da pilha sequencial é a seguinte:
typedef int ElemType; /* ElemType类型根据实际情况而定,这里假设为int */
typedef struct Stack
{
Elemtype *elem;
int top; /* 用于栈顶指针 */
int stacksize; /* 栈的空间大小 */
}SqStack;
Inicialização da pilha sequencial
- Abra o espaço inicial
- Inicializar no topo
- Initialize stacksize
void InitStack(PStack st)
{
assert(st != NULL); //确保st不为空指针
st->elem = (ElemType*)malloc(sizeof(ElemType)*STACK_INIT_SIZE);
st->stacksize = STACK_INIT_SIZE;
st->top = -1;
}
Expansão de pilha sequencial
- Abra espaço
- Atualizar tamanho da pilha
static void AppendStack(PStack st)//扩容
{
assert(st != NULL);
st->elem = (ElemType*)realloc(st->elem, st->stacksize + sizeof(ElemType)*STACKINCREMENT);
st->stacksize += STACKINCREMENT;
}
Push da pilha sequencial (Push)
Para a operação push, três coisas são realmente feitas
- Julgue que a pilha está cheia
- Ponteiro superior da pilha mais um
- Atribuir o elemento recém-inserido ao espaço superior da pilha
void Push(PStack st, ElemType val)
{
assert(st != NULL);
if (st->top == st->stacksize) //判断栈满
{
AppendStack(st);
}
st->top++; //栈顶指针加一
st->elem[st->top] = val; //将新插入元素赋值给栈顶空间
}
Pop da pilha sequencial (Pop)
Se a pilha não estiver vazia, coloque o elemento superior da pilha em e e diminua o ponteiro superior em um
int Pop(PStack st, ElemType *e) // 若栈不为空,则弹出栈顶元素给e,栈顶指针减一
{
assert(st != NULL);
if (st->top >= 0)
{
*e = st->elem[st->top];
st->top--;
return 1;
}
return 0;
}
Destruição da pilha sequencial
void Destory(PStack st)
{
assert(st != NULL);
free(st->elem);
st->elem = NULL;
st->stacksize = 0;
}
Esvaziamento de pilha sequencial
void Clear(PStack st)
{
assert(st != NULL);
st->top = 0;
}
A pilha de sequência está vazia
bool IsEmpty(PStack st)
{
assert(st != NULL);
return st->top == -1;
}
Obtenha o elemento superior da pilha sequencial
ElemType GetTop(PStack st)
{
assert(st != NULL);
return st->elem[st->top];
}
Estrutura de armazenamento em cadeia da pilha
A estrutura de armazenamento em cadeia da pilha deve implementar a pilha em um modo de lista vinculada, denominado pilha em cadeia. A
pilha em cadeia coloca o topo da pilha no topo da lista única vinculada, conforme mostrado na figura a seguir: A
estrutura da pilha em cadeia é a seguinte:
typedef struct StackNode // 栈结点
{
ElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack // 链栈
{
LinkStackPtr top;
int count;
}LinkStack;
A maioria das operações da pilha em cadeia são semelhantes às de uma lista unida individualmente, exceto para inserções e exclusões.
Empurrar a pilha de corrente (Empurrar)
Supondo que o novo nó s cujo valor do elemento é e deve ser colocado na pilha, e top é o ponteiro do topo da pilha, o diagrama esquemático de empurrar para a pilha é o seguinte:
- Atribuir o elemento do topo da pilha atual ao sucessor imediato do novo nó
- Atualize o ponteiro superior da pilha para apontar para o novo elemento
Status Push(LinkStack *LS, ElemType e)
{
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StacNode));
s->data = e;
s->next = LS->top; //将当前的栈顶元素赋值给新节点的直接后继
LS->top = s; //更新栈顶指针,使其指向新元素
LS->count++;
return OK;
}
Pop da pilha de corrente (Pop)
Suponha que a variável p seja usada para armazenar o nó superior da pilha a ser excluída
- Atribua o nó superior da pilha a p, conforme mostrado na etapa 1
- O ponteiro do topo da pilha se move um bit para baixo, conforme mostrado na etapa 2 abaixo
- Nó de liberação p
//若栈不为空,则删除栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status Pop(LinkStack *S, ElemType *e)
{
LinkStackPtr p;
if(StackEmpty(*S))
{
return ERROR;
}
*e = S->top->next;
p = S->top; //将栈顶结点赋值给p,如上图步骤1
S->top = S->top->next; //栈顶指针下移一位,如上图步骤2
free(p); //释放结点p
S->count--;
return OK;
}
Comparação de pilha sequencial e pilha de cadeia
A complexidade de tempo de empilhamento e empilhamento de pilha sequencial e pilha em cadeia é O (1). Para desempenho de espaço, a pilha sequencial precisa determinar um comprimento fixo com antecedência, o que pode causar um desperdício de espaço de memória, mas sua vantagem é que é fácil de acessar e localizar, enquanto a pilha em cadeia requer que cada elemento tenha um campo de ponteiro, que também Algum overhead de memória é adicionado, mas o comprimento da pilha pode ser desenvolvido de forma flexível. Portanto, a diferença entre eles é como a diferença entre uma lista sequencial e uma lista vinculada.
Se a mudança de elementos durante o uso da pilha for imprevisível, às vezes pequena, às vezes grande, então é melhor usar uma pilha em cadeia; por outro lado, se suas mudanças estiverem dentro de uma faixa controlável, você pode usar uma pilha sequencial