DS005 Estructura de datos: investigación sobre el principio de implementación de lista vinculada única: implementación de clase de plantilla C ++

1. La tabla de secuencia es tan buena, ¿por qué necesita una lista vinculada?

Desventajas de la tabla de secuencia:

Además del final de la tabla, insertar y borrar elementos en la tabla de secuencia requiere mover otros elementos, lo cual es ineficiente , la complejidad de tiempo promedio es O (n) .
• La tabla de secuencia necesita espacio continuo.Cuando la cantidad de datos es relativamente grande, si no hay suficiente espacio continuo, la tabla de secuencia fallará . !
 
Para solucionar esta deficiencia, se diseña una lista enlazada. La inserción y eliminación de la lista enlazada no necesita mover otros elementos, y la eficiencia de la inserción y eliminación es alta, pero se pierde la ventaja del acceso aleatorio .
 
Otro: ¡esta es una innovación disruptiva, comenzar de nuevo, no reparar en el marco del almacenamiento secuencial! !
La lista enlazada simple es la estructura de cadena más simple. A partir de esta divergencia y extensión, se pueden construir estructuras más complejas, como árboles y gráficos.
La base no es sólida, el suelo tiembla y la lista vinculada debe aprenderse bien.

En segundo lugar, la definición de lista enlazada individualmente

• Una lista enlazada individual conecta datos de secuencia como una "cadena" almacenando las direcciones de los nodos subsiguientes en el nodo actual, por lo que se denomina lista enlazada.
El "único" de la lista enlazada individualmente significa que sólo se almacenan datos de una dirección en el nodo actual, es decir, la dirección del nodo de datos siguiente.

Tres, la forma de nodo de la lista enlazada individualmente

Cuarto, la forma general de la lista enlazada individualmente

 

 

La configuración del nodo principal en la lista enlazada individualmente es para facilitar la inserción y eliminación de nodos en la cabecera de la lista enlazada.

      El nodo principal y el nodo de datos de la lista enlazada individual de la que hablamos en esta sección son del mismo tipo.

       A veces, por conveniencia, se puede establecer en el nodo principal un puntero al encabezado de la lista vinculada, un puntero al final de la lista vinculada y un número entero que represente la longitud de la lista vinculada . En este momento, el tipo de nodo principal es diferente del tipo de nodo de lista vinculado.

Cinco, la descripción de C ++ del nodo de lista enlazada

template <typename T> class list
{// Lista enlazada unidireccional 
    struct node
    {         T data;         node * next;     };     node * head; // Head node puntero     int length; // Registra el número de nodos de elementos




}

De esta manera, head es el puntero principal y length registra el número de nodos de elementos en la lista vinculada, excluyendo el nodo principal.

Seis, genera un nodo    

	node* creatNode(T x)
	{//为x生成结点,返回结点地址
		node* t;
		t = new node;
		if (t == 0)
			return 0;
		t->data = x;
		t->next = 0;
		return t;

	}

Utilice el nuevo operador para solicitar espacio de tipo de nodo desde el sistema operativo.

Si el sistema operativo dice que no soy rico y lo rechaza, devuelve 0, que es un puntero nulo; de lo contrario, devuelve la dirección del nuevo nodo. 

Siete, inicialización

Al principio, se genera y se implementa un nodo principal en el constructor.

	void init()
	{
		head = new node;
		head->next = 0;
		length = 0;
	}

    list()
	{
		init();
	}

head es una variable que almacena la dirección, que es la dirección del nodo principal, que no tiene nombre. 

 

8. Insertar un elemento después de cierto nodo.

void insert(node* p, node* q)
	{//p是链表中某个结点的指针,q是一个新结点的指针
		//将q插入到p的后面
		q->next = p->next;
		p->next = q;
		length++;
	}

	void insert(node* p, T x)
	{//在指针p所指的结点后面插入x
		node* q, * t;

		t = creatNode(x);
		insert(p, t);		

	}

La sobrecarga de funciones de C ++ tiene el mismo nombre de función pero diferentes parámetros. 

Inserte el nodo q después del nodo p. No debe desconectar primero el puntero después de p. Antes de desconectar, debe haber un puntero al nodo después del p original.

De lo contrario, el nodo se perderá.

Nueve, inserte elementos después del nodo principal

void push_front(T x)
	{

		insert(head, x);

	}

Con el presagio de la función de inserción anterior, la operación de insertar un nodo en la cabeza es tan simple.

10. Inserte un nodo al final de la lista vinculada.

 

void push_back(T x)
	{
		node* p;
		p = head;
		while (p->next)
		{
			p = p->next;
		}

		insert(p, x);

	}

 Primero busque el nodo final de la lista vinculada, apúntelo con el puntero p, y luego inserte los datos después de p.

11. Obtenga la dirección del i-ésimo nodo

node* Address(int i)
	{//得到第i个元素结点的地址
		if (i<0 || i>length)
			return 0;
		if (i == 0)
			return head;
		if (i == 1)
			return head->next;


		int j = 0;
		node* p = head;
		while (j < i)
		{
			p = p->next;
			j++;
		}
		return p;

	}

Encontrar el i-ésimo nodo en la lista enlazada individualmente es una operación básica. 

12. Insertar datos antes del i-ésimo nodo

void insert(int i, T x)
	{//在链表的第i个数据前面插入x
	 //即在第i-1个元素后面插入x
		node* p;
		if (i == 1)
			push_front(x);
		else if (i == length + 1)
			push_back(x);
		else
		{
			p = Address(i - 1);
			insert(p, x);

		}

	}

Para insertar datos en el i-ésimo nodo, inserte los datos después del i-1 ° nodo, y primero debe encontrar el i-1 ° nodo.

13. Eliminar el i-ésimo nodo

void erase(int i)
	{//删除第i个元素结点
		if (i<1 || i>length)
			return;
		node* q, * t;
		t = Address(i - 1);
		q = t->next;
		t->next = q->next;

		delete q;
		length--;
	}

Para eliminar el i-ésimo nodo, primero debe encontrar el i-1 ° nodo. 

14. Buscar en la lista vinculada

 

node* find(T x)
	{//查找元素x,若存在返回地址,否则返回空指针0
		node* p = head->next;
		while (p != 0)
		{
			if (p->data == x)
				return p;
			p = p->next;
		}
		return 0;
	}

15. Libere el espacio ocupado por la lista enlazada individualmente

Implementado en el destructor

~list()
	{
		node* p;
		node* q;
		while (head->next)
		{
			p = head->next;
			head->next = p->next;
			delete p;
		}
		delete head;
		head = 0;
		length = 0;
	}

16. Código completo

 



//#include "stdafx.h" //vc下面工程带的头文件,用dev编译时注释掉即可


#include <iostream>
using namespace std;

template<typename T>class list
{//单向链表 
	struct node
	{
		T data;
		node* next;
	};
	node* head;//头结点
	int length;
public:
	void init()
	{
		head = new node;
		head->next = 0;
		length = 0;
	}
	list()
	{
		init();
	}
	int size()
	{
		return length;
	}
	void print()
	{
		node* p;
		p = head->next;
		while (p != 0)
		{
			cout << p->data << " ";
			p = p->next;
		}
		cout << endl;
	}
	node* creatNode(T x)
	{//为x生成结点,返回结点地址
		node* t;
		t = new node;
		t->data = x;
		t->next = 0;
		return t;

	}

	void insert(node* p, node* q)
	{//p是链表中某个结点的指针,q是一个新结点的指针
		//将q插入到p的后面
		q->next = p->next;
		p->next = q;
		length++;
	}

	void insert(node* p, T x)
	{//在指针p所指的结点后面插入x
		node* q, * t;

		t = creatNode(x);
		insert(p, t);		

	}

	



	void push_front(T x)
	{

		insert(head, x);

	}
	void push_back(T x)
	{
		node* p;
		p = head;
		while (p->next)
		{
			p = p->next;
		}

		insert(p, x);

	}
	node* Address(int i)
	{//得到第i个元素结点的地址
		if (i<0 || i>length)
			return 0;
		if (i == 0)
			return head;
		if (i == 1)
			return head->next;


		int j = 0;
		node* p = head;
		while (j < i)
		{
			p = p->next;
			j++;
		}
		return p;

	}

	void insert(int i, T x)
	{//在链表的第i个数据前面插入x
	 //即在第i-1个元素后面插入x
		node* p;
		if (i == 1)
			push_front(x);
		else if (i == length + 1)
			push_back(x);
		else
		{
			p = Address(i - 1);
			insert(p, x);

		}

	}
	
	void erase(int i)
	{//删除第i个元素结点
		if (i<1 || i>length)
			return;
		node* q, * t;
		t = Address(i - 1);
		q = t->next;
		t->next = q->next;

		delete q;
		length--;
	}

	node* find(T x)
	{
		node* p = head->next;
		while (p != 0)
		{
			if (p->data == x)
				return p;
			p = p->next;
		}
		return 0;
	}

	~list()
	{
		node* p;
		node* q;
		while (head->next)
		{
			p = head->next;
			head->next = p->next;
			delete p;
		}
		delete head;
		head = 0;
		length = 0;
	}
};

int main()
{
	list<int> L;
	L.push_front(3);
	L.push_front(2);
	L.push_front(1);

	L.print();

	L.push_back(4);
	L.push_back(5);
	L.push_back(6);
	L.print();

	cout << L.size() << endl;

	cout << (L.Address(6)->data) << endl;

	L.insert(1, 44);
	L.print();
	L.insert(3, 55);
	L.print();
	L.insert(8, 66);
	L.print();

	cout << "begin to delete:\n";
	L.erase(1);
	L.print();
	L.erase(L.size());
	L.print();
	L.erase(3);
	L.print();

	cout << L.find(55)->data << endl;


	return 0;
}

17. Ejecución de resultados

Supongo que te gusta

Origin blog.csdn.net/weixin_43917370/article/details/108565818
Recomendado
Clasificación