Lenguaje C_(13)_lista enlazada unidireccional (fácil de entender, solo lea esto para comprender la lista enlazada)

Tabla de contenido

El concepto de lista enlazada.

0. La composición de la lista enlazada.

1. Crea un puntero de cabeza

2. Método de inserción de la cabeza

3. Imprimir lista enlazada

4. Determine si la lista vinculada está vacía.

5. Calcule el número de nodos efectivos en la lista vinculada.

6. Método de taponamiento de cola

7. Método de eliminación de cabeza

8. Método de eliminación de cola

9. Eliminar lista enlazada

10. Código fuente

resultado de la operación


El concepto de lista enlazada.

La lista vinculada es una estructura de almacenamiento no secuencial y no secuencial en la estructura de almacenamiento físico. El orden lógico de los elementos de datos se realiza a través del orden de conexión del puntero en la lista vinculada.

Cada nodo contiene su campo de datos y su campo de puntero. El campo de datos se utiliza para almacenar los datos de este nodo y el campo de puntero almacena la dirección del siguiente nodo vinculado por este nodo. Los nodos están unidos entre sí para formar un nodo.

Entonces, cómo vincular cada nodo y cómo formar una estructura de almacenamiento no secuencial y no secuencial. Podemos ver la siguiente figura para entender.

A partir de un nodo con datos vacíos, genere un nuevo nodo, almacene los datos que desea almacenar en el campo de datos del nuevo nodo y continúe almacenando la dirección del siguiente nodo en el campo de puntero del nodo actual, si hay No hay ningún siguiente nodo, luego establezca el campo de puntero del último nodo (NULL).

0. La composición de la lista enlazada.

La lista vinculada se compone de nodos. Podemos usar una estructura para formar cada nodo y luego podemos crear un tipo de datos de nodo.

//结点
typedef struct NodeName
{
          char *name;//数据域
          struct NodeName *next;//指针域
}namelist;

1. Crea un puntero de cabeza

Aquí primero creamos un nodo principal y configuramos el campo de datos del nodo principal en 0 (sin sentido) y el campo de puntero en NULL (para evitar punteros salvajes).

int main(int argc, char const *argv[])
{
         namelist head = {NULL,NULL};//头结点
         namelist *phead = &head;//头结点的指针
         return 0;
}

2. Método de inserción de la cabeza

Si quiero insertar un nuevo nodo al principio de la lista vinculada, este método se llama inserción de encabezado. Entonces, ¿cómo insertamos este nodo al frente, asumiendo que hay otros nodos antiguos detrás? Entonces, ¿cómo podemos insertar este nuevo nodo sin perder contacto con los nodos antiguos detrás?

Entonces tenemos que hacer que el campo de puntero del nuevo nodo apunte al nodo antiguo (campo de puntero de phead), insertar el campo de datos del nuevo nodo y dejar que el campo de puntero de phead apunte al nuevo nodo.

//头插法
int CreatHeadNode(namelist *phead, char *pname)
{
          namelist *NewHeadTmp = NULL;//创建新节点
          NewHeadTmp = malloc(sizeof(namelist));//分配堆空间
          if(NULL == NewHeadTmp)//如果申请空间失败,结束!
          {
                    printf("malloc NewHeadTmp failed\n");
                    return -1;
          }
          NewHeadTmp->next = phead->next;//将旧结点的地址给到新插入结点的地址域
          NewHeadTmp->name = pname;//传入数据
          phead->next = NewHeadTmp;//将新节点的地址给到Phead的地址域

          return 0;
}

3. Imprimir lista enlazada

Insertamos los datos del nombre mediante la inserción de encabezado, entonces, ¿cómo podemos ver los datos que insertamos?

Aquí pasamos phead a la función de imprimir la lista vinculada, y luego creamos un puntero p que apunta al campo de puntero de phead, que es la dirección del siguiente nodo, y luego imprimimos el campo de datos del nodo, y luego deje p paso a paso Luego apunte a cada nodo, imprima el campo de datos de cada nodo, hasta que el campo de puntero del último nodo sea NULL y finalice la impresión. Podemos usar un método similar de recorrido de matriz de cadenas para encontrar \0, aquí encontramos si el campo de puntero del último nodo es NULL;

//打印链表
void PrintfNode(namelist *phead)
{
          namelist *p = NULL;
          p = phead->next;//让p指向第一个结点
          while (NULL != p)//在p为NULL的时候结束循环
          {
                    printf("%s\n", p->name);
                    p = p->next;//指向下一个结点
          }      
}

resultado de la operación 

Aquí inserté tres nodos, el orden no es Zhang San, Li Si, Wang Wu. Debido a que es el método de inserción del encabezado, el orden de impresión se invierte.

int main(int argc, char const *argv[])
{
         namelist head = {NULL,NULL};//头结点
         namelist *phead = &head;//头结点的指针

         CreatHeadNode(phead,"张三");
         CreatHeadNode(phead,"李四");
         CreatHeadNode(phead,"王五");
         PrintfNode(phead);
         return 0;
}

4. Determine si la lista vinculada está vacía.

Lógica simple, sin análisis.

//判断链表是否为空
int JudgeNull(namelist *phead)
{
          return (NULL == phead->next);//为空返回1,不为空返回0
}

5. Calcule el número de nodos efectivos en la lista vinculada.

La idea de calcular el número de nodos es la misma que la idea de imprimir los nodos de la lista vinculada anterior. Solo necesitamos definir una variable de recuento en la función y agregarla hasta que atraviese a NULL para obtener el número.

//计算链表结点个数
int CountNode(namelist *phead)
{
          int count = 0;
          namelist *p = NULL;
          p = phead->next;

          while(NULL != p)//遍历
          {
                    count++;//计数
                    p = p->next;
          }
          return count;//返回结点个数
}

resultado de la operación 

Utilicé el método de interpolación de dos cabezales para imprimir el campo de datos del nodo y el número de nodos en la lista vinculada, respectivamente.

        código de función principal

int main(int argc, char const *argv[])
{
         namelist head = {NULL,NULL};//头结点
         namelist *phead = &head;//头结点的指针

         CreatHeadNode(phead,"张三");
         CreatHeadNode(phead,"李四");
         CreatHeadNode(phead,"王五");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数

         CreatHeadNode(phead,"托马斯");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数

          return 0;
}

6. Método de taponamiento de cola

Analizamos el método de inserción del encabezado y una serie de impresiones, conteos y juicios NULL arriba. A continuación, hablemos de la inserción de la cola.

En el método de interpolación de cola, los parámetros que pasamos a los parámetros de la función son los valores de Phead y los campos de datos.

Bajo la premisa de la inserción de cola , tenemos que juzgar si la lista vinculada es una lista vinculada vacía . Si es una lista vinculada vacía, ¿para qué cola debemos insertar la cola?

Entonces usamos lo que mencionamos anteriormente para determinar si la lista vinculada está vacía. Si está vacía, usamos el método de inserción de encabezado para crear un nuevo nodo primero, y luego la siguiente inserción no estará vacía. La lista vinculada se puede insertar por el método de inserción de la cola.

Al ingresar al método de inserción de cola, primero usamos un puntero para recorrer la última lista vinculada antes de la inserción de cola, y luego damos la dirección de la nueva lista vinculada al campo de puntero de la lista vinculada de cola antes de la inserción, y luego cargamos los datos. y luego coloque el campo de puntero de la lista vinculada final después de la inserción set NULL;

//尾插法
int CreatTailNode(namelist *phead, char *pname)
{

          if(JudgeNull(phead))//如果为空链表
          {
                    CreatHeadNode(phead,pname);
          }
          else
          {
                    namelist *NewTailTmp = NULL;
                    NewTailTmp = malloc(sizeof(namelist));
                    if(NULL == NewTailTmp)
                    {
                              printf("malloc NewTailTmp failed!\n");
                              return -1;
                    }
                    namelist *p = phead ->next;
                    while(NULL != p->next)//遍历
                    {
                              p = p->next;
                    }
                    p->next = NewTailTmp;//将新结点的地址,给到插入前最后一个结点的指针域
                    NewTailTmp->name = pname;//插入数据域
                    NewTailTmp->next = NULL;//将尾插结点的指针域置NULL
          }
          return 0;
}

resultado de la operación 

 Inserté dos datos más al final para compararlos sin inserción final.

int main(int argc, char const *argv[])
{
         namelist head = {NULL,NULL};//头结点
         namelist *phead = &head;//头结点的指针
         CreatHeadNode(phead,"张三");
         CreatHeadNode(phead,"李四");
         CreatHeadNode(phead,"王五");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
         CreatHeadNode(phead,"托马斯");
         CreatTailNode(phead,"詹姆斯");
         CreatTailNode(phead,"约翰逊");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          return 0;
}

7. Método de eliminación de cabeza

Hablamos sobre cómo insertar un nodo y hablemos sobre cómo eliminar un nodo.

Solo necesitamos asignar el campo de puntero del nodo que se eliminará al campo de puntero de phead y luego usar la función free () para liberarlo.

//删除头结点
void DeleteHeadNode(namelist *phead)
{
          if(!JudgeNull(phead))//如果不为空链表
          {
                    namelist *p = NULL;
                    p = phead->next;//p为删除结点的地址
                    phead->next = p->next;//将删除结点的指针域给到phead的指针域
                    free(p);//删除释放头结点
          }
}

resultado de la operación

Contenido de la función principal

int main(int argc, char const *argv[])
{
         namelist head = {NULL,NULL};//头结点
         namelist *phead = &head;//头结点的指针
         CreatHeadNode(phead,"张三");
         CreatHeadNode(phead,"李四");
         CreatHeadNode(phead,"王五");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
         CreatHeadNode(phead,"托马斯");
         CreatTailNode(phead,"詹姆斯");
         CreatTailNode(phead,"约翰逊");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
         DeleteHeadNode(phead);
         PrintfNode(phead);//打印链表
         printf("=======删除头结点后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          return 0;
}

8. Método de eliminación de cola

Si existe un método de poda de cabeza, debe haber un método de poda de cola.

La idea es atravesar hasta el penúltimo nodo, liberar y eliminar el campo de puntero del penúltimo nodo (es decir, la dirección del penúltimo nodo) y luego configurar el campo de puntero del penúltimo nodo a NULL para completar Eliminar, porque se usa el penúltimo nodo, por lo que si el número de nodos es menor que dos, el método de inserción de la cola no se completará, usamos el método de inserción de la cabeza para completar el eliminación, por lo que primero determinamos el número de nodos válidos y luego procedemos con el método de inserción de cola.

//删除尾结点
void DeleteTailNode(namelist *phead)
{
          if(2 <= CountNode(phead))//超过两个结点
          {
                    namelist *p = NULL;
                    p = phead->next;
                    while(NULL != p->next->next)//遍历到倒数第二个结点
                    {
                              p = p->next;
                    }
                    free(p->next);//释放删除尾结点
                    p->next = NULL;//将现在的最后结点的指针域置NULL
          }
          else//不超过两个结点
          {
                    DeleteHeadNode(phead);
          }
}

resultado de la operación

Contenido de la función principal

int main(int argc, char const *argv[])
{
         namelist head = {NULL,NULL};//头结点
         namelist *phead = &head;//头结点的指针
         CreatHeadNode(phead,"张三");
         CreatHeadNode(phead,"李四");
         CreatHeadNode(phead,"王五");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
         CreatHeadNode(phead,"托马斯");
         CreatTailNode(phead,"詹姆斯");
         CreatTailNode(phead,"约翰逊");
         PrintfNode(phead);//打印链表
         printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
         DeleteHeadNode(phead);
         PrintfNode(phead);//打印链表
         printf("=======删除头结点后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
         DeleteTailNode(phead);
         PrintfNode(phead);//打印链表
         printf("=======删除尾结点后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数

          return 0;
}

9. Eliminar lista enlazada

Entonces, ¿cómo eliminamos toda la lista vinculada? Después de aprender la eliminación de la cabeza y la eliminación de la cola, es muy fácil eliminar la lista vinculada. Escribimos un juicio de bucle. Mientras la lista vinculada esté siempre vacía, siempre realizaremos el método de eliminación de la cabeza o la eliminación de la cola. La eficiencia de El método de eliminación del encabezado es más alto que el método de eliminación de la cola, así que use el encabezado para eliminarlo.

//删除链表
void DeleteList(namelist *phead)
{
          while (!JudgeNull(phead))
          {
                    DeleteHeadNode(phead);
          }
          printf("已清空链表!\n");        
}

 resultado de la operación

función principal

int main(int argc, char const *argv[])
{
          namelist head = {NULL,NULL};//头结点
          namelist *phead = &head;//头结点的指针
          CreatHeadNode(phead,"张三");
          CreatHeadNode(phead,"李四");
          CreatHeadNode(phead,"王五");
          PrintfNode(phead);//打印链表
          printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          CreatHeadNode(phead,"托马斯");
          CreatTailNode(phead,"詹姆斯");
          CreatTailNode(phead,"约翰逊");
          PrintfNode(phead);//打印链表
          printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          DeleteHeadNode(phead);
          PrintfNode(phead);//打印链表
          printf("=======删除头结点后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          DeleteTailNode(phead);
          PrintfNode(phead);//打印链表
          printf("=======删除尾结点后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          DeleteList(phead);
          PrintfNode(phead);//打印链表
          printf("=======删除链表后后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          return 0;
}

10. Código fuente

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

//结点
typedef struct NodeName
{
          char *name;//数据域
          struct NodeName *next;//指针域
}namelist;

//头插法
int CreatHeadNode(namelist *phead, char *pname)
{
          namelist *NewHeadTmp = NULL;//创建新节点
          NewHeadTmp = malloc(sizeof(namelist));//分配堆空间
          if(NULL == NewHeadTmp)//如果申请空间失败,结束!
          {
                    printf("malloc NewHeadTmp failed\n");
                    return -1;
          }
          NewHeadTmp->next = phead->next;//将旧结点的地址给到新插入结点的地址域
          NewHeadTmp->name = pname;//传入数据
          phead->next = NewHeadTmp;//将新节点的地址给到Phead的地址域

          return 0;
}
//打印链表
void PrintfNode(namelist *phead)
{
          namelist *p = NULL;
          p = phead->next;//让p指向第一个结点
          while (NULL != p)//在p为NULL的时候结束循环
          {
                    printf("%s\n", p->name);
                    p = p->next;//指向下一个结点
          }      
}
//判断链表是否为空
int JudgeNull(namelist *phead)
{
          return (NULL == phead->next);//为空返回1,不为空返回0
}
//计算链表结点个数
int CountNode(namelist *phead)
{
          int count = 0;
          namelist *p = NULL;
          p = phead->next;

          while(NULL != p)//遍历
          {
                    count++;//计数
                    p = p->next;
          }
          return count;//返回结点个数
}
//尾插法
int CreatTailNode(namelist *phead, char *pname)
{

          if(JudgeNull(phead))//如果为空链表
          {
                    CreatHeadNode(phead,pname);
          }
          else
          {
                    namelist *NewTailTmp = NULL;
                    NewTailTmp = malloc(sizeof(namelist));
                    if(NULL == NewTailTmp)
                    {
                              printf("malloc NewTailTmp failed!\n");
                              return -1;
                    }
                    namelist *p = phead ->next;
                    while(NULL != p->next)//遍历
                    {
                              p = p->next;
                    }
                    p->next = NewTailTmp;//将新结点的地址,给到插入前最后一个结点的指针域
                    NewTailTmp->name = pname;//插入数据域
                    NewTailTmp->next = NULL;//将尾插结点的指针域置NULL
          }
          return 0;
}
//删除头结点
void DeleteHeadNode(namelist *phead)
{
          if(!JudgeNull(phead))//如果不为空链表
          {
                    namelist *p = NULL;
                    p = phead->next;//p为删除结点的地址
                    phead->next = p->next;//将删除结点的指针域给到phead的指针域
                    free(p);//删除释放头结点
          }
}
//删除尾结点
void DeleteTailNode(namelist *phead)
{
          if(2 <= CountNode(phead))//超过两个结点
          {
                    namelist *p = NULL;
                    p = phead->next;
                    while(NULL != p->next->next)//遍历到倒数第二个结点
                    {
                              p = p->next;
                    }
                    free(p->next);//释放删除尾结点
                    p->next = NULL;//将现在的最后结点的指针域置NULL
          }
          else//不超过两个结点
          {
                    DeleteHeadNode(phead);
          }
}
//删除链表
void DeleteList(namelist *phead)
{
          while (!JudgeNull(phead))
          {
                    DeleteHeadNode(phead);
          }
          printf("已清空链表!\n");        
}
int main(int argc, char const *argv[])
{
          namelist head = {NULL,NULL};//头结点
          namelist *phead = &head;//头结点的指针
          CreatHeadNode(phead,"张三");
          CreatHeadNode(phead,"李四");
          CreatHeadNode(phead,"王五");
          PrintfNode(phead);//打印链表
          printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          CreatHeadNode(phead,"托马斯");
          CreatTailNode(phead,"詹姆斯");
          CreatTailNode(phead,"约翰逊");
          PrintfNode(phead);//打印链表
          printf("==========结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          DeleteHeadNode(phead);
          PrintfNode(phead);//打印链表
          printf("=======删除头结点后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          DeleteTailNode(phead);
          PrintfNode(phead);//打印链表
          printf("=======删除尾结点后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          DeleteList(phead);
          PrintfNode(phead);//打印链表
          printf("=======删除链表后后结点个数count=%d==========\n",CountNode(phead));//打印此时结点个数
          return 0;
}

resultado de la operación

Supongo que te gusta

Origin blog.csdn.net/m0_58193842/article/details/128398602
Recomendado
Clasificación