Pila y cola de aprendizaje de estructura de datos (lenguaje C)

1. Introducción a las pilas y colas

​ Las pilas y las colas son dos estructuras lineales importantes. Desde la perspectiva de la estructura de datos, también son tablas lineales. Su particularidad es que sus operaciones básicas son un subconjunto de las tablas lineales, es decir, tablas lineales con funciones limitadas. Se llama un estructura de datos restringida.

​ Pero desde la perspectiva de los tipos de datos, no son exactamente lo mismo que las tablas lineales y, a veces, se usan como regla para administrar datos.

2. Estructura de pila

1. Introducción a la estructura de pila

​ La pila (stack) se limita a insertar o eliminar operaciones y tablas lineales solo al final de la tabla (solo un puerto puede entrar y salir de datos).Para la pila, el final y la cabecera de la tabla tienen significados especiales. La cola de la mesa se llama la parte superior de la pila, y la mesa La cabeza se llama la parte inferior de la pila , una lista vacía sin elementos se llama una pila vacía , el número de elementos alcanza la capacidad de la pila se llama una pila completa , agregar datos a la pila se llama empujar y empujar , y eliminar datos de la pila se llama sacar y sacar pila , debido a las reglas especiales de agregar y eliminar elementos de la pila, el fenómeno de que los elementos de la pila serán los primeros entrar, último en salir, denominado LIFO (Último en entrar, primero en salir).

2. Funciones de la estructura de la pila

1. Crea una pila

2. Destruye la pila

3. ¿Está vacía la pila?

4. ¿Está llena la pila?

5. Empuje en la pila

6. Salir

8. Ver el elemento superior de la pila

9. Número de elementos de la pila

​ Nota: Solo la estructura de pila secuencial necesita juzgar si la pila está llena.

3. Representación de secuencias e implementación de la estructura de pila.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TYPE int

typedef struct StackArray
{
    
    
	TYPE* base;
	int top;
	size_t cap;
}StackArray;

// 创建栈
StackArray* create_stack(size_t cap)
{
    
    
	// 之所以使用成员指针是为了兼顾笔试题
	StackArray* stack = malloc(sizeof(StackArray));
	stack->base = malloc(sizeof(TYPE)*cap);
	stack->cap = cap;
	// 初始值值决定的栈空、栈满、入栈、查看栈顶时的top的操作,
	stack->top = -1; 
	return stack;
}

// 销毁栈
void destroy_stack(StackArray* stack)
{
    
    
	free(stack->base);
	free(stack);
}

// 判断栈是否为空
bool empty_stack(StackArray* stack)
{
    
    
	// 因为top的初始值是-1
	return 0 > stack->top;
}

// 判断栈是否为满
bool full_stack(StackArray* stack)
{
    
    
	// 同上
	return stack->cap == stack->top+1;
}

// 入栈
bool push_stack(StackArray* stack,TYPE val)
{
    
    
	if(full_stack(stack))
		return false;

	// 同上
	stack->base[++stack->top] = val;
	return true;
}

// 出栈
bool pop_stack(StackArray* stack)
{
    
    
	if(empty_stack(stack))
		return false;

	stack->top--;
	return true;
}

// 计算栈元素数量
size_t size_stack(StackArray* stack)
{
    
    
	return stack->top+1;
}

// 查看栈顶
bool top_stack(StackArray* stack,TYPE* ptr)
{
    
    
	if(empty_stack(stack))
		return false;
	
	*ptr = stack->base[stack->top];
	return true;
}

int main(int argc,const char* argv[])
{
    
    
	int num;
	StackArray* stack = create_stack(10);
	for(int i=0; i<10; i++)
	{
    
    
		push_stack(stack,i);
		if(top_stack(stack,&num))
			printf("top %d\n",num);
	}
	printf("----------------------\n");
	while(!empty_stack(stack))
	{
    
    
		top_stack(stack,&num);
		printf("top %d\n",num);
		pop_stack(stack);
	}
}

Preguntas comunes de las pruebas escritas :

Evaluación de la secuencia de inserción y extracción de la pila, secuencia de inserción: 1 2 3 4 5 si la secuencia de extracción es: 1 2 3 5 4

bool push_pop_order(int* arr1,int* arr2,size_t len)
{
    
    
    StackArray* stack = create_stack(len);

    int num;
    for(int i=0,j=0; i<len; i++)
    {
    
    
        push_stack(stack,arr1[i]);
        while(top_stack(stack,&num) && num == arr2[j] && pop_stack(stack))
            j++;
    }

    return empty_stack(stack);
}

bool IsPopOrder(int* pushV, int pushVLen, int* popV, int popVLen ) 
{
    
    
    if(pushVLen != popVLen)
        return false;
    
    int stack[popVLen] , top = -1;
    for(int i=0,j=0; i<pushVLen; i++)
    {
    
    
        stack[++top] = pushV[i];
        while(top>=0 && stack[top] == popV[j])
        {
    
    
            top--;
            j++;
        }
    }
    return 0 > top;
}

bool IsPopOrder(vector<int> pushV,vector<int> popV)
{
    
    
    stack<int> s;
    for(int i=0,j=0; i<pushV.size(); i++)
    {
    
    
        s.push(pushV[i]);
        while(!s.empty() && s.top()==popV[j])
        {
    
    
            s.pop();
            j++;
        }
    }
    return s.empty();
}

4. Representación en cadena e implementación de la estructura de pila.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

typedef struct Node
{
    
    
	TYPE data;
	struct Node* next;
}Node;

Node* create_node(TYPE data)
{
    
    
	Node* node = malloc(sizeof(Node));
	node->data = data;
	node->next = NULL;
	return node;
}

typedef struct StackList
{
    
    
	Node* top;
	size_t cnt;
}StackList;

// 创建栈
StackList* create_stack(void)
{
    
    
	StackList* stack = malloc(sizeof(StackList));
	stack->top = NULL;
	stack->cnt = 0;
	return stack;
}

// 销毁栈
void destroy_stack(StackList* stack)
{
    
    
	while(NULL!=stack->top)
	{
    
    
		Node* node = stack->top;
		stack->top = node->next;
		free(node);
	}

	free(stack);
}

// 栈空
bool empty_stack(StackList* stack)
{
    
    
	return NULL == stack->top;
}

// 入栈
void push_stack(StackList* stack,TYPE data)
{
    
    
	Node* node = create_node(data);
	node->next = stack->top;
	stack->top = node;
	stack->cnt++;
}

// 出栈
bool pop_stack(StackList* stack)
{
    
    
	if(empty_stack(stack))
		return false;
	
	Node* node = stack->top;
	stack->top = node->next;
	free(node);
	stack->cnt--;
	return true;
}

// 查看栈顶
TYPE top_stack(StackList* stack)
{
    
    
	return stack->top->data;
}

// 元素数量
size_t size_stack(StackList* stack)
{
    
    
	return stack->cnt;
}

int main(int argc,const char* argv[])
{
    
    
	StackList* stack = create_stack();
	for(int i=0; i<10; i++)
	{
    
    
		push_stack(stack,i);
		if(!empty_stack(stack))
			printf("top %d\n",top_stack(stack));
	}
	printf("-------------------\n");
	while(!empty_stack(stack))
	{
    
    
		printf("top %d\n",top_stack(stack));
		pop_stack(stack);
	}
}

5. Aplicación de pila

1. La gestión de la memoria, como la memoria de pila, se denomina memoria de pila porque sigue la regla del último en entrar, primero en salir de la pila. Admite llamadas a funciones. Cuando una función pasa parámetros, empuja primero los parámetros a la memoria de pila. , y luego espera un salto.Después de dar la vuelta, los parámetros se extraen de la memoria de la pila.

2. Algoritmos especiales, tales como: conversión de bases, análisis de expresiones, resolución de laberintos.

3. Cola

1. Introducción a la cola

Es justo lo contrario de la pila. Es una tabla lineal de tipo primero en entrar, primero en salir. Tiene dos puertos para agregar y eliminar elementos. Un puerto solo puede agregar elementos, lo que se denomina ingresar a la cola. Este puerto se denomina el final de la cola, y el otro puerto Solo se puede eliminar, lo que se denomina eliminación de la cola, y el puerto se denomina cabeza del equipo.

2. Las funciones de la estructura de la cola

1. Crea una cola

2. Destruye la cola

3. ¿Está vacía la cola?

4. ¿Está llena la cola?

5. Únete al equipo

6. Salir

8. Verifique el elemento de cabecera de la cola

9. Ver los elementos al final de la cola

10. Número de elementos de cola

​ Nota: Solo la estructura de pila secuencial necesita juzgar si la cola está llena.

3. Representación en cadena e implementación de la estructura de la cola.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

typedef struct Node
{
    
    
	TYPE data;
	struct Node* next;
}Node;

Node* create_node(TYPE data)
{
    
    
	Node* node = malloc(sizeof(Node));
	node->data = data;
	node->next = NULL;
	return node;
}

typedef struct QueueList
{
    
    
	Node* front;
	Node* rear;
}QueueList;

// 创建队列
QueueList* create_queue(void)
{
    
    
	QueueList* queue = malloc(sizeof(QueueList));
	queue->front = NULL;
	queue->rear = NULL;
	return queue;
}

// 销毁队列
void destroy_queue(QueueList* queue)
{
    
    
	while(NULL != queue->front)
	{
    
    
		Node* node = queue->front;
		queue->front = node->next;
		free(node);
	}
	free(queue);
}

// 判断队列是否为空
bool empty_queue(QueueList* queue)
{
    
    
	return NULL == queue->front;
}

// 入队
void push_queue(QueueList* queue,TYPE data)
{
    
    
	Node* node = create_node(data);
	if(empty_queue(queue))
	{
    
    
		queue->front = node;
		queue->rear = node;
		return;
	}

	queue->rear->next = node;
	queue->rear = node;
}

// 出队
bool pop_queue(QueueList* queue)
{
    
    
	if(empty_queue(queue))
		return false;

	Node* node = queue->front;
	queue->front = node->next;
	free(node);
}

// 查看队头元素,调用该函数前要先判断队列是否为空,否则就会使用到空指针
TYPE front_queue(QueueList* queue)
{
    
    
	return queue->front->data;
}

// 查看队尾元素,调用该函数前要先判断队列是否为空,否则就会使用到野指针
TYPE rear_queue(QueueList* queue)
{
    
    
	return queue->rear->data;
}

// 队列元素数量
size_t size_queue(QueueList* queue)
{
    
    
	size_t size = 0;
	for(Node* n=queue->front; NULL!=n; n=n->next)
	{
    
    
		size++;
	}
	return size;
}

int main(int argc,const char* argv[])
{
    
    
	QueueList* queue = create_queue();
	for(int i=0; i<10; i++)
	{
    
    
		push_queue(queue,i);
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
	}
	printf("---------------------\n");
	while(!empty_queue(queue))
	{
    
    
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
		pop_queue(queue);
	}
}

4. Representación e implementación de cola secuencial

​ El subíndice superior de la pila secuencial aumentará a medida que los elementos se inserten en la pila y disminuirá cuando los elementos se extraigan de la pila, de modo que el espacio se pueda reutilizar, mientras que el puntero de la cola de la cola y el puntero de la cola de la cola del la cola secuencial se eliminará de la cola a medida que los elementos ingresen a la cola Ha ido aumentando y no se puede reutilizar, formando una estructura de datos de una sola vez.

Para evitar esta situación, cuando el subíndice de la cabeza de la cola y el subíndice de la cola de la cola lleguen al final del espacio de almacenamiento, encuentre una manera de "retroceder" el subíndice de la cabeza de la cola y el subíndice de la cola de la cola, es decir, trate el almacenamiento espacio de la cola secuencial como un "anillo", uso circular, por lo que las colas secuenciales también se denominan colas circulares.

Cola circular con versión de contador:

​ 1. Resuelto el problema de calcular el número de elementos

2. Resuelto el problema de juzgar si la cola está vacía o llena

​ 3. La desventaja es que se agrega un miembro, y se debe operar al crear, entrar y salir del equipo.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

typedef struct QueueArray
{
    
    
	TYPE* base;
	int front;
	int rear;
	size_t cnt;
	size_t cap;
}QueueArray;

// 创建队列
QueueArray* create_queue(size_t cap)
{
    
    
	QueueArray* queue = malloc(sizeof(QueueArray));
	queue->base = malloc(sizeof(TYPE)*cap);
	queue->cap = cap;
	queue->front = 0;
	queue->rear = -1;
	queue->cnt = 0;
	return queue;
}

// 销毁队列
void destroy_queue(QueueArray* queue)
{
    
    
	free(queue->base);
	free(queue);
}

// 判断队列是否为空
bool empty_queue(QueueArray* queue)
{
    
    
	return 0 == queue->cnt;
}

// 判断队列是否为满
bool full_queue(QueueArray* queue)
{
    
    
	return queue->cnt == queue->cap;
}

// 入队
bool push_queue(QueueArray* queue,TYPE data)
{
    
    
	if(full_queue(queue))
		return false;

	queue->rear = (queue->rear+1)%queue->cap;
	queue->base[queue->rear] = data;
	queue->cnt++;
	return true;
}

// 出队
bool pop_queue(QueueArray* queue)
{
    
    
	if(empty_queue(queue))
		return false;

	queue->front = (queue->front+1)%queue->cap;
	queue->cnt--;
	return true;
}

// 查看队头元素,判断队列是否为空
TYPE front_queue(QueueArray* queue)
{
    
    
	return queue->base[queue->front];
}

// 查看队尾元素
TYPE rear_queue(QueueArray* queue)
{
    
    
	return queue->base[queue->rear];
}

// 队列元素数量
size_t size_queue(QueueArray* queue)
{
    
    
	return queue->cnt;
}

int main(int argc,const char* argv[])
{
    
    
	QueueArray* queue = create_queue(10);
	for(int i=0; i<10; i++)
	{
    
    
		push_queue(queue,i);
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
	}
	printf("---------------------\n");
	while(!empty_queue(queue))
	{
    
    
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
		pop_queue(queue);
	}
	printf("---------------------\n");
	for(int i=0; i<10; i++)
	{
    
    
		push_queue(queue,i);
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
	}
	printf("---------------------\n");
	while(!empty_queue(queue))
	{
    
    
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
		pop_queue(queue);
	}
	destroy_queue(queue);
	return 0;
} 
Cola circular sin versión contador:

1. ¿Cómo juzgar el estado vacío de la cola?

Inicialice el subíndice de la cabeza del equipo al frente = 0, y el subíndice de la cola del equipo a la parte trasera = 0. La condición de juicio cuando la cola está vacía es al frente == atrás, pero el uso de colas aleatorias, el juicio cuando la cola está llena también es delantero == trasero.

​ La solución es dejar la última posición de la cola sin usar, de modo que el estado de la cola sea full front == rear+1;

2. ¿Cómo calcular el número de elementos de la cola?

(trasera-delantera+tapa)%tapa

3. Ver los elementos al final de la cola

​ base[(lectura-1+límite)%límite]

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define TYPE int

typedef struct QueueArray
{
    
    
	TYPE* base;
	int front;
	int rear;
	size_t cap;
}QueueArray;

// 创建队列
QueueArray* create_queue(size_t cap)
{
    
    
	QueueArray* queue = malloc(sizeof(QueueArray));
	queue->base = malloc(sizeof(TYPE)*cap+1);
	queue->cap = cap+1;
	queue->front = 0;
	queue->rear = 0;
	return queue;
}

// 销毁队列
void destroy_queue(QueueArray* queue)
{
    
    
	free(queue->base);
	free(queue);
}

// 判断队列是否为空
bool empty_queue(QueueArray* queue)
{
    
    
	return queue->front == queue->rear;
}

// 判断队列是否为满
bool full_queue(QueueArray* queue)
{
    
    
	return queue->front == (queue->rear+1)%queue->cap;
}

// 入队
bool push_queue(QueueArray* queue,TYPE data)
{
    
    
	if(full_queue(queue))
		return false;

	queue->base[queue->rear] = data;
	queue->rear = (queue->rear+1)%queue->cap;
	return true;
}

// 出队
bool pop_queue(QueueArray* queue)
{
    
    
	if(empty_queue(queue))
		return false;

	queue->front = (queue->front+1)%queue->cap;
	return true;
}

// 查看队头元素,判断队列是否为空
TYPE front_queue(QueueArray* queue)
{
    
    
	return queue->base[queue->front];
}

// 查看队尾元素
TYPE rear_queue(QueueArray* queue)
{
    
    
	return queue->base[(queue->rear - 1 + queue->cap) % queue->cap];
}

// 队列元素数量
size_t size_queue(QueueArray* queue)
{
    
    
	return (queue->rear - queue->front + queue->cap) % queue->cap;
}

int main(int argc,const char* argv[])
{
    
    
	QueueArray* queue = create_queue(10);
	for(int i=0; i<10; i++)
	{
    
    
		push_queue(queue,i);
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
	}
	printf("---------------------\n");
	while(!empty_queue(queue))
	{
    
    
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
		pop_queue(queue);
	}
	printf("---------------------\n");
	for(int i=0; i<10; i++)
	{
    
    
		push_queue(queue,i);
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
	}
	printf("---------------------\n");
	while(!empty_queue(queue))
	{
    
    
		printf("front:%d rear:%d\n",
			front_queue(queue),
			rear_queue(queue));
		pop_queue(queue);
	}
	destroy_queue(queue);
}

5. Aplicación de cola

La estructura de la cola generalmente se usa en el procesamiento comercial, como: sistema de llamadas de números bancarios, sistema de emisión de boletos 12306, procesamiento de pedidos de comercio electrónico, etc.

Supongo que te gusta

Origin blog.csdn.net/m0_62480610/article/details/126179747
Recomendado
Clasificación