Lenguaje C: agregue, elimine, verifique y modifique la lista enlazada circular principal bidireccional y sus ventajas y desventajas


Prefacio

Hay muchos tipos de listas enlazadas. Entre ellas, las listas enlazadas no circulares no iniciales unidireccionales y las listas enlazadas circulares iniciales bidireccionales son las más utilizadas. Ambas listas enlazadas tienen sus propias aplicaciones.
La estructura de la lista enlazada circular principal bidireccional es la más complicada y generalmente se utiliza para almacenar datos por separado. La estructura de datos de la lista enlazada que se utiliza en la práctica es una lista enlazada circular bidireccional que toma la iniciativa. Hoy, usaré el lenguaje C para realizar la adición, eliminación y modificación de la lista principal doblemente enlazada.


1. Lista enlazada circular principal bidireccional

1. Estructura de lista enlazada circular principal bidireccional

En primer lugar: observe la estructura de la lista enlazada circular principal bidireccional

Inserte la descripción de la imagen aquí
Se puede ver que cada nodo de la lista enlazada circular principal bidireccional está conectado a la parte delantera y trasera, formando así un bucle. Para realizar esta estructura, debe crear un nodo principal. El puntero de cola de los puntos del nodo principal a sí mismo, y el puntero de la cabeza también lo señala, sobre esta base, realiza la inserción y eliminación de otros nodos.

1. Código de implementación de lista enlazada circular principal bidireccional

La siguiente es la parte del código: el
archivo de encabezado
ListNode.h

#define pragama once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

//typedef方便修改结构体变量的类型
typedef int LTDataType;

//构建链表结构体,结构体变量包括头指针,尾指针及data值
typedef struct ListNode {
    
    
	
	struct ListNode* pre;
	struct ListNode* next;
	LTDataType data;

}ListNode;

//创建新节点
ListNode* BuyListNode(LTDataType x);
//链表初始化->创造头结点
ListNode* InitListNode();
//打印链表
void ListPrint(ListNode* phead);
//销毁链表
void ListDistory(ListNode* phead);

//增删查改
void ListPushBack(ListNode* phead, LTDataType x);
void ListPushFront(ListNode* phead, LTDataType x);
void ListPopBack(ListNode* phead);
void ListPopFront(ListNode* phead);
ListNode* ListFind(ListNode* phead, LTDataType x);
void ListInsert(ListNode* pos, LTDataType x);
void ListErase(ListNode* pos);
void Listchange(ListNode* pos, LTDataType x);

Body
ListNode.c

#include"ListNode.h"



ListNode* BuyListNode(LTDataType x)
{
    
    
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->data = x;
	newnode->next = NULL;
	newnode->pre = NULL;


	return newnode;
}


ListNode* InitListNode()
{
    
    
	//构造头结点
	ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
	phead->next = phead;
	phead->pre = phead;

	return phead;
}

void ListPrint(ListNode* phead)
{
    
    
	assert(phead);

	//从头结点后开始,到头结点结束
	ListNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		printf("%d", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

void ListDistory(ListNode* phead)
{
    
    
	ListNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		ListNode* next = cur->next;
		ListErase(cur);
		cur = next;
	}
	free(phead);
	phead = NULL;
}

//以下注释掉的代码段和留下的代码功能是一样的
void ListPushBack(ListNode* phead, LTDataType x)
{
    
    
	/*assert(phead);

	ListNode* newnode = BuyListNode(x);
	ListNode* tail = phead->pre;

	tail->next = newnode;
	newnode->pre = tail;
	newnode->next = phead;
	phead->pre = newnode;*/
	ListInsert(phead, x);
}

void ListPushFront(ListNode* phead, LTDataType x)
{
    
    
	/*assert(phead);

	ListNode* next = phead->next;
	ListNode* newnode = buyListNode(x);

	newnode->next = next;
	next->pre = newnode;
	phead->next = newnode;
	newnode->pre = phead;*/
	ListInsert(phead->next, x);

}

void ListPopBack(ListNode* phead)
{
    
    
	/*assert(phead);
	assert(phead->next != phead);
	
	ListNode* tail = phead->pre;
	ListNode* tailpre = tail ->pre;
	
	tailpre->next = phead;
	phead->pre = tailpre;
	
	free(tail);*/
	ListErase(phead->pre);
}

void ListPopFront(ListNode* phead)
{
    
    
	/*assert(phead);
	assert(phead->next != phead);
	
	ListNode* next = phead->next;
	ListNode* newnext = next ->next;
	
	phead->next = newnext;
	newnext->pre = phead;

	free(next);*/
	ListErase(phead->next);
}

ListNode* ListFind(ListNode* phead, LTDataType x)
{
    
    
	assert(phead);

	ListNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		if (cur->data == x)
		{
    
    
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//POS之前插入
void ListInsert(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);
	ListNode* pospre = pos->pre;
	ListNode* newnode = BuyListNode(x);
	
	pospre->next = newnode;
	newnode->pre = pospre;
	newnode->next = pos;
	pos->pre = newnode;

}
//pos不能是phead! 否则会破坏双向链表的结构;
void ListErase(ListNode* pos)
{
    
    
	assert(pos);
	ListNode* pospre = pos->pre;
	ListNode* posnext = pos->next;

	pospre->next = posnext;
	posnext->pre = pospre;
	free(pos);
}
void Listchange(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);
	pos->data = x;
}

Prueba de código
test.c

#include"ListNode.h"


void test()
{
    
    
	ListNode* phead = InitListNode();
	ListPushBack(phead, 1);
	ListPushBack(phead, 2);
	ListPushBack(phead, 3);
	ListPushBack(phead, 4);
	ListPushBack(phead, 5);
	ListPushFront(phead, 6);
	ListPrint(phead);

	ListNode* pos = ListFind(phead, 2);
	ListInsert(pos, 8);
	ListErase(pos);
	ListPrint(phead);
	ListNode* pos2 = ListFind(phead, 4);
	Listchange(pos2, 9);

	//ListDistory(phead);
	ListPrint(phead);

}
int main()
{
    
    
	test();
	return 0;
}

resultado de la operación
! [Inserte la descripción de la imagen aquí] (https://img-blog.csdnimg.cn/20210202194546953.png

En segundo lugar, las ventajas y desventajas de la lista enlazada circular principal bidireccional

Las ventajas y desventajas de la siguiente lista circular bidireccional se comparan con la tabla secuencial y la lista enlazada no circular unidireccional, por lo que las ventajas y desventajas de la siguiente tabla secuencial se resumen al mismo tiempo.

1. Ventajas y desventajas de la lista enlazada circular principal bidireccional

  • Ventajas : admite la inserción y eliminación de O (1) en cualquier posición, sin necesidad de expandir y sin desperdicio de espacio.
  • Desventajas : no se admite el acceso aleatorio y la tasa de aciertos de la caché es relativamente baja.

2. Ventajas y desventajas de la tabla de secuencia

ventaja:

  • En términos relativos, la tasa de utilización del espacio es mayor, no se necesita espacio adicional y el espacio es pequeño (la lista vinculada necesita almacenar punteros).
  • El espacio físico es continuo. Admite el acceso aleatorio, puede usar el acceso de subíndice (la mayor ventaja); la tasa de aciertos de caché es mayor.

Desventajas:

  • Insertar o eliminar datos en el encabezado o en el medio requiere mover los datos uno por uno, y la complejidad del tiempo es O (N).
  • Cuando el espacio es insuficiente, es necesario aumentar la capacidad. Generalmente, la capacidad se incrementa en múltiplos, por lo que puede haber una cierta cantidad de desperdicio de memoria.

Supongo que te gusta

Origin blog.csdn.net/weixin_47460769/article/details/113572440
Recomendado
Clasificación