La realización de listas circulares enlazadas individualmente y operaciones relacionadas.

Lista circular enlazada individualmente

Si hay alguna deficiencia, la corregiré. Entiendo que hay errores inevitables. Por favor, perdóname.

Hay muchas repeticiones y similitudes entre las listas enlazadas simples y las listas enlazadas dobles anteriores a las tres listas enlazadas de listas enlazadas circulares. La relación lógica general es la misma, la diferencia radica en la relación entre el primero y cada nodo

Lista enlazada individualmente : cada nodo está enlazado por punteros (la dirección es cabeza -> cola ). El nodo principal y el nodo cola -> siguiente son todos nulos.   Lista enlazada doble : hay dos punteros entre cada nodo (dirección entre sí ) nodo principal -> nodo anterior y final -> siguiente son nulos

(La lista de enlace único y la lista de enlace doble son esencialmente listas de enlace único)

Lista enlazada circular: reproduzca completamente la lista enlazada individualmente, la única diferencia es el nodo de cola -> siguiente = nodo principal

En resumen, se puede ver que la realización de listas enlazadas circulares se reproduce completamente en listas enlazadas individualmente, excepto para el procesamiento de nodos de cola.

1> Inicializar lista enlazada individualmente

Igual que la lista enlazada individualmente, la única diferencia es que el nodo principal apunta a la calle principal (la cabecera de la tabla inicial es tanto el nodo principal como el nodo final )

void InitLinkList(LinkList &L)//初始化单链表,强调表所以用LinkList
{
	L = (LNode*)malloc(sizeof(LNode));//为头节点开辟空间
	if (L == NULL)
	{
		printf("为头节点分配空间失败!\n");
	}
	else {
		L->next = L;//初始表头既是头又是尾
		printf("初始化成功\n"); 
	}
}

Definir si una función es una lista vacía

void Empty(LinkList L)
{
	if (L->next == L)
		printf("表头为空,分配成功\n");
}

2> Asignar un valor a la lista vinculada

El código es el mismo que el de la lista enlazada individualmente, la única diferencia es que se procesa el nodo final, se encuentra el nodo final y el puntero apunta al nodo principal.

void CreatList(LinkList &L)//输入数据
{
	LNode *P, *D;//DATA是用来保持每次输入的数据,P的作用是指向单链表尾部
	L = (LNode*)malloc(sizeof(LNode));//创建头节点
	L->next = NULL;//初始化单链表,一开始为空表
	P = L;//空表时头节点也是尾部节点
	int n;//输入数据的个数
	printf("请输入数据的个数:");
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		D = (LinkList)malloc(sizeof(LNode));//给D节点开辟一个空间
		printf("data[%d]=", i);
		scanf("%d", &D->data);//每次输入的数据到D
		D->next = P->next;//第一个节点已经填充,将移动下一个节点
		P->next = D;//D代表的是一个节点,P->next是指向下一个节点
		P = D;
		if (i==n - 1)
		{
			P->next = L;//尾节点指针指向头节点
		}
	}

}

Simplemente agregue un juicio dentro del ciclo para determinar si es un nodo de cola y apúntelo al nodo principal L (si L-> siguiente = NULL es lo mismo porque su asignación sobrescribirá los datos sucios pero los escribirá de manera más rigurosa)

Recuerde que el juicio del final del ciclo es el juicio (algunos escritos descuidadamente = tendrán resultados diferentes como sigue)

Después de ingresar el primer elemento, parpadeará y emitirá directamente

 

3> La salida de la lista vinculada

void ShowList(LinkList L)
{
	LNode * P;
	P = (LNode*)malloc(sizeof(LNode));//分配空间
	P = L->next;//单链表从P点开始遍历,等同于从头节点开始
	int i = 0;//记录位序
	printf("打印单链表\n");
	while (P != NULL&&P!=L)//只要节点不为空就可以继续输出
	{
		printf("data[%d]=%d\n", i, P->data);
		i++;
		P = P->next;
	}

La lógica de salida se encuentra en la lógica de entrada , y la única diferencia es que el último paso del procesamiento apunta al puntero del nodo de cola al encabezado de la tabla . La condición de juicio de bucle de la lógica de salida está a punto de cambiar

Análisis: cuando la variable alcanza el último nodo, la condición de juicio de la lista enlazada individualmente es (nodo-> siguiente! = Nulo), si el siguiente nodo del nodo está vacío, saltará del ciclo. Ahora, para la lista enlazada circular, además de ( nodo-> siguiente! = Nulo), el último nodo debe ser juzgado. Dado que el recorrido del nodo es P = P-> siguiente, el siguiente nodo apuntado por la dinámica nodo cada vez es el siguiente nodo.

Experiencia personal : Cuando escribí por primera vez, agregué P-> next! = L a mi condición de juicio. Parece que no hay problema, pero el código dentro del ciclo (P = P-> next) ha apuntado al nodo de cola al nodo principal (L), por lo que si juzga de esta manera, habrá problemas con la salida y se generará un nodo de cola menos (la salida del código de error en la siguiente figura)

4> Búsqueda en lista vinculada

Lista vinculada individualmente : si busca en relación con el nodo, debido a que no tiene las características de una consulta aleatoria, solo puede atravesar el nodo completo desde el nodo principal para encontrar el nodo requerido

Lista doblemente enlazada : el mismo principio pero no tan bien entendido y la naturaleza del nodo precursor de una sola cadena a nodo no puede procesar, la lista doblemente enlazada, como una mayor flexibilidad (y eliminar los nodos i e i + 2 e i-2 nodos ), si el procesamiento de lista de enlace único necesita recorrerse varias veces (también se puede hacer a la vez, pero es más problemático y requiere varios nodos de evaluación), mientras que la lista de enlace doble solo necesita recorrerse una vez. Aplicable a diferentes entornos, cada uno tiene sus propias características

Lista vinculada circular: si es necesario eliminar todos los nodos, pero cada vez que se elimina un nodo y es el nodo de cola, en tales condiciones, la lista de vínculo simple y la lista de vínculo doble se eliminan una vez y se recorren una vez, lo que desperdiciará mucho tiempo y recursos. Pero la lista enlazada circular puede resolver este problema. En el caso de procesamiento frecuente de cabeza y cola, el puntero puede apuntar directamente al nodo de cola (nodo de cola -> el siguiente es el nodo de cabeza) ahorrará mucho tiempo y recursos. Pero depende de la situación, aquí está el elemento de búsqueda habitual

void GetElem(LinkList L, int i)
{
	if (i < 0)
		printf("查询位置不合法");
	else {
		LNode* P;//创建一个记录节点的指针
		int number = 1;//记录查询到几个节点
		P = L->next;//指向头节点,从头节点开始查询变量
		if (i == 0)
			printf("头节点为空");//头节点不存放数据
		while (P != NULL && number < i)
		{
			P = P->next;//寻找到第i节点
			number++;
			if (P->next ==L)
			{
				P->next = L->next;
			}
		}
		printf("查询第%d个元素为%d\n", i, P->data);
	}

}

La búsqueda bit a bit es básicamente la misma que la de una lista enlazada individualmente. He procesado el nodo de cola aquí para reflejar la lista enlazada circular. Se puede emitir un juicio en el nodo de cola. Si se atraviesa el nodo de cola, el puntero puede apuntar al primer nodo (el primer nodo después del nodo de cabeza). De hecho, este método también se puede utilizar para juzgar la legalidad del posición de inserción. Si los elementos de consulta en la lista no obtienen la longitud del caso ha llegado al nodo final, también se puede enviar la consulta (no más allá del alcance de la lista de consultas) pero esto se repite en un diseño de un solo golpe, hay sin acceso directo a la longitud de la lista de empatía de alta disponibilidad

De manera similar, el principio de consulta por valor es el mismo que el de las listas enlazadas individualmente, que se omite aquí.

5> Eliminar datos de la lista vinculada

El código de datos de eliminación es consistente con la lista enlazada individualmente, y el procesamiento en el epítopo solo necesita hacer que el nodo i-1 apunte a L ( p-> siguiente = q-> siguiente; ) ya está implícito

Eliminar el elemento i-th

Pasos: Primero tenemos que encontrar el nodo i-1th -> juzgar si el nodo i-1 es el nodo de cola (Sí: eliminar el nodo que no está en la lista vinculada, No: eliminar el nodo i-th) - > eliminar el nodo i-ésimo después del nodo (apunte el nodo i-1 al nodo principal y suelte el nodo i)

void ListDelet(LinkList &L, int i)
{
	if (i < 1)
		printf("删除位置不合法");
	LNode *p;//用来指向查询元素的指针
	int number = 0;//记录节点的位置
	int e=0;//用来保存删除数据
	p = L;//查询节点应从头开始,所以指向头节点
	while (p != NULL && number < i - 1)
	{
		p = p->next;//只是寻找到第i-1节点
		number++;
	}
	if (p == NULL)//这里是说明了i-1是尾节点
	{
		printf("删除内容为空");
	}
	else {
		LNode*q = p->next;
		e = q->data;//记录删除的数据
		if (q->next = L)
		{
			p->next = L;
			free(q);//释放掉该节点
		}
		else {
			p->next = q->next;
			free(q);//释放掉该节点
		}
		printf("删除第%d节点元素%d成功\n", i, e);
	}
		
}

6> Código general

#include<stdio.h>
#include<stdlib.h>
typedef struct LNode
{
	int data;//保存每个节点数据的变量
	struct LNode *next;//指向下一个节点的指针
}LNode,*LinkList;

void InitLinkList(LinkList &L)//初始化单链表,强调表所以用LinkList
{
	L = (LNode*)malloc(sizeof(LNode));//为头节点开辟空间
	if (L == NULL)
	{
		printf("为头节点分配空间失败!\n");
	}
	else {
		L->next = L;//初始表头既是头又是尾
		printf("初始化成功\n"); 
	}
}

void Empty(LinkList L)//检查表是否为空
{
	if (L->next == L)
		printf("表头为空,分配成功\n");
}

void CreatList(LinkList &L)//输入数据
{
	LNode *P, *D;//DATA是用来保持每次输入的数据,P的作用是指向单链表尾部
	L = (LNode*)malloc(sizeof(LNode));//创建头节点
	L->next = NULL;//初始化单链表,一开始为空表
	P = L;//空表时头节点也是尾部节点
	int n;//输入数据的个数
	printf("请输入数据的个数:");
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		D = (LinkList)malloc(sizeof(LNode));//给D节点开辟一个空间
		printf("data[%d]=", i);
		scanf("%d", &D->data);//每次输入的数据到D
		D->next = P->next;//第一个节点已经填充,将移动下一个节点
		P->next = D;//D代表的是一个节点,P->next是指向下一个节点
		P = D;
		if (i==n - 1)
		{
			P->next = L;//尾节点指针指向头节点
		}
	}

}


void GetElem(LinkList L, int i)
{
	if (i < 0)
		printf("查询位置不合法");
	else {
		LNode* P;//创建一个记录节点的指针
		int number = 1;//记录查询到几个节点
		P = L->next;//指向头节点,从头节点开始查询变量
		if (i == 0)
			printf("头节点为空");//头节点不存放数据
		while (P != NULL && number < i)
		{
			P = P->next;//寻找到第i节点
			number++;
			if (P->next ==L)
			{
				P->next = L->next;
			}
		}
		printf("查询第%d个元素为%d\n", i, P->data);
	}

}

void ListDelet(LinkList &L, int i)
{
	if (i < 1)
		printf("删除位置不合法");
	LNode *p;//用来指向查询元素的指针
	int number = 0;//记录节点的位置
	int e = 0;//用来保存删除数据
	p = L;//查询节点应从头开始,所以指向头节点
	while (p != NULL && number < i - 1)
	{
		p = p->next;//只是寻找到第i-1节点
		number++;
	}
	if (p == NULL)//这里是说明了i-1是尾节点
		printf("删除内容为空");
	LNode*q = p->next;
	e = q->data;//记录删除的数据
	if (p->next->next = L)
	{
		p->next = L;
		free(q);//释放掉该节点
	}
	else {
		p->next = q->next;
		free(q);//释放掉该节点
	}
	printf("删除第%d节点元素%d成功\n", i, e);
}

void ShowList(LinkList L)
{
	LNode * P;
	P = (LNode*)malloc(sizeof(LNode));//分配空间
	P = L->next;//单链表从P点开始遍历,等同于从头节点开始
	int i = 0;//记录位序
	printf("打印单链表\n");
	while (P != NULL&&P!=L)//只要节点不为空就可以继续输出
	{
		printf("data[%d]=%d\n", i, P->data);
		i++;
		P = P->next;
	}
}
		



void main()
{
	LinkList L;//创建一个单链表
	InitLinkList(L);//初始化
	Empty( L);//判断是否为空
	CreatList(L);//输入数据
	GetElem(L, 7);//查询数据(按位)
	ListDelet(L, 5);
	ShowList(L);//输出数据

}

 

Supongo que te gusta

Origin blog.csdn.net/qq_46861651/article/details/112861145
Recomendado
Clasificación