El entrevistador me preguntó qué es una "pila" y dibujé 10 dibujos para explicar


Autor | Li Xiaoyao

Fuente | La tecnología hace los sueños más grandes (ID: TechDreamer)

Concepto de pila

La pila es una estructura de datos que se limita a operar solo en un extremo de la tabla, y la pila es una estructura de datos de primero en entrar, último en salir. El extremo que permite la operación se llama la parte superior de la pila y el que no está permitido se llama la parte inferior de la pila, como se muestra en la siguiente figura Mostrar:

Antes de hablar sobre la lista vinculada, solo podemos operar en el nodo final de su lista vinculada, y solo insertar un nuevo nodo y eliminar el último nodo, y una 'lista vinculada' tan restrictiva ', es lo que llamamos la pila.

Al igual que un callejón sin salida, solo hay una salida, como se muestra en la figura, hay un concepto:


Diseño de nodo de la pila

La pila se divide en una pila de matriz y una pila de lista enlazada. Las diferencias son las siguientes:

  • La pila de arreglos usa arreglos para simular funciones, lo cual es más rápido y conveniente;

  • La pila de lista enlazada está diseñada con la idea de lista enlazada, que es relativamente difícil de implementar, pero es estable y no es fácil cometer errores;

  • La pila de lista enlazada se divide en pila de lista enlazada estática y pila de lista enlazada dinámica. La diferencia es la siguiente:

  • No se permite que el tamaño del espacio de la pila dada de la pila de lista enlazada estática exceda el almacenamiento de elementos que excedan el tamaño de datos dado;

  • La pila dinámica se crea utilizando el método de creación automática de espacio. Siempre que cumpla con los requisitos de hardware de la máquina y el control del compilador, en teoría es excelente.

Pila de matriz

En realidad, utiliza un espacio de almacenamiento continuo para almacenar los elementos de datos en la pila, que tiene las siguientes características:

  1. El espacio de almacenamiento que ocupan los elementos debe ser continuo, la continuidad aquí se refiere a la continuidad lógica, no a la continuidad física.

  2. La ubicación de los elementos en el espacio de almacenamiento se almacena en un orden lógico.

Tomemos un ejemplo: dado que todos los subíndices de la matriz del lenguaje C comienzan con 0, y el tamaño del espacio requerido para el uso de la pila es difícil de estimar, al inicializar la pila vacía, no se debe establecer la capacidad máxima de la pila.

Primero establecemos una capacidad básica para la pila, durante el proceso STACK_, cuando el espacio de la pila no es suficiente, se expandirá gradualmente.

Establezca 2 constantes, STACK_INIT_SIZE (cantidad de asignación inicial de espacio de almacenamiento) y STACK_INCREMENT (incremento de asignación de espacio de almacenamiento), la definición de macro es la siguiente:

#define STACK_INIT_SIZE 1000 //数值可以根据实际情况确定
#define STACK_INCREMENT 10   //数值可以根据实际情况确定

La definición de pila es la siguiente:

typedef struct      
{
    void *base; 
    void *top;
    int stackSize;
} SqSTACK;

  • base representa el puntero inferior de la pila

  • top representa el puntero superior de la pila

  • stackSize representa la capacidad máxima actualmente disponible para la pila

Si el valor de base es NULL, significa que la estructura de la pila no existe, el valor inicial de top apunta a la parte inferior de la pila, es decir, top = base;

Siempre que se inserta un nuevo elemento, el puntero superior se incrementa en 1; de lo contrario, se reduce en 1. El puntero superior de la pila no vacía siempre está encima del siguiente puntero del elemento superior de la pila .

La relación entre los elementos de datos y el puntero en la parte superior de la pila se muestra en la siguiente figura:


Pila de lista vinculada

Tomamos la pila de lista enlazada dinámica de la pila de lista enlazada como ejemplo para diseñar la pila.

El primero es el nodo de la pila. Se diseñan dos estructuras. Un nodo de estructura representa el nodo, que contiene un campo de datos y el siguiente puntero, como se muestra en la figura:

Nodo

Entre ellos, los datos representan datos y el siguiente puntero representa el siguiente puntero, que apunta al siguiente nodo, y cada nodo está vinculado a través del siguiente puntero.

El siguiente es el enfoque de nuestro diseño. Para este diseño restrictivo, necesitamos agregar una estructura adicional, que incluye un puntero en la parte superior que siempre apunta a la parte superior de la pila y un contador para registrar el número de elementos.

Su función principal es establecer los punteros de los elementos de operación permitidos y determinar cuándo la pila está vacía, como se muestra en la figura:

Apilar

Aquí utilizo una combinación de top y count. El código se puede expresar como:

//栈的结点设计
//单个结点设计,数据和下一个指针
typedef struct node     
{
    int data; 
    struct node *next;
} Node;

Utilice los nodos anteriores para crear una pila, que se divide en un puntero superior al nodo principal y cuenta para contar.

typedef struct stack    
{
    Node *top;
    int count;
} Link_Stack;


La operación básica de la pila-en la pila (empujar la pila)

La secuencia básica de apilamiento se puede mostrar en la siguiente figura:

En la operación push, solo necesitamos encontrar el espacio apuntado por top, crear un nuevo nodo, apuntar el siguiente puntero del nuevo nodo al espacio apuntado por el puntero superior, y luego transferir el puntero superior y apuntar al nuevo Nodo, esta es la operación de inserción.

El código se puede expresar como:

//入栈 push
Link_Stack *Push_stack(Link_Stack *p, int elem)
{
    if (p == NULL)
        return NULL;
    Node *temp;
    temp=(Node*)malloc(sizeof(Node));
    //temp = new Node;
    temp->data = elem;
    temp->next = p->top;
    p->top = temp;
    p->count++;
    return p;
}


栈的基本操作—出栈

La operación pop es una operación que se repite cuando la pila no está vacía. Debe realizar una operación nula, eliminar el elemento en la parte superior de la pila y mover el puntero superior y el siguiente hacia abajo.

El código se puede expresar como:

//出栈 pop
Link_Stack *Pop_stack(Link_Stack *p)
{
    Node *temp;
    temp = p->top;
    if (p->top == NULL)
    {
        printf("错误:栈为空");
        return p;
    }
    else
    {
        p->top = p->top->next;
        free(temp);
        //delete temp;
        p->count--;
        return p;
    }
}


栈的基本操作—遍历

Esto es muy común y también es un medio necesario para depurar.

El recorrido de la pila es relativamente complicado, debido a la naturaleza especial de la pila, solo permite operaciones en un extremo, por lo que las operaciones de recorrido son siempre en orden inverso.

Para describir brevemente, el proceso es, cuando la pila no está vacía, acceder hacia abajo desde el elemento superior de la pila una vez hasta que el puntero apunte a un vacío (es decir, al final de la pila).

El código se puede expresar como:

//遍历栈:输出栈中所有元素
int show_stack(Link_Stack *p)
{
    Node *temp;
    temp = p->top;
    if (p->top == NULL)
    {
        printf("");
        printf("错误:栈为空");
        return 0;
    }
    while (temp != NULL)
    {
        printf("%d\t", temp->data);
        temp = temp->next;
    }
    printf("\n");
    return 0;
}


Realización de código de matriz de pila y lista vinculada de pila

Finalmente, usamos código para ayudarnos a comprender:

Matriz de pila

La pila de matrices es una forma más rápida de simular la implementación de la pila, no hablaremos de eso aquí.

La simulación significa que en lugar de utilizar un diseño de lista enlazada real, se utiliza una matriz para las operaciones de simulación.

En otras palabras, esta es una operación de tipo simulación, que puede ayudarnos rápidamente a construir el código, analizar el proceso y la implementación correspondiente es más conveniente.

El código es el siguiente:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 10000

//结点设计
typedef struct stack{
    int data[maxn];
    int top;
}stack;

//创建
stack *init(){
    stack *s=(stack *)malloc(sizeof(stack));
    if(s==NULL){
        printf("分配内存空间失败");
        exit(0);
    }
    memset(s->data,0,sizeof(s->data));
    //memset操作来自于库文件string.h,其表示将整个空间进行初始化
    //不理解可以查阅百度百科https://baike.baidu.com/item/memset/4747579?fr=aladdin
    s->top=0;     //栈的top和bottom均为0(表示为空)
    return s;
}

//入栈push
void push(stack *s,int data){
    s->data[s->top]=data;
    s->top++;
}

//出栈pop
void pop(stack *s){
    if(s->top!=0){
        s->data[s->top]=0;  //让其回归0模拟表示未初始化即可
        s->top--;
    }
}

//模拟打印栈中元素
void print_stack(stack *s){
    for(int n=s->top-1;n>=0;n--){
        printf("%d\t",s->data[n]);
    }
    printf("\n");   //习惯性换行
}

int main(){
    stack *s=init();
    int input[5]={11,22,33,44,55};  //模拟五个输入数据
    for(int i=0;i<5;i++){
        push(s,input[i]);
    }
    print_stack(s);
    /
    pop(s);
    print_stack(s);
    return 0;
}

Los resultados de la compilación son los siguientes:

Lista de pila

#include <stdio.h>
#include <stdlib.h>
//栈的结点设计
//单个结点设计,数据和下一个指针
typedef struct node     
{
    int data; 
    struct node *next;
} Node;
//利用上面的结点创建栈,分为指向头结点的top指针和计数用的count
typedef struct stack    
{
    Node *top;
    int count;
} Link_Stack;

//创建栈
Link_Stack *Creat_stack()
{
    Link_Stack *p;
    //p = new Link_Stack;
    p=(Link_Stack*)malloc(sizeof(Link_Stack));
    if(p==NULL){
        printf("创建失败,即将退出程序");
        exit(0);
    }
 else
 {printf("创建成功\n");
 }
    p->count = 0;
    p->top = NULL;
    return p;
}

//入栈 push
Link_Stack *Push_stack(Link_Stack *p, int elem)
{
    if (p == NULL)
        return NULL;
    Node *temp;
    temp=(Node*)malloc(sizeof(Node));
    //temp = new Node;
    temp->data = elem;
    temp->next = p->top;
    p->top = temp;
    p->count++;
    return p;
}

//出栈 pop
Link_Stack *Pop_stack(Link_Stack *p)
{
    Node *temp;
    temp = p->top;
    if (p->top == NULL)
    {
        printf("错误:栈为空");
        return p;
    }
    else
    {
   printf("\npop success");
        p->top = p->top->next;
        free(temp);
        //delete temp;
        p->count--;
        return p;
    }
}

//遍历栈:输出栈中所有元素
int show_stack(Link_Stack *p)
{
    Node *temp;
    temp = p->top;
    if (p->top == NULL)
    {
        printf("");
        printf("错误:栈为空");
        return 0;
    }
    while (temp != NULL)
    {
        printf("%d\t", temp->data);
        temp = temp->next;
    }
    printf("\n");
    return 0;
}

int main()
{ //用主函数测试一下功能
 int i;
    Link_Stack *p;
    p = Creat_stack();
    int n = 5;
    int input[6] = {10,20,30,40,50,60};
    /以依次入栈的方式创建整个栈//
    for(i=0;i<n;i++){
        Push_stack(p, input[i]);
    }
    show_stack(p);
    出栈///
    Pop_stack(p);
    show_stack(p);
    return 0;
}

El resultado de la compilación es el siguiente:


Resumen sobre la pila

Stack-It es una tabla lineal con operaciones limitadas. Se puede usar en la conversión de sistemas numéricos, verificación de coincidencia de corchetes, evaluación de expresiones, etc., y puede resolver problemas de manera más simple.

Eso es todo para los conceptos básicos de la pila de hoy. ¡Nos vemos en el próximo número!

更多精彩推荐
☞CSDN 今日发布开源代码托管平台 CODE.CHINA
☞乘“峰”而上,聚生态之力共创软件产业新未来

☞腾讯微博即将关停,十年了,你用过吗?
☞Cognitive Inference:认知推理下的常识知识库资源、常识推理测试评估与中文实践项目索引
☞超详细 | 21张图带你领略集合的线程不安全
☞腾讯云区块链邀您参加2020腾讯全球数字生态大会
点分享点点赞点在看

Supongo que te gusta

Origin blog.csdn.net/csdnnews/article/details/108544140
Recomendado
Clasificación