Estructura de datos: la estructura y realización de una lista enlazada circular bidireccional (lenguaje C)

1. La estructura y realización de la lista doblemente enlazada

1.1 Lista enlazada circular bidireccional principal

La estructura es la más compleja y generalmente se usa 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. Además, aunque la estructura de esta estructura es compleja, encontrarás que la estructura traerá muchas ventajas luego de usar el código para lograrlo, pero la implementación es simple, y sabremos cuándo se implementa el código más adelante.

Inserte la descripción de la imagen aquí

1.2 La realización de la lista enlazada circular bidireccional principal

// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
    
    
	LTDataType _data;			
	struct ListNode* _next;	
	struct ListNode* _prev;
}ListNode;

En segundo lugar, la realización de la interfaz de la lista doblemente enlazada

2.1 Crear una lista doblemente enlazada

Cree un nodo principal, solicite espacio, newNode -> _ next = newNode -> _ prev = newNode;
Inserte la descripción de la imagen aquí

ListNode* BuyNode(LTDataType x)
{
    
    
	ListNode* newNode = (ListNode *)malloc(sizeof(ListNode));
	newNode->_data = x;
	newNode->_next = newNode->_prev = NULL;
	return newNode;

}

// 创建返回链表的头结点.
ListNode* ListCreate()
{
    
    
	ListNode* Head = BuyNode(0);
	Head->_next = Head->_prev = Head;
	return Head;
}

2.2 Destrucción de lista doblemente enlazada

//双向链表的清除,保留头节点
void ListClear(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	//遍历每个节点并释放
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	pHead->_next = pHead->_prev = pHead;
}

// 双向链表销毁
void ListDestory(ListNode** ppHead)
{
    
    
	assert(*ppHead);
	ListClear(*ppHead);
	free(*ppHead);
	*ppHead = NULL;
}

2.3 La lista doblemente enlazada se inserta delante de pos.

Inserte la descripción de la imagen aquí

// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* newNode = BuyNode(x);
	newNode->_prev = prev;	//1.
	prev->_next = newNode;	//2.
	pos->_prev = newNode;	//3.
	newNode->_next = pos;	//4.


}

2.4 La lista doblemente enlazada elimina el nodo en la posición pos

Inserte la descripción de la imagen aquí

// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* next = pos->_next;	//pos的后一个节点
	
	free(pos);
	prev->_next = next;	//1.
	next->_prev = prev;	//2.

}

2.5 Impresión de listas doblemente enlazadas

// 双向链表打印
void ListPrint(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	
	遍历每个节点并打印
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;	//next指向下一个节点
		printf("%d ", cur->_data);	//打印当前节点
		cur = next;		//cur指向下一个节点
	}
	printf("\n");

}

2.5 Finalizar la inserción de una lista enlazada doble

Inserte la descripción de la imagen aquí
La inserción de la cola es en realidad para insertar el nodo frente al nodo principal , por lo que puede llamar directamente a la interfaz escrita antes, o puede implementarla gradualmente usted mismo

// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead, x);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//ListNode* newNode = BuyNode(x);	//创建一个新节点
	//tail->_next = newNode;	//1.
	//newNode->_prev = tail;	//2.
	//newNode->_next = pHead;	//3.
	//pHead->_prev = newNode;	//4.
}

2.6 Finalizar la eliminación de la lista doblemente enlazada

La eliminación de la cola es eliminar el último nodo de la lista doblemente vinculada, y la posición de eliminación es el nodo anterior del nodo principal.

// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
    
    
	assert(pHead);

	ListErase(pHead->_prev);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//if (tail == pHead)	//只有头节点说明双向链表为空,直接返回
	//{
    
    
	//	return;
	//}
	//ListNode* prev = tail->_prev;	//尾节点的前一个节点,即新的尾节点
	//free(tail);		//释放尾节点
	//prev->_next = pHead;	//1.新的尾节点next指向head
	//pHead->_prev = prev;	//2.head的prev指向新的尾节点
}

2.7 Inserción del cabezal del medidor de doble enlace

El inserto de la cabeza se inserta detrás del nodo de la cabeza

// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead->_next, x);


}

2.8 Eliminación del encabezado de la lista doblemente enlazada

La eliminación del encabezado es eliminar el elemento después del nodo principal.

// 双向链表头删
void ListPopFront(ListNode* pHead)
{
    
    
	assert(pHead);
	
	ListErase(pHead->_next);


}

2.9 Búsqueda de lista doblemente enlazada

// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		if (cur->_data == x)
		{
    
    
			return cur;
		}
		cur = next;
	}
	return NULL;
}

Tres, la lista de códigos

3.1 Lista.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>

// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
    
    
	LTDataType _data;			
	struct ListNode* _next;	
	struct ListNode* _prev;
}ListNode;

// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListClear(ListNode* pHead);
void ListDestory(ListNode** ppHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

3.2 Lista.c

#include "List.h"


ListNode* BuyNode(LTDataType x)
{
    
    
	ListNode* newNode = (ListNode *)malloc(sizeof(ListNode));
	newNode->_data = x;
	newNode->_next = newNode->_prev = NULL;
	return newNode;

}

// 创建返回链表的头结点.
ListNode* ListCreate()
{
    
    
	ListNode* Head = BuyNode(0);
	Head->_next = Head->_prev = Head;
	return Head;
}


//双向链表的清除,保留头节点
void ListClear(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	//遍历每个节点并释放
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	pHead->_next = pHead->_prev = pHead;
}

// 双向链表销毁
void ListDestory(ListNode** ppHead)
{
    
    
	assert(*ppHead);
	ListClear(*ppHead);
	free(*ppHead);
	*ppHead = NULL;
}

// 双向链表打印
void ListPrint(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	
	遍历每个节点并打印
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;	//next指向下一个节点
		printf("%d ", cur->_data);	//打印当前节点
		cur = next;		//cur指向下一个节点
	}
	printf("\n");

}
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead, x);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//ListNode* newNode = BuyNode(x);	//创建一个新节点
	//tail->_next = newNode;	//1.
	//newNode->_prev = tail;	//2.
	//newNode->_next = pHead;	//3.
	//pHead->_prev = newNode;	//4.
}
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
    
    
	assert(pHead);

	ListErase(pHead->_prev);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//if (tail == pHead)	//只有头节点说明双向链表为空,直接返回
	//{
    
    
	//	return;
	//}
	//ListNode* prev = tail->_prev;	//尾节点的前一个节点,即新的尾节点
	//free(tail);		//释放尾节点
	//prev->_next = pHead;	//1.新的尾节点next指向head
	//pHead->_prev = prev;	//2.head的prev指向新的尾节点
}
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead->_next, x);


}
// 双向链表头删
void ListPopFront(ListNode* pHead)
{
    
    
	assert(pHead);
	
	ListErase(pHead->_next);


}

// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		if (cur->_data == x)
		{
    
    
			return cur;
		}
		cur = next;
	}
	return NULL;
}
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* newNode = BuyNode(x);
	newNode->_prev = prev;	//1.
	prev->_next = newNode;	//2.
	pos->_prev = newNode;	//3.
	newNode->_next = pos;	//4.


}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* next = pos->_next;	//pos的后一个节点
	
	free(pos);
	prev->_next = next;	//1.
	next->_prev = prev;	//2.

}

3.3 prueba.c

#include"List.h"

void TestList()
{
    
    
	ListNode *p;
	p = ListCreate();
	ListPushFront(p, 5);
	ListPushFront(p, 4);
	ListPushFront(p, 3);
	ListPushFront(p, 2);
	ListPushFront(p, 1);
	ListPrint(p);

	ListPopFront(p);
	ListPopFront(p);
	ListPopFront(p);
	ListPopFront(p);
	ListPopFront(p);
	ListPrint(p);

	ListPushBack(p, 1);
	ListPushBack(p, 2);
	ListPushBack(p, 3);
	ListPushBack(p, 4);
	ListPushBack(p, 5);
	ListPrint(p);

	ListPopBack(p);
	ListPopBack(p);
	ListPopBack(p);
	ListPopBack(p);
	ListPopBack(p);
	ListPrint(p);


	//ListDestory(&p);

	ListPushFront(p, 5);
	ListPushFront(p, 4);
	ListPushFront(p, 3);
	ListPushFront(p, 2);
	ListPushFront(p, 1);
	ListPrint(p);

	ListNode* pos = ListFind(p, 3);
	pos->_data = 30;
	ListPrint(p);

	ListInsert(pos, 33);
	ListPrint(p);
	ListErase(pos);
	ListPrint(p);

	ListDestory(&p);
}

int main()
{
    
    
	TestList();
	system("pause");
	return 0;
}

Cuatro, resultados de la prueba

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_40076022/article/details/112526801
Recomendado
Clasificación