Tabla de contenido
(1) El concepto básico de la pila
③ Las características de la pila
(2) La implementación secuencial de la pila.
① Pila de secuencias y sustantivos comunes
② Definición de tipo de pila secuencial
③ Operación básica de pila secuencial
Ⅱ Juicio de que la pila está vacía
Ⅴ Consigue el elemento superior de la pila
(3) Implementación de enlace de pila - cadena de pila
① Definición de cadena de pila
② Escriba la descripción de la pila encadenada
③ Operación básica de la pila de cadena
Ⅱ Juicio de que la pila está vacía
Ⅴ Consigue el elemento superior de la pila
(4) Aplicación y recursividad de la pila.
① Ejemplos básicos de aplicación de la pila
③ Forma general de recursividad
(1) El concepto básico de cola
④ Funcionamiento básico de la cola
(2) Implementación secuencial de colas
Ⅱ Implementación de Circular Queue Loop
Ⅲ Definición de tipo de cola circular
③ Operación básica de cola circular
Ⅴ Obtener el primer elemento de la cola
(3) Implementación de enlace de la cola
① Definición de cola en cadena
② Descripción del tipo de cola de cadena
③ Operación básica de cola de cadena
Ⅴ Obtener el primer elemento de la cola
(1) Estructura lógica y operaciones básicas de arreglos
(2) La estructura de almacenamiento de la matriz
① Estructura de almacenamiento —— Estructura de almacenamiento secuencial
② Fórmula de direccionamiento (principalmente almacenada en filas)
(3) almacenamiento comprimido de matriz
② Matriz especial: matriz simétrica
③ Matriz especial: matriz triangular
④ Matriz especial: matriz dispersa
1. Pila
Los archivos de encabezado que describen las implementaciones de pila y cola son los siguientes:
- Seqstack.h: La definición e implementación de la pila secuencial.
- Lkstack.h: Definición e implementación de cadena de pila.
- Sequeue.h: Definición de cola de secuencia y su implementación.
- Lkqueue.h: La definición e implementación de la cola en cadena.
(1) El concepto básico de la pila
① Definición
Stack : es una tabla lineal que solo se puede insertar y eliminar en un extremo de la tabla (el final de la tabla)
- El final (final de la tabla) que permite la inserción y eliminación se denomina la parte superior de la pila (Top)
- El otro extremo (cabecera) se llama la parte inferior de la pila (inferior)
- Cuando no hay elementos en la lista, se llama pila vacía.
- empujar : inserta un elemento en la parte superior de la pila
- Pop : elimina un elemento de la parte superior de la pila
- Las pilas y las colas se pueden considerar como tablas lineales especiales, que son tablas lineales con operaciones limitadas.
② Diagrama esquemático
【Ejemplo】 Una pila de libros o una pila de platos
【Diagrama esquemático】
③ Las características de la pila
último en entrar primero en salir:
- Los elementos de la pila se insertan en la pila en el orden de a 1 , a 2 , a 3 , ... a n , y el primer elemento que sale de la pila debe ser el elemento superior de la pila.
- En otras palabras, la modificación de la pila se realiza según el principio de último en entrar, primero en salir.
- Por lo tanto, la pila se denomina lista lineal de último en entrar, primero en salir ( LIFO ).
El propósito de la pila: a menudo se usa para almacenar temporalmente datos para ser procesados.
④ Operación básica de la pila
- Inicializar la pila: InitStack(S);
- Juzga que la pila está vacía: EmptyStack (S);
- Empujar en la pila: Empujar (S,x);
- Pop: Pop (C);
- Obtener la parte superior de la pila: GetTop(S);
(2) La implementación secuencial de la pila.
① Pila de secuencias y sustantivos comunes
- Pila secuencial , es decir, la implementación secuencial de la pila.
- Capacidad de pila : el número máximo de elementos que se pueden almacenar en la pila
- Puntero superior de la pila superior: indica la posición del elemento superior actual en la pila
- Pila vacía : cuando no hay ningún elemento en la pila, significa que la pila está vacía
- Pila llena : cuando el espacio de la matriz está lleno, se llama pila llena
- Subdesbordamiento : cuando la pila está vacía y luego requiere una operación de pila, se denomina "subdesbordamiento"
- Desbordamiento : cuando la pila está llena, se denomina "desbordamiento" si se requiere realizar una operación de inserción.
② Definición de tipo de pila secuencial
[ Tipo de pila secuencial ]
const int maxsize = 6; // 定义常量,表示栈的最大大小 typedef struct seqstack { DataType data[maxsize]; // 定义存储元素的数组 int top; // 顶部指针,指向栈顶元素下标 } SeqStk; // 定义顺序栈的结构体
【Diagrama esquemático】
【Explicación del código】
- En este código, definimos una estructura de pila secuencial
seqstack
, que contiene una matriz de elementos de almacenamientodata
y un puntero superiortop
. El puntero superiortop
se usa para indicar la posición del subíndice del elemento superior de la pila, y la matriz que almacena los elementosdata
se usa para almacenar los elementos en la pila.- Además, usamos
const int
la palabra clave para definir una constantemaxsize
, que indica el tamaño máximo de la pila, para que la constante se pueda usar convenientemente en todo el programa.- Tenga en cuenta que en el código anterior
DataType
hay un marcador de posición que indica el tipo de datos, puede reemplazarlo con el tipo de datos que necesita de acuerdo con sus necesidades reales.【ilustrar】
SeqStk *s ; /*定义一顺序栈s*/
El primer elemento de la pila de convenciones se almacena en data[1], luego:
- s -> top==0 significa que la pila de secuencias s está vacía
- s -> top==maxsize-1 significa que la pila secuencial s está llena
③ Operación básica de pila secuencial
Ⅰ Inicialización
【Código de ejemplo】
// 初始化栈 int Initstack(SeqStk* stk) { stk->top = 0; // 将栈的顶部指针设置为0,表示栈为空 return 1; // 返回1表示初始化成功 }
【Diagrama esquemático】
【Explicación del código】
1. Este código implementa una función para inicializar la pila
Initstack
.2. El parámetro de la función es un puntero a
SeqStk
la estructurastk
, a través del cual podemos manipular las propiedades relevantes de la pila.3. Los comentarios en el código explican lo que hace cada línea:
stk->top = 0;
top
Establezca el puntero superior de la pila en 0, lo que indica que la pila está vacía.return 1;
Devuelve 1, lo que indica que la pila se inicializó correctamente.4. El propósito de esta función es inicializar el puntero superior de la pila a 0 para las operaciones subsiguientes de inserción y extracción.
5. Cabe señalar que la función que devuelve 1 se puede utilizar como una señal de éxito, que se puede modificar adecuadamente según las necesidades reales.
Ⅱ Juzga que la pila está vacía
【Código de ejemplo】
// 判断栈是否为空 int EmptyStack(SeqStk* stk) { if (stk->top == 0) // 如果栈的顶部指针为0,表示栈为空 return 1; // 返回1表示栈为空 else return 0; // 返回0表示栈不为空 }
【Explicación del código】
1. Este código implementa una función para determinar si la pila está vacía
EmptyStack
.2. El parámetro de la
SeqStk
funciónstk
, a través del cual podemos obtener el puntero superior de la pilatop
.3. Los comentarios en el código explican lo que hace cada línea:
if (stk->top == 0)
Si el puntero superior de la pilatop
es 0, significa que la pila está vacía.return 1;
Devuelve 1, lo que indica que la pila está vacía.else return 0;
Si el puntero superior de la pilatop
no es 0, significa que la pila no está vacía y devuelve 0.4. El propósito de esta función es juzgar si la pila está vacía, y el juicio lógico correspondiente se puede hacer de acuerdo con el valor de retorno 0 o 1.
5. Cabe señalar que en el juicio condicional se debe utilizar para
==
expresar la relación de igualdad, no un solo=
operador de asignación.6. El valor devuelto es 1 cuando la pila está vacía, de lo contrario, el valor devuelto es 0
Ⅲ Empuje en la pila
【Código de ejemplo】
// 入栈操作 int Push(SeqStk* stk, DataType x) { /* 数据元素x进顺序栈stk */ if (stk->top == maxsize - 1) // 判断栈是否上溢(满栈) { error("栈满"); // 输出错误信息,表示栈已满 return 0; // 返回0,表示入栈失败 } else { stk->top++; // 修改栈顶指针,指向新的栈顶 stk->data[stk->top] = x; // 将元素x插入新的栈顶位置 return 1; // 返回1,表示入栈成功 } }
【Explicación del código】
1. Este código implementa una función de operación de pila
Push
.2. Los parámetros de la
SeqStk
función incluyen unstk
puntero a lax
3. Los comentarios en el código explican lo que hace cada línea:
if (stk->top == maxsize - 1)
Determinetop
si es igual amaxsize - 1
, es decir, si la pila está llena.error("栈满");
Si la pila está llena, muestra el mensaje de error "pila llena".return 0;
Devuelve 0, lo que indica que la inserción falló.stk->top++;
El puntero superior de la pilatop
aumenta , apuntando a la nueva posición superior de la pila.stk->data[stk->top] = x;
Inserte el elementox
en la nueva posición superior de la pila.return 1;
Devuelve 1, lo que indica que la pila se ha realizado correctamente.4. El propósito de esta función es insertar elementos de datos
x
en la pila secuencial y generar un mensaje de error si la pila está llena.5. Un valor de retorno de 0 indica que el apilamiento falló y un valor de retorno de 1 indica que el apilamiento fue exitoso.
Ⅳ .
【Código de ejemplo】
// 出栈操作 int Pop(SeqStk* stk) { /* 顺序栈stk的栈顶元素退栈 */ if (stk->top == 0) // 判断栈是否下溢(空栈) { error("栈空"); // 输出错误信息,表示栈已空 return 0; // 返回0,表示出栈失败 } else { stk->top--; // 修改栈顶指针,指向新的栈顶 return 1; // 返回1,表示出栈成功 } } /* Pop */
【Explicación del código】
1. Este código implementa una función para abrir la pila
Pop
.2. El parámetro de la función es un
SeqStk
puntero a la estructurastk
.3. Los comentarios en el código explican lo que hace cada línea:
if (stk->top == 0)
Determinetop
si es 0, es decir, si la pila está vacía.error("栈空");
Si la pila está vacía, se emite el mensaje de error "pila vacía".return 0;
Devuelve 0, lo que indica un error al salir de la pila.stk->top--;
El puntero superior de la pilatop
se reduce para señalar la nueva parte superior de la pila.return 1;
Devuelve 1, lo que indica que la pila se extrajo con éxito.4. El propósito de esta función es desapilar el elemento superior
stk
de y generar un mensaje de error si la pila está vacía.5. Un valor de retorno de 0 indica que la ventana emergente falló y un valor de retorno de 1 indica que la ventana emergente fue exitosa.
6. El último
/* Pop */
es un comentario para la función, que indica que el segmento de código implementa la operación de pila.
Ⅴ Tome el elemento superior de la pila
【Código de ejemplo】
// 获取栈顶元素 DataType GetTop(SeqStk* stk) { if (EmptyStack(stk)) // 判断栈是否为空 return NULLData; // 如果为空,返回空数据元素 else return stk->data[stk->top]; // 返回栈顶元素 }
【Explicación del código】
1. Este código implementa una función para obtener el elemento superior de la pila
GetTop
.2. El parámetro de la función es un puntero a
SeqStk
la estructurastk
.3. Los comentarios en el código explican lo que hace cada línea:
if (EmptyStack(stk))
LlameEmptyStack
a la función para determinar si la pila está vacía.return NULLData;
Si la pila está vacía, devuelve un elemento de datos vacío.else return stk->data[stk->top];
Si la pila no está vacía, devuelve el elemento superior de la pila.4. El propósito de esta función es obtener el elemento superior
stk
de la pila está vacía, devuelve un elemento de datos vacío.5. De lo contrario, devuelva el valor del elemento superior de la pila.
6. Cabe señalar que, de acuerdo con la situación real,
NULLData
se pueden realizar las modificaciones apropiadas según el tipo de datos.
(3) Implementación de enlace de pila - cadena de pila
① Definición de cadena de pila
- La estructura de almacenamiento vinculada de la pila se denomina pila vinculada . Es una lista de un solo vínculo con operaciones limitadas. Las operaciones de inserción y eliminación solo se limitan a la posición del encabezado.
- El puntero superior de la pila es el puntero principal de la lista enlazada
② Escriba la descripción de la pila encadenada
【Tipo de pila de cadena 】
// 定义链式栈节点结构体 typedef struct node { DataType data; // 数据元素 struct node* next; // 指向下一个节点的指针 } LkStk;
【Aviso】
- Condición de subdesbordamiento: LS -> siguiente == NULL
- Overflow: no considera el fenómeno stack full
【Explicación del código】
1. Este código define una estructura de nodos de pila encadenados
LkStk
.2. Contiene las siguientes dos variables miembro:
DataType data;
Una variable que almacena elementos de datos, aquí se suponeDataType
que es un tipo de datos personalizado.struct node* next;
Un puntero al siguiente nodo, utilizado para implementar una estructura de cadena.3. La estructura representa un nodo en la pila de cadena y cada nodo contiene un elemento de datos y un puntero al siguiente nodo.
4. Mediante la conexión continua de nodos, se puede formar una estructura de pila en cadena.
③ Operación básica de la pila de cadena
Ⅰ Inicialización
【Código de ejemplo】
// 初始化链式栈 void InitStack(LkStk* LS) { LS = (LkStk*)malloc(sizeof(LkStk)); // 分配内存空间,LS指向新的栈顶节点 LS->next = NULL; // 将栈顶节点的指针指向NULL,表示栈为空 }
【Explicación del código】
1. Este código implementa una función para inicializar la pila de cadena
InitStack
.2. El parámetro de la función es un puntero a
LkStk
la estructuraLS
.3. Los comentarios en el código explican lo que hace cada línea:
LS = (LkStk*)malloc(sizeof(LkStk));
Utilicemalloc
la asignación dinámica de espacio de memoria para apuntar el punteroLS
al nuevo nodo superior de la pila.LS->next = NULL;
next
Asigne el puntero del nodo superior de la pila aNULL
, lo que indica que la pila vinculada está vacía.4. El propósito de esta función es inicializar la pila de cadena.
5. Mediante la asignación dinámica de espacio de memoria, cree un nodo superior de pila y apunte su puntero
NULL
para indicar que la pila vinculada está vacía.6. Cabe señalar que dado que el parámetro es un puntero, la modificación del valor del puntero dentro de la función no afectará el parámetro real que se pasa cuando se llama a la función.
7. Por lo tanto, si desea poder acceder al nodo superior de la pila recién asignado después de llamar a la función, se recomienda cambiar el parámetro de la función a un puntero doble o devolver el puntero del nodo superior de la pila recién asignado.
Ⅱ Juzga que la pila está vacía
【Código de ejemplo】
// 判断链式栈是否为空 int EmptyStack(LkStk* LS) { if (LS->next == NULL) // 判断栈顶节点指针是否为空 return 1; // 如果为空,返回1表示栈为空 else return 0; // 如果不为空,返回0表示栈不为空 }
【Explicación del código】
1. Este código implementa una función para determinar si la pila vinculada está vacía
EmptyStack
.2. El parámetro de la
LkStk
funciónLS
un3. Los comentarios en el código explican lo que hace cada línea:
if (LS->next == NULL)
Juzgarnext
si el puntero del nodo superior de la pila está vacío, es decir, si la pila encadenada está vacía.return 1;
Si la pila está vacía, devuelve 1, lo que indica que la pila está vacía.return 0;
Si la pila no está vacía, devuelve 0, lo que indica que la pila no está vacía.4. El propósito de esta función es juzgar si la pila vinculada está vacía.
5. Determine el estado de la pila de la cadena juzgando si el puntero del nodo superior de la pila está vacío.
6. Si el puntero del nodo superior de la pila está vacío, significa que la pila está vacía, de lo contrario, significa que la pila no está vacía.
7. Un valor de retorno de 1 indica que la pila está vacía y un valor de retorno de 0 indica que la pila no está vacía.
Ⅲ Empuje en la pila
[Definición] insertar en la pila : insertar un elemento x en la parte superior de la pila
- Genere un nuevo nodo (la pila de cadena no se desbordará)
- Inserte un nuevo nodo en la pila de cadenas y conviértalo en el nuevo nodo superior de la pila
【Código de ejemplo】
// 将元素入栈 void Push(LkStk* LS, DataType x) { LkStk* temp; // 定义临时指针变量temp temp = (LkStk*)malloc(sizeof(LkStk)); // 分配内存空间,创建新的节点 temp->data = x; // 将输入的元素x赋值给新节点的数据域 temp->next = LS->next; // 将新节点的next指针指向原来栈顶节点的next指针 LS->next = temp; // 将栈顶指针指向新节点,使其成为新的栈顶节点 }
【Diagrama esquemático】
【Explicación del código】
1. Este código implementa una función que empuja elementos a la pila
Push
.2. Los parámetros de la función incluyen un
LkStk
puntero a la estructuraLS
y unDataType
elemento de tipox
, que indica el elemento que se va a colocar en la pila.3. Los comentarios en el código explican lo que hace cada línea:
LkStk* temp;
Defina una variable de puntero temporaltemp
para apuntar al nodo recién creado.temp = (LkStk*)malloc(sizeof(LkStk));
Utilícelo para asignarmalloc
dinámicamente espacio de memoria y crear un nuevo nodo.temp->data = x;
x
Asigne el elemento que se empujará a la pila al campo de datos del nuevo nodo.temp->next = LS->next;
Apunte elnext
puntero alnext
puntero del nodo superior de la pila original para realizar la conexión de la estructura de la cadena.LS->next = temp;
Apunte el puntero superior de la pilaLS->next
al nuevo nodo, haciendo que el nuevo nodo sea el nuevo nodo superior de la pila.4. El propósito de esta función es empujar elementos
x
a la pila.5. Primero cree un nuevo nodo y asigne elementos al campo de datos del nuevo nodo.
6. Luego apunte el
next
puntero alnext
puntero del nodo superior de la pila original, y luego apunte el puntero de la parte superior de la pila al nuevo nodo para darse cuenta la operación de empuje.
Ⅳ .
[Definición] Emerger : elimina un elemento en la parte superior de la pila y regresa
- Considere el problema de subdesbordamiento
- Si no se desborda, saque el elemento superior de la pila, elimine el nodo superior de la pila de cadena y devuelva el nodo al sistema
【Código de ejemplo】
// 将元素出栈 int Pop(LkStk* LS) { LkStk* temp; // 定义临时指针变量temp if (!EmptyStack(LS)) // 判断栈是否为空 { temp = LS->next; // 将temp指针指向栈顶节点 LS->next = temp->next; // 将栈顶指针指向栈顶节点的下一个节点,跳过当前栈顶节点 free(temp); // 释放当前栈顶节点的内存空间 return 1; // 返回1表示出栈成功 } else return 0; // 返回0表示栈为空,无法进行出栈操作 }
【Diagrama esquemático】
【Explicación del código】
1. Este código implementa una función que extrae elementos de la pila
Pop
.2. El parámetro de la función es un
LkStk
puntero a una estructuraLS
, que se utiliza para representar la pila de cadenas que se operará.3. Los comentarios en el código explican lo que hace cada línea:
LkStk* temp;
Defina una variable de puntero temporaltemp
para apuntar al nodo superior de la pila actual.if (!EmptyStack(LS))
Para juzgar si la pila está vacía, useEmptyStack()
la función para ayudar en el juicio.temp = LS->next;
Apunte la variable de puntero temporaltemp
al nodo superior de la pila.LS->next = temp->next;
Apunte el puntero superior de la pila al siguiente nodo del nodo superior de la pila, omitiendo el nodo superior de la pila actual.free(temp);
Libere el espacio de memoria del nodo superior de la pila actual, es decir, elimínelo de la pila de la cadena.return 1;
Devolver 1 indica que la pila se abrió con éxito.return 0;
Si la pila de enlaces está vacía, devolver 0 significa que la pila está vacía y no se puede abrir.4. El propósito de esta función es realizar la operación de apilamiento de elementos.
5. Primero juzgue si la pila está vacía, si no lo está, apunte el puntero superior de la pila al siguiente nodo del nodo superior de la pila y libere el espacio de memoria del nodo superior actual de la pila en el Mismo tiempo.
6. Si la pila está vacía, significa que no se puede realizar la operación de pila.
7. Un valor de retorno de 1 significa que la ventana emergente se realizó correctamente y un valor de retorno de 0 significa que la pila está vacía y no se puede abrir.
Ⅴ Tome el elemento superior de la pila
【Código de ejemplo】
// 获取栈顶元素 DataType GetTop(LkStk* LS) { if (!EmptyStack(LS)) // 判断栈是否为空 return LS->next->data; // 返回栈顶节点的数据域值 else return NULLData; // 如果栈为空,则返回空数据(NULLData) }
【Explicación del código】
1. Este código implementa una función para obtener el elemento superior de la pila
GetTop
.2. El parámetro de la función es un
LkStk
puntero a una estructuraLS
, que se utiliza para representar la pila de cadenas que se operará.3. Los comentarios en el código explican lo que hace cada línea:
if (!EmptyStack(LS))
Para juzgar si la pila está vacía, useEmptyStack()
la función para ayudar en el juicio.return LS->next->data;
Si la pila no está vacía, devuelve el valor del campo de datos del nodo superior de la pila.return NULLData;
Si la pila está vacía, devuelve datos vacíos (NULLData
), lo que significa que no hay elementos en la pila.4. El propósito de esta función es obtener el valor del elemento superior de la pila sin modificar la pila.
5. Primero juzgue si la pila está vacía, si no, devuelva el valor del campo de datos del nodo superior de la pila, si la pila está vacía, devuelva datos vacíos ( )
NULLData
para indicar que no hay elementos en la pila.
(4) Aplicación y recursividad de la pila.
① Ejemplos básicos de aplicación de la pila
[Ejemplo 1] Supongamos que la secuencia de entrada de la pila es 1, 2, 3, 4 en secuencia, ¿cuál de las secuencias de salida obtenidas coincide?
【Análisis del problema】 Respuesta correcta: d
d 3,4,2,1
La pila es una estructura de datos que sigue el principio "Último en entrar, primero en salir" (Last In First Out, LIFO), por lo que cuando insertamos los elementos 1, 2, 3 y 4 en la pila en secuencia, la secuencia de salida resultante solo puede ser- Ninguna de las otras opciones ( a 1,2,3,4 ; b 4,2,3,1 ; c 1,3,2,4 ) puede ser la secuencia de salida de la pila.
- La opción d 3,4,2,1 es la única secuencia de salida que se ajusta a las propiedades de la pila y corresponde al caso en que la secuencia de entrada es 1,2,3,4.
[Respuesta detallada]
- Opción a 1,2,3,4 : la pila generará elementos de acuerdo con el principio de último en entrar, primero en salir, por lo que la secuencia de salida será 4,3,2,1, que no coincide con las opciones dadas.
- Opción b 4,2,3,1 : la pila generará primero el último elemento insertado en la pila, por lo que la secuencia de salida será 4,3,2,1, que no coincide con la opción dada.
- Opción c 1,3,2,4 : antes de que la pila genere el elemento 4, primero debe generar el elemento 3, y la secuencia dada por la opción c es 1,3, lo cual es inconsistente con las características de la pila.
- Opción d 3,4,2,1 : la pila es una estructura de datos de último en entrar, primero en salir (LIFO), y el orden en que los elementos se extraen de la pila es opuesto al orden en que se insertaron la pila. Según la secuencia de entrada en el título es 1, 2, 3, 4, según las características de la pila, el elemento 4 se coloca en la pila primero, luego el elemento 3, luego el elemento 2 y finalmente el elemento 1. Por lo tanto, el orden en la pila es 4,3,2,1. La secuencia de salida 3, 4, 2, 1 correspondiente a la opción d también es consistente con las características de la pila.Primero se extrae el elemento 3, luego el elemento 4, luego el elemento 2 y el último elemento 1. Entonces, la opción d es la secuencia de salida correcta que se ajusta a las reglas de la pila y es consistente con la secuencia de entrada.
[Ejemplo 2] Operación de pila secuencial
【Código de ejemplo】
const int maxsize = 50; // 定义常量 maxsize,表示栈的最大大小 typedef struct seqstack // 定义结构体 seqstack,表示顺序栈 { char data[maxsize]; // 字符数组,用于存储栈中的元素 int top; // 整型变量,表示栈顶指针的位置 } seqstk; int main() { seqstk stk; // 声明一个 seqstk 类型的变量 stk int i; char ch; Initstack(&stk); // 初始化栈 stk for (ch = 'A'; ch <= 'A' + 10; ch++) // 将字符 'A' 到 'A' + 10 入栈 { Push(&stk, ch); // 将字符 ch 压入栈 stk printf("%c", ch); // 打印字符 ch } printf("\n"); while (!Emptystack(&stk)) // 当栈不为空时执行循环 { ch = GetTop(&stk); // 获取栈顶元素赋值给变量 ch Pop(&stk); // 弹出栈顶元素 printf("%c", ch); // 打印变量 ch 的值 } printf("\n"); return 0; }
【Explicación del código】
1. La función del código es crear una pila secuencial e inicializarla, luego empujar los caracteres 'A' a 'K' en la pila en secuencia, luego imprimir los caracteres empujados a la pila y finalmente abrir la pila e imprimir los personajes fuera de la pila a su vez.
2. Los detalles son los siguientes:
const int maxsize = 50;
Defina una constantemaxsize
que represente el tamaño máximo de la pila.typedef struct seqstack
Defina un nuevo tipo de datosseqstk
que represente una pila secuencial.char data[maxsize];
Defina una matriz de caracteres enseqstk
la estructuradata
para almacenar los elementos en la pila.int top;
Defina una variable entera enseqstk
la estructuratop
para indicar la posición del puntero superior de la pila.int main()
Entrada de la función principal.seqstk stk;
Declare unaseqstk
variable de tipostk
para representar una pila secuencial.Initstack(&stk);
Llame a la funciónInitstack()
para inicializar la pilastk
.for (ch = 'A'; ch <= 'A' + 10; ch++)
Bucle, empuje los caracteres 'A' a 'A' + 10 en la pila en secuencia.Push(&stk, ch);
La función de llamada empujaPush()
los caracteresch
a la pilastk
.printf("%c", ch);
Imprimir caracteresch
.while (!Emptystack(&stk))
Ejecute el bucle mientras la pila no esté vacía.ch = GetTop(&stk);
Llame a la funciónGetTop()
para obtener el elemento superior de la pila y asígnelo a una variablech
.Pop(&stk);
La función de llamadaPop()
saca el elemento superior de la pila.printf("%c", ch);
Imprimech
el valor de una variable.return 0;
Devuelve el indicador de que la función principal se ejecuta correctamente.3. En resumen, la función de este código es crear una pila secuencial, insertar una serie de caracteres en la pila e imprimirlos uno por uno, y luego sacar los elementos de la pila uno por uno e imprimirlos. y el resultado de salida final es "ABCDEFGHIJK".
【Resultados del】
- Durante la ejecución, los caracteres 'A' a 'K' se colocan en la pila, por lo que la salida de la primera línea es "ABCDEFGHIJK".
- Luego, en cada bucle, el elemento superior de la pila se extrae y se imprime hasta que la pila está vacía.
- Por lo tanto, la segunda línea de salida es "KJIHGFEDCBA", que es el orden inverso de los caracteres 'K' a 'A'.
ABCDEFGHIJK KJIHGFEDCBA
[Ejemplo 3] Escriba un algoritmo que invierta la lista enlazada individualmente con el nodo principal que se muestra en la siguiente figura con la ayuda de una pila.
【Código de ejemplo】
void ReverseList(LkStk *head) { Lkstk *S; // 定义指向链栈的指针变量 S DataType x; // 定义数据类型变量 x,用于临时存储链表节点的数据 InitStack(S); // 初始化链栈 S p = head->next; // p 指向链表的第一个节点 while (p != NULL) // 扫描链表 { Push(s, p->data); // 元素进栈:将链表节点的数据入栈 p = p->next; // p 指向下一个节点 } p = head->next; // 重新让 p 指向链表的第一个节点 while (!EmptyStack(S)) // 栈不为空时 { p->data = GetTop(S); // 元素填入单链表中:将栈顶元素赋值给链表节点的数据 Pop(S); // 出栈:弹出栈顶元素 p = p->next; // p 指向下一个节点 } }
【Explicación del código】
1. La función de este código es realizar la operación inversa de la lista enlazada. Los pasos específicos de implementación son los siguientes:
- Declare una variable de puntero que apunte a la pila de enlaces
S
.- Declare una variable temporal
x
para almacenar los datos de los nodos de la lista enlazada.- Inicialice la pila de cadenas
S
.- Apunte el puntero
p
al primer nodo de la lista enlazada.- Recorra la lista enlazada e inserte los datos del nodo en la pila.
- Vuelva a apuntar el puntero
p
al primer nodo de la lista vinculada.- Recorra la pila, asigne el elemento superior de la pila a los datos del nodo de la lista vinculada a su vez y extraiga el elemento superior de la pila.
- Apunte el puntero
p
al siguiente nodo, es decir, recorra la lista enlazada hacia atrás.- Complete la operación inversa de la lista enlazada.
2. Los detalles son los siguientes:
void ReverseList(LkStk *head)
El nombre de la función esReverseList
y el parámetro es un puntero al nodo principal de la lista vinculadahead
, lo que indica que la lista vinculada está invertida.Lkstk *S;
Declare unLkstk
tipo de variable de punteroS
que represente el puntero de la pila de enlaces.DataType x;
DataType
Declare una variable cuyo tipo de datosx
es para almacenar temporalmente los datos de los nodos de la lista enlazada.InitStack(S);
Llame a la función para inicializarInitStack()
la pila de enlaces .S
p = head->next;
Apunte el punterop
al primer nodo de la lista enlazada.while (p != NULL)
Ejecute el bucle mientras el punterop
no sea nulo.Push(s, p->data);
Llame a la funciónPush()
para insertar los datos del nodo de la lista vinculada en la pila.p = p->next;
Apunte el punterop
al siguiente nodo de la lista vinculada, es decir, recorra la lista vinculada hacia atrás.p = head->next;
Vuelva a apuntar el punterop
al primer nodo de la lista vinculada.while (!EmptyStack(S))
Ejecute el bucle mientras la pila de enlacesS
no esté vacía.p->data = GetTop(S);
Asigne el elemento superior de la pila a los datos del nodo de la lista vinculada.Pop(S);
La función de llamadaPop()
saca el elemento superior de la pila.p = p->next;
Apunte el punterop
al siguiente nodo de la lista vinculada, es decir, recorra la lista vinculada hacia atrás.3. En resumen, esta función logra la inversión de la lista vinculada mediante el uso de una pila vinculada y variables temporales para insertar los datos de los nodos de la lista vinculada en la pila primero y luego sacarlos de la pila.
② Definición de recursividad
Si una función se llama a sí misma antes de completarse, se llama función recursiva .
[Ejemplo] Encuentra la función factorial de un número entero n :
【Código de ejemplo】
int f(int n) { if (n == 0) // 如果 n 等于 0 return 1; // 返回 1 else // 否则 return n * f(n - 1); // 递归调用函数 f,传入 n-1,并将结果乘以 n 返回 }
【Explicación del código】
int f(int n)
El nombre de la función esf
y el parámetro es un número enteron
, lo que indica la función para calcular el factorial.if (n == 0)
Si n es igual a 0, significa que se recurrió al caso más básico, y el resultado del factorial es 1.return 1;
Devuelve el resultado 1.else
Si n no es igual a 0, significa que se debe continuar con el cálculo recursivo del factorial.return n * f(n - 1);
Llame a la función f recursivamente, pasando n-1, y devuelva el resultado multiplicado por n. El propósito de la llamada recursiva es calcular el factorial de n igual a n veces el factorial de n-1.
③ Forma general de recursividad
void fname(参数表)
{
if (数据作为递归出口)
{
// 简单操作
}
else
{
// 简单操作
fname(参数表);
// 简单操作
// [fname(参数表); 简单操作;]
// 可能有多次递归调用
}
}
[Explicación detallada] Lo anterior es la forma general de una función recursiva, y la explicación específica es la siguiente:
void fname(参数表)
: El nombre de la función esfname
, con un conjunto de parámetros.if (数据作为递归出口)
: Cuando se cumple una determinada condición, los datos se utilizan como salida de la recursión, es decir, la recursión finaliza.// 简单操作
: Acción simple realizada en la salida recursiva.else
: Si no se cumple la condición, realice las siguientes operaciones.// 简单操作
: Operaciones simples realizadas antes o después de la llamada recursiva.fname(参数表)
: Llame a la función recursivamentefname
y pase la lista de parámetros.// 可能有多次递归调用
: Después de la llamada recursiva, la función puede continuarfname
siendo llamada para la recursividad y puede haber múltiples llamadas recursivas.[Nota] La función recursiva debe cumplir las condiciones para el final de la recursión; de lo contrario, ingresará a una recursividad infinita y hará que el programa se bloquee. Al mismo tiempo, las funciones recursivas deben tener en cuenta el orden de las llamadas recursivas y el establecimiento de las condiciones de finalización para garantizar que la recursividad pueda finalizar normalmente.
Dos, la cola
Los archivos de encabezado que describen las implementaciones de pila y cola son los siguientes:
- Seqstack.h: La definición e implementación de la pila secuencial.
- Lkstack.h: Definición e implementación de cadena de pila.
- Sequeue.h: Definición de cola de secuencia y su implementación.
- Lkqueue.h: La definición e implementación de la cola en cadena.
(1) El concepto básico de cola
① Definición
Queue: También es una tabla lineal con operaciones limitadas.
- Queue : es una tabla lineal que solo permite inserciones en un extremo de la tabla y eliminaciones en el otro extremo.
- El extremo que permite la eliminación se llama frente .
- El otro extremo que permite la inserción se llama la cola de la cola (posterior)
- Cola Q=(a1, a2, a3,...an)
② Diagrama esquemático
【Ejemplo】 Compras en línea
- Cola de trabajos en el sistema operativo
- El miembro que entra primero en la cola siempre sale primero de la cola
- Por lo tanto, la cola también se denomina tabla lineal de primero en entrar, primero en salir (First In First Out) , o tabla FIFO para abreviar .
- Cuando no hay elementos en la cola, se denomina cola vacía.
- Después de agregar los elementos a 1 , a 2 , ... an a la cola vacía en secuencia , a 1 es el elemento principal de la cola y a n es el elemento final de la cola.
- Obviamente, el orden de salida de la cola sólo puede ser un 1 , un 2 , ... un n , es decir, la modificación de la cola se realiza según el principio de first in first out .
③ Características de la cola
Primero en entrar, primero en salir ( FIFO ) :
El propósito de la cola: a menudo se usa para almacenar temporalmente datos para ser procesados.
④ Funcionamiento básico de la cola
➢Inicialización de cola InitQueue(Q):
- Establecer una cola vacía Q
➢ColaVacía ( Q):
- Si la cola Q está vacía, el valor devuelto es 1 , de lo contrario, el valor devuelto es 0
➢Poner en cola Poner en cola (Q,x):
- Inserte el elemento de datos x en la cola desde el final de la cola, convirtiéndolo en el nuevo elemento de cola de la cola
➢Cola de salida (Q):
- eliminar el primer elemento de la cola
➢Obtener el primer elemento de la cola GetHead(Q):
- Devuelve el valor del primer elemento de la cola.
(2) Implementación secuencial de colas
① cola secuencial
[Definición] Cola secuencial : solo se puede insertar desde un extremo de la matriz y eliminar desde el otro extremo.[Descripción] SeqQue sq ;
- Condición de desbordamiento: sq.rear == maxsize-1 (cola llena)
- Condición de subdesbordamiento: sq.rear == sq.front (cola vacía)
[Nota] Desbordamiento falso : sq.rear == maxsize-1 , pero la capacidad real en la cola no ha alcanzado la capacidad máxima.
② Cola circular
[Definición] La implementación secuencial de la cola - cola circular
- Use una matriz unidimensional como estructura de almacenamiento de la cola
- Capacidad de la cola : el número máximo de elementos que se pueden almacenar en la cola
【Diagrama esquemático】
【Acuerdo】
- Inicial: delantero=trasero=0
- Enqueue: la parte trasera se incrementa en 1, y el elemento se inserta en la posición señalada por el puntero de la cola
- Eliminación de la cola: aumente el frente en 1, obtenga el elemento en la posición señalada por el puntero de la cabeza
【ilustrar】
- El frente del puntero de la cabeza: siempre apunta a la posición anterior del elemento de la cabeza real
- El indicador de cola trasero - siempre apunta al elemento de cola real
➢En la operación de cola:
- cuadrado.trasero=cuadrado.trasero+1;
- sq.data[sq.trasero]=x;
➢Operación de eliminación de cola :
- frente cuadrado=frente cuadrado+1;
- La figura a es una cola vacía, sq.rear=0, sq.front=0.
- La figura b muestra que después de 20 ingrese a la cola, sq.rear=1, sq.front=0.
- La figura c muestra que después de que 30, 40 y 50 se ponen en cola por turnos, sq.rear=4, sq.front=0.
- La figura d muestra que después de que 20, 30, 40 y 50 estén fuera de la cola en secuencia, sq.rear=4, sq.front=4.
- La figura e muestra que después de 60 ingrese a la cola, sq.rear=5, sq.front=4.
【Código de ejemplo】const int maxsize = 20; // 定义队列的最大容量为20 // 定义顺序队列结构体 typedef struct seqqueue { DataType data[maxsize]; // 存储队列中的元素 int front, rear; // 队头指针和队尾指针 } SeqQue; SeqQue sq; // 声明一个顺序队列变量sq
【Explicación del código】1. La siguiente es una explicación de comentario para cada línea de código:
const int maxsize = 20;
Se define una constantemaxsize
que indica que la capacidad máxima de la cola es 20.typedef struct seqqueue
define unseqqueue
tipo de estructura llamado .DataType data[maxsize];
seqqueue
Se define una matriz en la estructura paradata
almacenar los elementos en la cola. El tamaño de la matriz esmaxsize
.int front, rear;
Enseqqueue
la estructura se definen dos variables enterasfront
yrear
, que representan respectivamente el puntero de cabeza de cola y el puntero de cola de cola.SeqQue sq;
Se declara una variable de cola secuencialsq
, de tipoSeqQue
.2. Este código define una estructura de datos de cola secuencial
SeqQue
, que contiene una matriz de tamaño fijodata
y dos punteros que indican la posición de la cabeza y la cola de lafront
colarear
.3. Al declarar
sq
variables, podemos usarSeqQue
estructuras para crear objetos de cola secuenciales.
Ⅰ Definición de cola circular
[Definición] Cola circular : asigne un espacio de almacenamiento ( representación de matriz ) para la cola y considere este espacio de almacenamiento como conectado de cabeza a cola.【Diagrama esquemático】【Aviso】
- Puntero de cabeza frontal : una posición detrás del elemento de cabeza de cola real en el sentido de las agujas del reloj
- Puntero de cola trasero : apunta al elemento de cola real
Ⅱ Implementación de Circular Queue Loop
➢Para insertar en la cola: el puntero al final de la cola se incrementa en 1Sq.rear=(sq.rear+1)%maxsize
➢ Dequeue inmediatamente después de la eliminación: el puntero de la cabeza de la cola se incrementa en 1
Sq.front=(sq.front+1)%maxsize
Ⅲ Definición de tipo de cola circular
【Código de ejemplo】
typedef struct Cycqueue { DataType data[maxsize]; // 存储数据的数组 int front, rear; // 队头和队尾指针 } CycQue; // 定义循环队列类型 CycQue CQ; // 声明一个循环队列实例 CQ
【Explicación del código】
typedef struct Cycqueue
Indica la definición de un tipo de estructuraCycqueue
.{}
Defina los miembros de la estructura dentro de llaves.DataType data[maxsize];
Declare unadata
matriz nombrada para almacenar datos, el tamaño de la matriz esmaxsize
.int front, rear;
Declare dos variables enterasfront
yrear
, que representan los punteros de cabeza y cola de la cola circular respectivamente.} CycQue;
Indica el final de la definición del tipo de estructura y le cambia el nombre aCycQue
.CycQue CQ;
Declare una instancia de cola circularCQ
, utilizando el tipo de estructura definido anteriormente.
Ⅳ Provisiones
cola circular CQ
- La condición de subdesbordamiento significa que la cola está vacía : CQ.front==CQ.rear
- La condición de desbordamiento es que la cola está llena : el puntero de la cola alcanza al puntero de la cabeza por detrás
Es decir: (CQ.rear+1)%maxsize==CQ.front ( cabeza de captura de cola )
- Se desperdicia un espacio, cuando el equipo está lleno, la capacidad real del equipo = maxsize-1
③ Operación básica de cola circular
Ⅰ Inicialización
【Código de ejemplo】
void InitQueue(CycQue CQ) { CQ.front = 0; // 初始化循环队列的队头指针为 0 CQ.rear = 0; // 初始化循环队列的队尾指针为 0 }
【Explicación del código】
1. Esta función se utiliza para inicializar la cola circular y establecer los punteros de cabeza y cola de cola en 0, lo que indica que la cola está vacía.
2. La explicación detallada es la siguiente:
void InitQueue(CycQue CQ)
Indica que una función está definidaInitQueue
y el parámetro es una cola circularCQ
.CQ.front = 0;
Inicialice el puntero principal de la cola circularfront
en 0, lo que indica que la cola está vacía.CQ.rear = 0;
Inicialice el puntero de la cola de la cola circularrear
en 0, lo que indica que la cola está vacía.
Ⅱ Juzgar que la cola está vacía
【Código de ejemplo】
int EmptyQueue(CycQue CQ) { if (CQ.rear == CQ.front) // 如果队尾指针等于队头指针,表示队列为空 return 1; // 返回 1,表示队列为空 else return 0; // 返回 0,表示队列不为空 }
【Explicación del código】
1. Esta función se utiliza para juzgar si la cola circular está vacía.
2. Cuando el puntero de cola de cola es igual al puntero de cabeza de cola, significa que la cola está vacía, de lo contrario, significa que la cola no está vacía.
3. Un valor de retorno de 1 indica que la cola está vacía y un valor de retorno de 0 indica que la cola no está vacía.
4. La explicación detallada es la siguiente:
int EmptyQueue(CycQue CQ)
Indica que una función está definidaEmptyQueue
y el parámetro es una cola circularCQ
.if (CQ.rear == CQ.front)
Determine si el puntero de cola de colarear
es igual al puntero de cabeza de colafront
.return 1;
Si el puntero de cola de cola es igual al puntero de cabeza de cola, lo que indica que la cola está vacía, devuelve 1.return 0;
Si el puntero de cola de cola no es igual al puntero de cabeza de cola, significa que la cola no está vacía y devuelve 0.
Ⅲ Entrar en la cola
[Definición] Entrar en el equipo - insertar un nuevo elemento x al final del equipo
- ¿Desbordamiento de juicio? Sí, el desbordamiento regresa;
- De lo contrario, modifique el puntero de la cola de la cola (aumente 1) e inserte el nuevo elemento x en la cola de la cola.
【Código de ejemplo】
// 在循环队列中插入元素 int EnQueue(CycQue CQ, DataType x) { // 判断队列是否已满 if ((CQ.rear + 1) % maxsize == CQ.front) { error("队列满"); // 队列满时报错 return 0; } else { CQ.rear = (CQ.rear + 1) % maxsize; // 队尾指针向后移动一个位置 CQ.data[CQ.rear] = x; // 将元素x插入队尾 return 1; } }
【Explicación del código】
1. Este código implementa la operación de insertar elementos en la cola circular.
2. La explicación detallada es la siguiente:
CycQue
Es el tipo de estructura de la cola circular.DataType
es el tipo de datos de los elementos en la cola.maxsize
es la capacidad máxima de la cola.3. En la función, primero juzgamos si la cola está llena, lo cual se juzga según las siguientes condiciones:
(CQ.rear + 1) % maxsize == CQ.front
. Si la condición es verdadera, la cola está llena, se generará un mensaje de error y se devolverá 0.4. Si la cola no está llena,
else
se ejecutarán las siguientes sentencias. Primero, mueva el puntero de la cola hacia atrás una posición:CQ.rear = (CQ.rear + 1) % maxsize
. Luego, inserte el elementox
al final de la cola:CQ.data[CQ.rear] = x
. Finalmente, la función devuelve 1 para indicar una inserción exitosa.5. Tenga en cuenta que
CQ
los parámetros se pasan por valor, por lo que modificar los parámetros dentro de la función noCQ.rear
afectará el exterior.CQ.data
Si desea modificar una estructura externa dentro de una función, debe usar punteros o referencias como parámetros de función.
Ⅳ Desencolar
[Definición] Dequeue : elimina el elemento al principio de la cola y regresa
- ¿Se considera desbordamiento? Sí, desbordamiento de retorno;
- Si no se desborda, modifique el puntero del encabezado de la cola y obtenga el elemento del encabezado de la cola.
【Código de ejemplo】
// 从循环队列中取出元素 int OutQueue(CycQue CQ) { // 判断队列是否为空 if (EmptyQueue(CQ)) { error("队列空"); // 队列空时报错 return 0; } else { CQ.front = (CQ.front + 1) % maxsize; // 队头指针向后移动一个位置 return 1; } }
【Explicación del código】
1. La función del código es sacar elementos de la cola circular.
2. La explicación detallada es la siguiente:
CycQue
Es el tipo de estructura de la cola circular.maxsize
es la capacidad máxima de la cola.3. En la función, primero juzgamos si la cola está vacía, lo que se
EmptyQueue(CQ)
juzga llamando a la función. Si la cola está vacía, se emite un mensaje de error y se devuelve 0.4. Si la cola no está vacía, se ejecutará la
else
siguiente . Primero, mueva el puntero de cabeza de línea hacia atrás una posición:CQ.front = (CQ.front + 1) % maxsize
. Luego, la función devuelve 1 para indicar que el elemento se recuperó correctamente.5. Tenga en cuenta que, al igual que las
EnQueue()
funciones anteriores,CQ
los parámetros también se pasan por valor, por lo que modificar el interior de la función noCQ.front
afectará el exterior. Si desea modificar una estructura externa dentro de una función, debe usar punteros o referencias como parámetros de función.
Ⅴ Obtener el primer elemento de la cola
【Código de ejemplo】
// 获取栈顶元素 DataType GetTop(LkStk* LS) { if (!EmptyStack(LS)) // 判断栈是否为空 return LS->next->data; // 返回栈顶节点的数据域值 else return NULLData; // 如果栈为空,则返回空数据(NULLData) }
【Explicación del código】
1. La función del código es obtener el elemento cabeza de la cola circular.
2. La explicación detallada es la siguiente:
DataType
es el tipo de datos de los elementos en la cola.CycQue
Es el tipo de estructura de la cola circular.maxsize
es la capacidad máxima de la cola.NULLData
es un valor específico que representa datos vacíos.3. En la función, primero juzgamos si la cola está vacía, lo que se
EmptyQueue(CQ)
juzga llamando a la función. Si la cola está vacía, devuelve datos vacíos directamenteNULLData
.4. Si la cola no está vacía, ejecute
else
la siguiente declaración. Se utiliza aquí(CQ.front + 1) % maxsize
para calcular la siguiente posición de la cabeza de la cola y devolver el elemento en esa posiciónCQ.data[(CQ.front + 1) % maxsize]
.5. Tenga en cuenta que, al igual que las funciones anteriores,
CQ
los parámetros aquí también se pasan por valor, por lo que las modificaciones dentro de la funciónCQ.front
no afectarán el exterior. Si desea modificar una estructura externa dentro de una función, debe usar punteros o referencias como parámetros de función. Además, defina e inicialice en el código de acuerdo con la situación realNULLData
.
(3) Implementación de enlace de la cola
① Definición de cola en cadena
[Definición] Cola encadenada : una cola representada por una lista enlazada, es decir, es una lista con un solo enlace que se limita a la eliminación en el encabezado y la inserción al final de la lista .【Diagrama esquemático】[Explicación] Obviamente, solo el puntero de cabeza de la lista enlazada única no es conveniente para insertar al final de la lista. Por esta razón, agregue un puntero de cola para apuntar al último nodo de la lista enlazada.[Nota] Hay dos punteros adjuntos:
- Puntero de cabecera frontal : apunta al nodo de cabecera de la tabla; el nodo del elemento de cabecera de la cola está delante->siguiente
- Tail pointer rear : apunta al último nodo de la lista enlazada (es decir, el nodo final de la cola)
② Descripción del tipo de cola de cadena
[Descripción] Los dos punteros de cola de cola y cabeza de cola se pueden encapsular juntos, y el tipo de cola de cadena se puede definir como una estructuratipo【Código de ejemplo】// 定义链式队列结点 typedef struct LinkQueueNode { DataType data; // 结点数据 struct LinkQueueNode* next; // 指向下一个结点的指针 } LkQueNode; // 定义链式队列 typedef struct LkQueue { LkQueue* front; // 队头指针 LkQueue* rear; // 队尾指针 } LkQue; LkQue LQ;
【Explicación del código】
1. El código define el tipo de estructura de la cola encadenada y crea una instancia de cola.
2. La siguiente es una explicación del código:
DataType
es el tipo de datos de los elementos en la cola.3. Defina el tipo de estructura del nodo de cola de cadena
LinkQueueNode
:
data
son los datos almacenados en el nodo.next
Un puntero al siguiente nodo.4. Defina el tipo de estructura de la cola encadenada
LkQueue
:
front
Es el puntero de cabecera de la cola, que apunta al primer nodo de la cola.rear
Es el puntero de la cola de la cola, que apunta al último nodo de la cola.
5
.CreóLkQue LQ;
una instancia de una cola encadenadaLQ
para operaciones relacionadas con la cola encadenada.Tenga en cuenta que las palabras clave se utilizan en el código anterior
typedef
para definir nuevos nombres de tipoLkQueNode
yLkQue
para su uso posterior.【Aviso】
- LQ.front - el puntero de cabeza del equipo encadenado
- LQ.rear - el puntero de la cola del equipo encadenado
- Desbordamiento de equipos encadenados : se puede ignorar (debido al espacio dinámico de la aplicación)
- Desbordamiento del equipo encadenado : es decir, cuando el equipo encadenado está vacío, también se requiere abandonar el equipo;
➢En este momento, no hay ningún nodo real en la lista enlazada:➢ Provisiones:
- Cuando la cola de la cadena esté vacía, haga que el puntero posterior también apunte al nodo de encabezado.
➢Condiciones de desbordamiento de la cola de la cadena :
- LQ.front->siguiente==NULL
- 或:LQ. frente==LQ. trasero;
③ Operación básica de cola de cadena
Ⅰ Inicialización
【Código de ejemplo】
// 初始化链式队列 void initQueue(LkQue* LQ) { LkQueNode* temp; // 创建一个临时结点指针 // 分配内存以存储临时结点 temp = (LkQueNode*)malloc(sizeof(LkQueNode)); LQ->front = temp; // 将队头指针指向临时结点 LQ->rear = temp; // 将队尾指针指向临时结点 (LQ->front)->next = NULL; // 设置临时结点的下一个结点为空 }
【Diagrama esquemático】
【Explicación del código】
1. La función del código es inicializar la cola encadenada.
2. La siguiente es una explicación de comentario para cada línea de código:
LkQue* LQ
: el parámetro de puntero de cola encadenado entrante, que se utiliza para operar colas relacionadas.LkQueNode* temp
: crea un puntero de nodo de cola encadenado temporal.3. En la función, primero usamos
malloc
la función para asignar memoria para el nodo temporaltemp
para almacenar el nodo de cola de cadena.sizeof(LkQueNode)
Se utiliza para especificar el tamaño de la memoria que se asignará.Luego, tanto el puntero de cabeza de cola
LQ->front
como el puntero de cola de colaLQ->rear
se configuran para apuntar al nodo temporaltemp
, de modo que inicialmente solo hay este nodo en la cola.4.
(LQ->front)->next
Finalmente, establezca el siguiente puntero de nodo del nodo temporal enNULL
, lo que indica que este nodo no tiene un nodo sucesor.5. De esta forma, se completa la operación de inicialización de la cola.
Ⅱ Juzgar que la cola está vacía
【Código de ejemplo】
// 判断链式队列是否为空 int EmptyQueue(LkQue LQ) { if (LQ.rear == LQ.front) // 如果队尾指针和队头指针相同,则队列为空 return 1; // 返回1表示队列为空 else return 0; // 返回0表示队列非空 }
【Explicación del código】
1. La función del código es juzgar si la cola encadenada está vacía.
2. La siguiente es una explicación de comentario para cada línea de código:
int
: el tipo de retorno de la función es un número entero, lo que indica si la cola está vacía.LkQue LQ
: el parámetro de estructura de la cola encadenada entrante, que se utiliza para determinar si la cola está vacía.3. En la función, primero determinamos si la cola está vacía al juzgar
LQ.rear
si el puntero de cola de cola es el mismo que el puntero de cabeza de cola .LQ.front
Si es lo mismo, la cola está vacía porque no hay elementos en la cola.4. Si el puntero de cola de cola y el puntero de cabeza de cola no son iguales, significa que la cola no está vacía.
5. Finalmente, la función devuelve 1 para indicar que la cola está vacía y devuelve 0 para indicar que la cola no está vacía.
6. De esta forma, se completa la operación de juzgar si la cola está vacía.
Ⅲ Entrar en la cola
[Definición] Entrar en el equipo - insertar un elemento x al final del equipo, es decir, al final de la lista enlazada
Genere un nuevo nodo p (establezca su campo de datos en x y su campo de cadena en NULL) Inserte el nuevo nodo p al final de la tabla y conviértase en el nuevo nodo final de la cola【Diagrama esquemático】
【Código de ejemplo】
// 入队操作 void EnQueue(LkQue* LQ, DataType x) { LkQueNode* temp; // 创建一个临时结点指针 // 分配内存以存储新结点 temp = (LkQueNode*)malloc(sizeof(LkQueNode)); temp->data = x; // 设置新结点的数据为x temp->next = NULL; // 设置新结点的下一个结点为空 (LQ->rear)->next = temp; // 将新结点添加到队尾结点的后面 LQ->rear = temp; // 更新队尾指针为新结点 }
【Explicación del código】
1. La función del código es realizar la operación de puesta en cola de la cola en cadena.
2. La siguiente es una explicación de comentario para cada línea de código:
LkQue* LQ
: el parámetro de puntero de cola encadenado entrante, que se utiliza para operar colas relacionadas.DataType x
: poner en cola los datos.3. En la función, primero usamos
malloc
la función para asignar memoria para el nuevo nodotemp
para almacenar datos.sizeof(LkQueNode)
Se utiliza para especificar el tamaño de la memoria que se asignará.4. Luego, establecemos los datos del nuevo nodo
temp
como un parámetrox
, que representa los datos recién agregados a la cola.
(LQ->rear)->next
A continuación, establezca el puntero del siguiente nodo del nodo temporal entemp
y agregue el nuevo nodo después del nodo final.5. Finalmente, actualice el puntero de cola
LQ->rear
para que apunte al nuevo nodo de colatemp
.6. De esta manera, se completa la operación de puesta en cola.
Ⅳ Desencolar
[Definición] Fuera del equipo: elimine el elemento principal en el equipo encadenado y envíelo a e
- Considere subdesbordamiento no
- no se desborda, entonces:
- Tome la temperatura del nodo principal de la cola;
- Envía el elemento principal a x;
- Eliminar el nodo principal del equipo encadenado;
- Si solo hay un elemento en la cola encadenada, la cola estará vacía después de la eliminación y el puntero de cola de la cola debe modificarse;
- La temperatura del nodo regresa al sistema.
【Diagrama esquemático】
【Código de ejemplo】
// 出队操作 int OutQueue(LkQue* LQ) { LkQueNode* temp; // 创建一个临时结点指针 if (EmptyQueue(*LQ)) // 判断队列是否为空 { error("队空"); // 输出错误提示信息 return 0; // 返回0表示出队失败 } else { temp = (LQ->front)->next; // 获取队头结点的下一个结点 (LQ->front)->next = temp->next; // 将队头指针指向下一个结点 if (temp->next == NULL) // 如果出队后队列为空 LQ->rear = LQ->front; // 更新队尾指针为队头指针 free(temp); // 释放出队的结点 return 1; // 返回1表示出队成功 } }
【Explicación del código】
1. La función del código es realizar la operación de eliminación de la cola de la cadena.
2. La siguiente es una explicación de comentario para cada línea de código:
LkQue* LQ
: el parámetro de puntero de cola encadenado entrante, que se utiliza para operar colas relacionadas.3. En la función, primero juzgamos si la cola está vacía y
EmptyQueue(*LQ)
juzgamos llamando a la función. Si está vacío, se generará un mensaje de error"队空"
y se devolverá 0 para indicar un error en la eliminación de la cola.4. Si la cola no está vacía, ejecute la operación de eliminación de cola.
5. Primero apuntamos el puntero de nodo temporal
temp
al siguiente nodo del nodo principal de la cola, es decir, el nodo que se va a quitar de la cola.6.
(LQ->front)->next
Luego, configure el puntero del siguiente nodo del nodo principal de la cola para que seatemp->next
, es decir, apunte el puntero del comienzo de la cola al siguiente nodo del nodo de salida de la cola.7. A continuación, verificamos si la cola está vacía después de la operación de eliminación de cola y determinamos
temp->next
si lo estáNULL
. En caso afirmativo, significa que la cola está vacía después de salir de la cola, y el puntero de cola de cola debe actualizarseLQ->rear
al puntero de cabeza de colaLQ->front
.8. Finalmente, use
free
la función para liberar el espacio de los nodos que se descartan de la cola para evitar pérdidas de memoria.9. La función devuelve 1 para indicar que la eliminación de la cola se realizó correctamente. De esta forma, se completa la operación de dequeue.
Ⅴ Obtener el primer elemento de la cola
【Código de ejemplo】
// 获取队头元素的值 DataType GetHead(LkQue LQ) { LkQueNode* temp; // 创建一个临时结点指针 if (EmptyQueue(LQ)) // 判断队列是否为空 return NULLData; // 如果队列为空,则返回空数据 else { temp = LQ.front->next; // 获取队头结点的下一个结点 return temp->data; // 返回队头结点的数据 } }
【Explicación del código】
1. La función del código es obtener el valor del elemento cabeza de la cola encadenada.
2. La siguiente es una explicación de comentario para cada línea de código:
DataType GetHead(LkQue LQ)
: Obtiene el valor del elemento al principio de la cola, y el tipo de valor de retorno esDataType
.LkQue LQ
: el parámetro de la cola encadenada entrante, que se utiliza para obtener el elemento principal de la cola.3. En la función, primero juzgamos si la cola está vacía y
EmptyQueue(LQ)
juzgamos llamando a la función. Si la cola está vacía, devuelve datos vacíos directamenteNULLData
.4. Si la cola no está vacía, realizar la operación de obtención del elemento de cabeza de cola.
5. Primero apuntamos el puntero de nodo temporal
temp
al siguiente nodo del nodo de cabeza de cola, es decir, el elemento de cabeza de cola que se va a obtener.6. Luego, devuelva los datos del nodo principal de la cola
temp->data
.7. De esta forma se completa la operación de obtención del valor del elemento cabeza.
3. matriz
Matriz: puede considerarse como una tabla lineal especial. La característica especial es que los elementos también son una tabla lineal.
(1) Estructura lógica y operaciones básicas de arreglos
【Definición】Matriz : es una extensión de una tabla lineal , cada elemento del cual se compone de un valor y un conjunto de subíndices, y el número de subíndices se denomina dimensión de la matriz .
- Las matrices son el tipo de datos más familiar y, en los primeros lenguajes de alto nivel, las matrices eran el único tipo de datos disponible.
- Dado que cada elemento de la matriz tiene un tipo uniforme y los subíndices de los elementos de la matriz generalmente tienen límites superior e inferior fijos, el procesamiento de la matriz es más simple que otras estructuras complejas.
- Las matrices multidimensionales son una generalización de las listas lineales.
[Nota] Una vez que se define una matriz, su dimensión y el límite de la dimensión no cambiarán. Por lo tanto , además de la inicialización y destrucción de estructuras, los arreglos generalmente tienen solo dos operaciones básicas :
- read - Dado un conjunto de subíndices, lee el elemento de datos correspondiente
- Escribir : dado un conjunto de subíndices, modifique los elementos de datos correspondientes
[Matriz bidimensional] Matriz bidimensional: La matriz bidimensional A mn puede considerarse como un vector compuesto por m vectores fila , o como un vector compuesto por n vectores columna .
【Diagrama esquemático】
(2) La estructura de almacenamiento de la matriz
①Estructura de almacenamiento - estructura de almacenamiento secuencial
- Dado que la estructura de memoria de la computadora es unidimensional , para representar una matriz multidimensional con memoria unidimensional, es necesario organizar los elementos de la matriz en una secuencia en un cierto orden y luego almacenar esta secuencia lineal en la memoria.
- Y debido a que la matriz generalmente no se inserta ni elimina, es decir, una vez que se establece la matriz, la cantidad de elementos en la estructura y la relación entre los elementos no cambiará. Por lo tanto, el método de almacenamiento secuencial se usa generalmente para representar la matriz.
② Fórmula de direccionamiento (principalmente almacenada por fila)
La matriz bidimensional Amn se almacena en la memoria en "orden de fila principal", suponiendo que cada elemento ocupa k unidades de almacenamiento :
- La dirección de almacenamiento del elemento aij debe ser la dirección base de la matriz más el número de celdas ocupadas por los elementos delante de aij .
- Debido a que a ij está ubicado en la i-ésima fila y la j-ésima columna, hay i × n elementos en la i fila frontal, y hay j elementos frente a a ij en la i-ésima fila, por lo que hay i ×n+j elementos delante de él, entonces, la función de cálculo de dirección de un ij es:
LOC(aij)=LOC(a00)+(i*n+j)*k
(3) almacenamiento comprimido de matriz
Para ahorrar espacio de almacenamiento , podemos comprimir y almacenar este tipo de matriz : es decir, solo se asigna un espacio de almacenamiento para múltiples elementos idénticos distintos de cero; no se asigna espacio para elementos cero .
① Matriz especial
Matriz especial , es decir, una matriz en la que la distribución de elementos distintos de cero o elementos cero tiene ciertas reglas .
Almacenamiento comprimido de varias matrices especiales:
- Matriz simétrica
- matriz triangular
- matriz dispersa
② Matriz especial: matriz simétrica
Ⅰ Definición
[Definición] En una matriz cuadrada A de orden n, si los elementos satisfacen las siguientes propiedades, entonces A se denomina matriz simétrica:
- aij = ají
- 0≤i
- j≤n-1
[Ejemplo] La siguiente figura es una matriz simétrica de orden 5:
Ⅱ Almacenamiento físico
- Los elementos de la matriz simétrica son simétricos con respecto a la diagonal principal, por lo que siempre que se almacenen los elementos del triángulo superior o del triángulo inferior de la matriz, deje que cada dos elementos simétricos compartan un espacio de almacenamiento , de modo que casi la mitad del espacio de almacenamiento puede ser salvado.
- Sin pérdida de generalidad, almacenamos elementos debajo de la diagonal principal (incluidas las diagonales) en "primer orden de fila", y el formato de almacenamiento se muestra en la figura:
- En esta matriz triangular inferior, la fila i tiene exactamente i elementos y el número total de elementos es:
∑(i)=n(n+1)/2
- Por tanto, podemos almacenar estos elementos en un arreglo unidimensional S[0..n(n+1)/2-1] en el orden indicado por las flechas en la figura .
- Para facilitar el acceso a los elementos de la matriz simétrica A, debemos encontrar una correspondencia entre aij y S[k].
Fórmula de transformación de subíndice: (representado por el triángulo a continuación )
- Si i≥j , entonces aij está en el triángulo inferior: hay 1+2+…+i=i(i+1)/2 elementos en la fila i antes de aij (desde la fila 0 hasta la fila i-1), En línea i, hay exactamente j elementos antes de aij (es decir, ai0, ai1, ai2, ai3,…,ai j-1), entonces:
- Si i<j , entonces aij está en la matriz triangular superior: debido a que aij=aji, simplemente intercambie i y j en la relación correspondiente anterior para obtener:
- Con la relación de intercambio de subíndices anterior, para cualquier conjunto dado de subíndices (i, j), el elemento de matriz aij se puede encontrar en S[k], de lo contrario, para todo k=0,1,2,3,...n (n+1)/2-1, puede determinar la posición (i, j) del elemento en S[k] en la matriz. Por lo tanto, S[n(n+1)/2] se denomina almacenamiento comprimido de la matriz simétrica A, como se muestra en la siguiente figura:
- Por ejemplo, a31 y a13 se almacenan en sa[7] porque:
k=i*(i+1)/2+j=3*(3+1)/2+1=7
③ Matriz especial: matriz triangular
Ⅰ Definición
[Definición] Dividida por la diagonal principal, la matriz triangular tiene dos tipos: triangular superior y triangular inferior:
- La matriz triangular superior se muestra en la figura, y los elementos en su triángulo inferior (excluyendo la diagonal principal) son todos constantes.
- Una matriz triangular inferior es todo lo contrario, con constantes por encima de la diagonal principal, como se muestra en la figura.
- En la mayoría de los casos, la constante de la matriz triangular es cero.
【Ejemplo】
【ilustrar】
El elemento repetido c en la matriz triangular puede compartir un espacio de almacenamiento, y los elementos restantes tienen exactamente n(n+1) / 2. Por lo tanto, la matriz triangular se puede comprimir y almacenar en el vector s[0..n(n +1)/2 ], donde c se almacena en el último componente del vector.
Ⅱ Matriz triangular superior
[Explicación] En la matriz triangular superior , la p-ésima fila (0≤p<n) sobre la diagonal principal tiene exactamente np elementos. Cuando los elementos a ij en la matriz triangular superior se almacenan en el orden de la fila , el There son (np)=i(2n-i+1)/2 elementos en la línea i, y hay exactamente ji elementos antes de a ij en la línea i: a ij , a ij +1 , … a ij-1 .[Fórmula] Por lo tanto, la relación correspondiente entre s[k] y aij es :
Ⅲ Matriz triangular inferior
[Fórmula] El almacenamiento de la matriz triangular inferior es similar al de una matriz simétrica, y la relación correspondiente entre s[k] y aij es:
④ Matriz especial: matriz dispersa
Ⅰ Definición
Matriz dispersa : suponga que hay s elementos distintos de cero en la matriz A, si s es mucho más pequeño que el número total de elementos de la matriz, entonces A se denomina matriz dispersa .
- Almacenamiento comprimido de matrices dispersas , es decir, solo se almacenan elementos distintos de cero en matrices dispersas.
- Propósito: Ahorra espacio de almacenamiento .
Ⅱ trillizos
- Dado que la distribución de elementos distintos de cero es generalmente irregular , la posición (i, j) de la fila y la columna donde se encuentra también debe registrarse mientras se almacena el elemento distinto de cero.
- Por el contrario, un triplete (i, j, a ij ) identifica de forma única una entrada distinta de cero de la matriz A.
- Por lo tanto, una matriz dispersa se puede identificar de forma única mediante tripletas que representan elementos distintos de cero y su número de filas y columnas.
Ⅲ Mesa triple
La siguiente tabla de tripletes:
( (0,1,12),(0,2,9),(2,0,- 3),(2,5,14),(3,2,24), (4,1,18), (5,0,15),(5,3,-7) )
- Agregar el par de valores de fila y columna (5,6) se puede usar como otra descripción de la siguiente matriz M.
- Los diferentes métodos de representación de la tabla triple mencionada anteriormente pueden conducir a diferentes métodos de almacenamiento de compresión para matrices dispersas.
Ⅳ Lista de secuencias triples
[Representación] La representación de la tabla de secuencia triple de la matriz dispersa—— Convierta los elementos distintos de cero en la matriz en triples y guárdelos en la memoria en el orden no decreciente de las filas (orden creciente de las filas en las columnas) .[Estructura de tabla triple] Estructura de tabla triple: suponiendo que la tabla triple está representada por una estructura de almacenamiento secuencial, se puede obtener el momento escasoUn método de almacenamiento comprimido para arreglos: tabla de secuencia triple.[Código de ejemplo] Tipo de almacenamiento de tabla de triplete de matriz dispersa:const int maxnum = 10; // 定义非零元素的最大个数为10 typedef struct node { int i, j; // 非零元的行下标和列下标 DataType v; // 非零元素的值 } NODE; // 定义三元组结构体 // 定义稀疏矩阵结构体 typedef struct spmatrix { NODE data[maxnum]; // 非零元三元组表 int mu, nu, tu; // 矩阵的行数、列数和非零元个数 } SpMtx;
[Diagrama esquemático] Supongamos: SpMtrx M ; Entonces la representación del triplete de la matriz dispersa que se muestra en la siguiente figura es la siguiente:
【Explicación del código】1. La siguiente es una explicación de comentario para cada línea de código:
const int maxnum = 10;
Se define una constantemaxnum
que indica que el número máximo de elementos distintos de cero es 10.typedef struct node
define unnode
tipo de estructura llamado .int i, j;
node
En la estructura se definen dos variables enterasi
y ,j
que representan respectivamente el subíndice de fila y el subíndice de columna de elementos distintos de cero.DataType v;
Una variable de tiponode
se define en la estructura , que representa el valor del elemento distinto de cero.DataType
v
NODE;
Se define el tipoNODE
, que es una estructura de triplete.typedef struct spmatrix
define unspmatrix
tipo de estructura llamado .NODE data[maxnum];
Se define una matriz enspmatrix
la estructuradata
, que se utiliza para almacenar la tabla triple de elementos distintos de cero. El tamaño de la matriz esmaxnum
, que es el número máximo de elementos distintos de cero.int mu, nu, tu;
Tres variables enteras , yspmatrix
se definen en la estructura , representando respectivamente el número de filas, columnas y elementos distintos de cero de la matriz.mu
nu
tu
SpMtx;
El tipo está definidoSpMtx
, que es una estructura de matriz dispersa.2. Este código define una estructura de datos de matriz dispersa
SpMtx
, que consta de una matriz de tripletesdata
y tres variables enterasmu
,nu
ytu
.3. La
data
matriz se utiliza para almacenar la tabla de tripletes de los elementos distintos de cero de la matriz dispersa, ymu
,nu
ytu
representa el número de filas, columnas y elementos distintos de cero de la matriz, respectivamente.4.
maxnum
Limite el número máximo de elementos distintos de cero.