Listas Vinculadas en Estructura de Datos

Las listas vinculadas, enlazadas o enhebradas en la estructuras de datos lineales en las que los elementos no se almacenan en ubicaciones contiguas en la memoria y en las que los elementos están vinculados entre sí mediante punteros. La siguiente figura muestra la estructura de listas enlazadas:

estructura de listas enlazadas
Estructura de listas enlazadas

Las listas de subprocesos constan de nodos y cada nodo contiene un campo de datos y un puntero (enlace) al siguiente nodo de la lista.

Tabla de contenidos


¿Por qué utilizar listas vinculadas?

Las matrices se pueden utilizar para almacenar datos lineales del mismo tipo, pero el uso de estas matrices tienen las siguientes desventajas:

  1. Las matrices tienen un tamaño fijo, lo que significa que debemos conocer el número máximo de elementos que entrarán en la matriz de antemano, y la cantidad de memoria reservada es igual a la cantidad máxima de elementos en la matriz, independientemente de cuantos elementos la componen realmente.
  2. Para agregar un nuevo elemento a la matriz requiere un elevado consumo de memoria. Esto se debe a que agregar un nuevo elemento significa encontrar un espacio para él en la matriz, lo que a su vez significa desplazar los elementos de la matriz de sus posiciones.

Supongamos el siguiente ejemplo, digamos que tenemos una lista de identificadores dispuestos en una matriz: id[] = [10, 12, 15, 20, 22]‎.

Si queremos agregar un nuevo identificador que contenga el valor 15 sin alterar el orden de los elementos, entonces tenemos que mover todos los elementos que siguen al identificador 10.

El proceso de eliminación también es costoso, a menos que usemos algunas técnicas especiales. Por ejemplo, para poder borrar el identificador 12 en el arreglo anterior, debemos mover todos los elementos que siguen al identificador 12.

Listas y matrices vinculadas

Las listas enlazadas difieren de las matrices en los siguientes puntos:

  1. Una matriz es una estructura de datos que contiene un grupo de elementos de tipo similar, mientras que una lista vinculada es una estructura de datos no primitiva que contiene un grupo de elementos relacionados y desordenados llamados nodos.
  2. Los elementos de las matrices pertenecen a índices, lo que significa que para acceder al cuarto elemento de la matriz, el nombre de la variable debe escribirse con su índice o ubicación entre corchetes.
  3. En las listas enlazadas, debes empezar desde la cabecera y luego ir pasando por los elementos uno por uno hasta llegar al cuarto elemento.
  4. Se puede acceder rápidamente a un elemento de una matriz. Para una lista vinculada, se necesita más tiempo lineal para acceder a los elementos. Por lo tanto, las listas de subprocesos son un poco más lentas que las matrices.
  5. Las operaciones como la adición y eliminación toman mucho tiempo en matrices, pero son rápidas en listas de subprocesos.
  6. Las matrices tienen un tamaño fijo, a diferencia de las listas de subprocesos que tienen un tamaño variable y son flexibles y tienen la capacidad de aumentar o disminuir su tamaño según sea necesario.
  7. La información sobre el uso de matrices se asigna a la memoria en el momento de la compilación. Cuando se utilizan listas de subprocesos, la memoria se reserva en el tiempo de ejecución.
  8. Los elementos de la matriz se almacenan en orden y se almacenan en listas relacionadas aleatoriamente.
  9. Las matrices requieren menos memoria porque los datos reales se almacenan en el índice y las listas de subprocesos requieren más memoria porque necesitan almacenar elementos adicionales para apuntar a los nodos anteriores y posteriores.
  10. La memoria no se puede utilizar de forma eficiente con matrices, a diferencia de las listas enlazadas.

Desventajas de las listas enlazadas

  1. No se puede acceder a las listas de subprocesos de forma aleatoria, se debe acceder a ellas en orden comenzando desde el primer nodo. Por lo tanto, la búsqueda binaria no se puede realizar de manera eficiente si usamos el método predeterminado para tratar con listas enhebradas.
  2. Cada elemento necesita espacio de memoria adicional para que cada elemento esté asociado con un puntero.
  3. No es compatible con la caché. Dado que los elementos de la matriz están en ubicaciones contiguas, las referencias a los elementos están en una única localidad de referencia, algo que falta en las listas vinculadas.

Representación de listas enlazadas

Una lista de subprocesos está representada por un puntero al primer nodo en la lista de subprocesos. El primer nodo se llama cabeza, y si la lista de subprocesos está vacía, el valor del encabezado es NULL.

Cada nodo de la lista tiene dos partes:

  1. datos.
  2. Punteros o referencia al siguiente nodo.

Los nodos se pueden representar en C usando estructuras. El siguiente ejemplo muestra un nodo de lista enhebrado con datos escalares.

struct Node { 
  int data; 
  struct Node *next; 
}

En Java y C #, las listas de subprocesos se pueden representar por una clase y los nodos por una clase separada, y la clase de lista de subprocesos contiene una referencia a la clase de nodo.

class LinkedList { 
	Node head; 

	class Node { 
		int data; 
		Node next; 
// constructor para crear un nuevo nodo
		Node (int d) {data = d;}
	}  
}
class LinkedList { 
    Node head;
    class Node { 
        int data; 
        Node next; 
 // constructor para crear un nuevo nodo 
// el valor del nodo siguiente se inicializa automáticamente a nulo 
        Node(int d) {data = d;} 
    }  
}
# Node class 
class Node: 
    #función para inicializar el objeto de nodo 
    def __init__(self, data): 
        self.data = data  # Asignamos datos 
        self.next = None   # Inicializa el siguiente nodo para que esté vacío null
   
# 
class LinkedList:
     # Función para inicializar el objeto de lista enhebrada   
    def __init__(self):  
        self.head = None

Crea listas enlazadas

Los siguientes ejemplos muestran cómo crear listas de subprocesos en varios lenguajes de programación(C++, Python, Java) :

#include <bits/stdc++.h> 
using namespace std; 

class Node { 
	public: 
	int data; 
	Node *next; 
} 
// Este programa crea una lista sencilla 
// que tiene tres nodos 
int main() { 
	Node* head = NULL; 
	Node* second = NULL; 
	Node* third = NULL; 	
// reservar posiciones para 3 nodos 
	head = new Node(); 
	second = new Node(); 
	third = new Node(); 
/* 
Tres bloques se reservan en memoria dinámicamente y 
tenemos punteros a estos bloques son 
   
	   head		   second	   third 
		|			 |			 | 
		|			 |			 | 
	+---+-----+	 +----+----+	 +----+----+ 
	| # | # |	 | # | # |	 | # | # | 
	+---+-----+	 +----+----+	 +----+----+ 
representa cualquier valor aleatorio Los datos son aleatorios porque no hemos asignado ningún valor aún 
 */  
	
head->data = 1; // asigna un valor al primer 
head->next = second; // atar el primer nudo con el segundo
	
/* 
Los datos se asignan a la parte de datos del primer bloque (encabezado del menú) y el puntero 
posterior apunta al segundo bloque, por lo que los dos bloques están relacionados
       head		   second	   third 
		|			 |			 | 
		|			 |			 | 
	+---+---+	 +----+----+	 +-----+----+ 
	| 1 | o----->| # | # |	 | # | # | 
	+---+---+	 +----+----+	 +-----+----+	 
*/
  
second->data = 2;  // asigna un valor al segundo nodo  
second->next = third;  // conecta el segundo nodo al tercer 
	
/* 
Asignar un valor a la parte de datos del segundo bloque, 
y el puntero al segundo bloque apunta al tercer bloque, 
por lo que los dos bloques están vinculados 
 
       head		   second	   third 
		|			 |			 | 
		|			 |			 | 
	+---+---+	 +---+---+	 +----+----+ 
	| 1 | o----->| 2 | o-----> | # | # | 
	+---+---+	 +---+---+	 +----+----+
*/	

third->data = 3; // asigna un valor al tercer nodo 
third->next = NULL; 
	
/* 
Asignar un valor a la parte de datos del tercer nodo 
Null y el puntero final en el tercer bloque apunta al valor 
para indicar el final de la lista enhebrada en esa posición

	  head	 
		| 
		| 
	+---+---+	 +---+---+	 +----+------+ 
	| 1 | o----->| 2 | o-----> | 3 | NULL | 
	+---+---+	 +---+---+	 +----+------+	   
Tenga en cuenta que el encabezado de la lista es suficiente para representar la lista completa. Puede navegar por todos los elementos del menú siguiendo el cursor 
*/	

return  0;  
}
clase  Nodo: 

	# Una función para inicializar el objeto de nodo 
	def __init__(self, data):  
		self.data = data  # Asignar datos a 
		self.next = None  # null Inicializa el nodo subsiguiente para ser


    # clase de lista vinculada que contiene el objeto 
    class LinkedList: 

	# Inicializar encabezado de lista 
	def __init__ ( self ):  
		self.head = none


  if __name__=='__main__':

	# Comenzamos con una lista de subprocesos vacía 
	llist = LinkedList() 

	llist.head = Node(1) 
	second = Node(2) 
	third = Node(3) 
    
	'''
    Tres bloques se reservan dinámicamente en la memoria y 
	tenemos punteros a estos bloques son 
	first, second, third

	llist.head	 second			 third 
		|			 |				 | 
		|			 |				 | 
	+----+------+	 +----+------+	 +----+------+ 
	| 1 | None |	 | 2 | None |	 | 3 | None | 
	+----+------+	 +----+------+	 +----+------+ 
    '''
    
	
	llist.head.next = second;  # une el primer nudo al segundo

	'''  
	El primer nodo ahora se refiere al segundo nodo, por lo que están interconectados

	llist.head                second		 	 third
		   |                    |                  | 
		   |                    |                  | 
	+ ---- + ------ +   + ---- + ------ +   + ---- + ------ + 
	| 1 | o -------->   | 2 | nulo | 3 |    | nulo | 
	+ ---- + ------ +   + ---- + ------ +   + ---- + ------ + 
	'''

	second.next = third;  # une el segundo nudo con el tercero

	''' 
	El segundo nudo se refiere al tercer nudo, por lo que están interconectados
    llist.head               second		          third
		|                      |                    | 
		|                      |                    | 
	+ ---- + ------ +   + ---- + ------ +    + ---- + ------ + 
	| 1 | o -------->   | 2 | o -------->    | 3 | nulo | 
	+ ---- + ------ +   + ---- + ------ +    + ---- + ------ + 
	'''
class LinkedList { 
	Node head; // parte superior de la lista

	/* lista de subprocesos nodo */ 
	static class Node { 
		int data; 
		Node next; 
		Node(int d) { data = d; next=null; } // constructor }  
    }  

	/* Continuar creando una lista simple de tres nodos */ 
	public static void main(String[] args) { 
      
		/* Comenzamos con una lista vacía */ 
		LinkedList llist = new LinkedList(); 

		llist.head = new Node(1); 
		Node second = new Node(2); 
		Node third = new Node(3); 
      
		/* Tres nodos reservan un lugar en la memoria dinámicamente y 
		nuestras referencias a estos bloques son 
		first, second, third

		llist.head	   second		third 
			|            |            | 
			|            |            | 
		+ ---- + ------ + + ---- + ------ + + ---- + ------ + 
		| 1 | nulo | | 2 | nulo | | 3 | nulo | 
		+ ---- + ------ + + ---- + ------ + + ---- + ------ + */

		llist.head.next = second;  // atar el primer nudo al segundo

		/* El primer nodo ahora se refiere al segundo nodo y, 
		por lo tanto, los dos nodos están vinculados

		llist.head	        second		 third 
			|                 |            | 
			|                 |            | 
		+ ---- + ------ + + ---- + ------ + + ---- + ------ + 
		| 1 | o --------> | 2 | nulo | | 3 | nulo | 
		+ ---- + ------ + + ---- + ------ + + ---- + ------ + */

		second.next = third;  // conecta el segundo nodo al tercer nodo

		/* Ahora el segundo nodo se refiere al tercer nodo y 
		así los dos nodos están vinculados

		llist.head         second             third 
			|                 |                 | 
			|                 |                 | 
		+ ---- + ------ + + ---- + ------ + + ---- + ------ + 
		| 1 | o --------> | 2 | o --------> | 3 | nulo | 
		+ ---- + ------ + + ---- + ------ + + ---- + ------ + */ 
	}  
}

Los siguientes ejemplos muestran cómo navegar por los nodos en listas de subprocesos en varios lenguajes de programación (C++, Python, Java):

#include <bits/stdc++.h> 
using namespace std; 

class Node { 
	public: 
	int data; 
	Node *next; 
}; 
// Esta función imprime el contenido de la lista de subprocesos 
// comenzando desde el nodo dado 
void printList(Node *n) { 
	while (n != NULL) { 
		cout << n->data << " "; 
		n = n->next; 
	} 
} 
// prueba la función anterior 
int main() { 
	Node* head = NULL; 
	Node* second = NULL; 
	Node* third = NULL;
	// reserva tres nodos en la memoria 
	head = new Node(); 
	second = new Node(); 
	third = new Node(); 

	head->data = 1;  // Asignar los datos a la 
	head->next = second; // atar el primer nudo al segundo

	second->data = 2;  // Asignar los datos al segundo nodo 
	second->next = third; 

	third->data = 3;  // Asignar los datos al tercer nodo 
	third->next = NULL; 
	
	printList(head); 

	return 0; 
}
class Node: 

	# Una función para inicializar el objeto de nodo 
	def __init__(self, data):  
		self.data = data  # Asignar datos  
		self.next = None # null Inicializa el nodo subsiguiente


# class una lista vinculada que contiene un objeto de nodo de 
class LinkedList: 

	# Inicializar encabezado de lista 
	def __init__(self): 
		self.head = None
	# Esta función imprime el contenido de la lista 
    # enhebrada comenzando desde el nodo dado 
    def printList(self): 
		temp = self.head 
		while (temp): 
			print temp.data, 
			temp = temp.next


if __name__=='__main__': 

	# comenzar con una lista de subprocesos vacía 
	llist = LinkedList() 

	llist.head = Node(1) 
	second = Node(2) 
	third = Node(3) 

	llist.head.next = second;  # Conecta el primer nudo con el 
	second.next = third;  # Ate el segundo nudo con el tercero

	llist.printList()
class LinkedList { 
	Node head; // parte superior de la lista

	/* Nodo en la lista de subprocesos */ 
	static class Node { 
		int data; 
		Node next; 
		Node(int d) { data = d; next=null; } // constructor }   

	/* Esta función imprime el contenido de la lista enhebrada comenzando desde el encabezado de la lista */ 
	public void printList() { 
		Node n = head; 
		while (n != null) { 
			System.out.print(n.data+" "); 
			n = n.next; 
		} 
	} 
	/* Crea una lista de subprocesos de tres nodos */ 
	public static void main(String[] args) { 
		/* Empiece con una lista de subprocesos vacía */ 
		LinkedList llist = new LinkedList(); 

		llist.head	 = new Node(1); 
		Node second	 = new Node(2); 
		Node third	 = new Node(3); 

		llist.head.next = second;  // Conecta el primer nodo al 
		second.next = third;  // atar el segundo nudo al tercero

		llist.printList(); 
	} 
}

El código anterior da la siguiente salida:

1 2 3

Agregar nodos a listas de subprocesos

Los nodos se pueden agregar a la lista vinculada en tres lugares:

  1. al principio de la lista enhebrada.
  2. después de un cierto nodo.
  3. al final de la lista vinculada.

Agregue un nodo al comienzo de la lista de subprocesos

El nuevo nodo siempre se agrega antes del encabezado de la lista de subprocesos, y el nuevo nodo se convierte en el encabezado de esa lista. Por ejemplo, si tenemos la lista enlazada siguiente: y 10->15->20->25 añadimos el número 5 al principio de la lista, que se verá como esto: 5->10->15->20->25.

Si llamamos a la función que agrega el nuevo elemento al principio de la lista de subprocesos por nombre, push() entonces esta función debe recibir un puntero al puntero del encabezado. Esto se debe a que este puntero debe apuntar al nuevo nodo.

La complejidad temporal de la función push()‎ O (1)‎ se debe a que realiza una cantidad fija de trabajo.

Agregar un nodo después de un nodo existente

En este caso, tenemos un puntero a un nodo específico y queremos agregar un nuevo nodo después.

La complejidad temporal de una función insertAfter()‎ O(q)‎ se debe a que realiza una cantidad fija de trabajo.

Agregue un nodo al final de la lista de subprocesos

El nuevo nodo siempre se agrega después del último nodo en la lista de subprocesos. Por ejemplo, si tenemos la lista enlazada siguiente: y 5->10->15->20->25 queremos añadir el elemento 30 al final de la lista, la lista enlazada se hace de la siguiente manera: 5->10->15->20->25->30.

Dado que el encabezado suele ser una lista enhebrada, tenemos que pasar por los elementos de la lista hasta el final, y luego cambiar el nodo junto al último nodo para convertirlo en el nuevo nodo.

La cantidad de tiempo que representa la complejidad de este proceso para O(n)‎ representar los n nodos de conteo en la lista vinculada, y cuando el tráfico por parte de los elementos existentes de la función de trabajo, la función para realizar el O(n)‎ trabajo.

Esta función se puede mejorar con complejidad O(1)‎manteniendo un puntero adicional al final de la lista de subprocesos.

Ejemplos y aplicaciones en código

Los siguientes ejemplos muestran los tres métodos de suma y en varios lenguajes de programación:

#include <bits/stdc++.h> 
using namespace std; 

// lista de nodos interconectado 
class Node { 
	public: 
	int data; 
	Node *next; 
}; 

/* Inserta un nuevo nodo al principio de la lista 
usando un puntero al encabezado de la lista 
y el entero dado */ 
void push(Node** head_ref, int new_data) { 
	/* 1. Reserva la ubicación del nodo en la memoria */ 
	Node* new_node = new Node();

	/* 2. Agregar datos */ 
	new_node->data = new_data;  

	/* 3. Hacer que el encabezado de la lista sea el siguiente nodo del nuevo nodo */ 
	new_node->next = (*head_ref); 

	/* 4. Mover el encabezado de la lista para apuntar al nuevo nodo */ 
	(*head_ref) = new_node; 
} 

/* Inserta un nodo después del nodo anterior dado */ 
void insertAfter(Node* prev_node, int new_data) {  
	/* 1. Null Comprueba que 
	el nodo anterior dado no puede ser NULL */ 
      if (prev_node == NULL) 
	{ 
		cout<<"the given previous node cannot be NULL"; 
		return; 
	} 

	/* 2. Reserva la ubicación del nuevo nodo en la memoria */ 
	Node* new_node = new Node();  

	/* 3. Agregar datos */ 
	new_node->data = new_data;

	/* 4. Hacer que el siguiente nodo del nuevo nodo sea el sucesor del nodo anterior */ 
	new_node->next = prev_node->next; 

	/* 5. Mueva el siguiente nodo del nodo anterior para convertirse en el nuevo nodo */ 
	prev_node->next = new_node; 
} 

/* Agrega un nuevo nodo al final de la lista usando el 
puntero (un puntero a un puntero) al encabezado de la lista y el entero dado */

void append(Node** head_ref, int new_data) { 
	/* 1. Reserva la nueva ubicación del nodo en la memoria */ 
	Node* new_node = new Node(); 

   /* utilizado en el paso 5 */
	Node *last = *head_ref; 

	/* 2. Insertar datos */ 
	new_node->data = new_data; 

	/* 3. El nuevo nodo será el último nodo en la lista 
	por lo que haremos que el siguiente nodo sea 
	NULL */ 
	new_node->next = NULL;

	/* 4. Si la lista está vacía, el 
	nuevo nodo será en la cabecera de la lista */ 
	if (*head_ref == NULL) { 
		*head_ref = new_node; 
		return; 
	} 

	/* 5. Si la lista no está vacía, mueva el nuevo nodo al final de la lista */ 
	while (last->next != NULL) 
		last = last->next; 

	/* 6. Cambiamos el nodo final al último nodo. */ 
	last->next = new_node; 
	return; 
} 

// Esta función imprime el contenido de la lista de subprocesos 
// comenzando desde el encabezado 
void printList(Node *node) 
{ 
	while (node != NULL) 
	{ 
		cout<<" "<<node->data; 
		node = node->next; 
	} 
} 
// probar las funciones anteriores 
int main() {  
	/* comenzar con una lista vacía */ 
	Node* head = NULL; 
	
	// inserte el elemento 6 
	// la lista se verá así 
    // 6-> NULL 
	append(&head, 6);
	
	// inserte el elemento 7 al principio de la lista 
	// la lista se verá así 
    // 7-> 6-> NULL 
	push(&head, 7);  
	
	// inserte el elemento 1 al principio de la lista 
    // la lista se verá así 
    // 1-> 7-> 6-> NULL 
	push(&head, 1); 
	
	// inserta el elemento 4 al final de la lista  
    append(&head, 4); 
	
	// inserta el elemento 8 después del elemento 7 
    // la lista se verá como 
	insertAfter(head->next, 8); 
	
	cout<<"Created Linked list is: "; 
	printList(head); 
	
	return 0; 
}
# class node
class Node: 

	# Una función para inicializar el objeto de nodo 
	def __init__(self, data): 
		self.data = data # Asignar datos a 
		self.next = None # null Inicializa el nodo subsiguiente para ser


# La clase de lista vinculada incluye un objeto de nodo de 
class  LinkedList: 

	# Función para inicializar el encabezado de la lista 
	def __init__(self): 
		self.head = None


	# función para insertar un nodo al principio de la lista 
	def push(self, new_data):

		# 1: reservando la ubicación del nodo en la memoria 
		# 2: agregando datos 
		new_node = Node(new_data)

		# 3. Haga que el nodo final del nuevo nodo sea el encabezado
        new_node.next = self.head 

		# 4: Mueva el encabezado de la lista para apuntar al nuevo nodo
		self.head = new_node


	# Este método inserta un nuevo nodo después de un nodo dado 
    def insertAfter(self, prev_node, new_data):

		# 1: Verifique que un nodo dado esté realmente en la lista de subprocesos 
		if prev_node is None: 
			print "The given previous node must inLinkedList."
			return

		# 2: Cree un nuevo nodo 
        # 3: agregue datos 
		new_node = Node(new_data)

		# 4: Haga que el nodo que sigue al nuevo nodo sea el nodo que sigue al 
		new_node.next = prev_node.next

		# 5: Hacer que el nuevo nodo al nodo raíz de la dada 
		prev_node.next = new_node  


	# agrega un nuevo nodo al final de la lista de subprocesos 
	def append(self, new_data): 

		# 1: Crear un nuevo nodo 
        # 2: Agregar datos 
        # 3: Ninguno Hacer que el siguiente nodo sea 
		new_node = Node(new_data)

        # 4: Haga que el nuevo nodo sea el encabezado de la lista 
        # si la lista enhebrada está vacía 
		if self.head is None: 
			self.head = new_node 
			return

		# 5: de lo contrario, Venntql a través de los elementos del menú hasta el último nodo 
		last = self.head 
		while (last.next): 
			last = last.next

		# 6: cambiar la siguiente último nodo 
		last.next = new_node 


	# función auxiliar para imprimir el contenido de la lista enhebrada 
	def printList(self): 
		temp = self.head 
		while (temp): 
			print temp.data, 
			temp = temp.next

# Prueba las funciones anteriores 
if __name__=='__main__':

	# Empezamos con una lista vacía 
	llist = LinkedList() 

	# Insertamos el elemento 6 en la lista para que se convierta en 
    # 6-> Ninguno 
	llist.append(6) 

	# Inserte el elemento 7 al principio de la lista, por lo que se convierte en 
    # 7-> 6-> Ninguno 
	llist.push(7); 

	# Insertamos el elemento 1 al principio de la lista para que se convierta en 
    # 1 -> 7-> 6-> None 
	llist.push(1); 

	# Ponemos el elemento 4 al final de la lista para que se convierta en 
    # 1 -> 7-> 6-> 4-> None 
	llist.append(4) 

	# Insertamos el elemento 8 después del elemento 7 en la lista para que se convierta en 
    # 1 -> 7-> 8-> 6-> 4-> None 
	llist.insertAfter(llist.head.next, 8) 

	print 'Created linked list is:', 
	llist.printList()
class LinkedList { 
	Node head;  // parte superior de la lista

	// nodo de lista enhebrada

	class Node { 
		int data; 
		Node next; 
		Node(int d) {data = d; next = null; } 
	} 
	/* Inserta un nuevo nodo en la parte superior de la lista */ 
	public void push(int new_data) {  
		/* 
		1: Reserva la ubicación del nodo en la memoria 
		2: Agrega información */ 
		Node new_node = new Node(new_data); 

		/* 3. Hacer que el encabezado de la lista lea el nuevo nodo */ 
		new_node.next = head;

		/* 4. Mover el encabezado de la lista para apuntar al nuevo nodo */ 
		head = new_node; 
	} 

	/* Insertar el nodo después de un nodo determinado */ 
	public void insertAfter(Node prev_node, int new_data) { 
      
		/* 1. Verificar la presencia de un nodo determinado en la lista vinculada */ 
      
		if (prev_node == null) 
		{ 
			System.out.println("The given previous node cannot be null"); 
			return; 
		} 

		/* 2: establece la ubicación del nodo en la memoria 
		3: agrega datos 
		*/  
		Node new_node = new Node(new_data);

		/* 4. Haga que el siguiente del nuevo nodo sea el siguiente del nodo anterior */ 
		new_node.next = prev_node.next;

		/* 5. Hacer que el nuevo nodo siga al nodo anterior */ 
		prev_node.next = new_node; 
	} 
	
    /* El  
	método agrega un nuevo nodo al final de la lista de subprocesos */ 
  public void append(int new_data) {  
		/* 1: Reserva la ubicación del nodo en la memoria 
		2: Agrega datos 
		3: null 
        Hace lo siguiente para el nuevo nodo */ 
		Node new_node = new Node(new_data);

		/* Hacer que el nuevo nodo sea el encabezado de la lista si la lista está vacía */ 
		if (head == null) 
		{ 
			head = new Node(new_data); 
			return; 
		} 

		/* 4. El nuevo nodo será el último nodo de la lista 
		nulo, por lo que convertiremos el siguiente */ 
		new_node.next = null;
		
        /* 5. De lo contrario, pasaremos por los elementos de la lista hasta el último nodo */ 
		Node last = head; 
		while (last.next != null) 
			last = last.next; 

		/* 6. Cambiamos lo siguiente al último nodo */ 
		last.next = new_node; 
		return; 
	} 

	/* Este 
	método imprime el contenido de la lista de subprocesos comenzando desde el nodo dado */ 
  public void printList() { 
		Node tnode = head; 
		while (tnode != null) 
		{ 
			System.out.print(tnode.data+" "); 
			tnode = tnode.next; 
		} 
	} 

	/* Probar el código anterior */

	public static void main(String[] args) {
		/* comienza con una lista vacía */ 
		LinkedList llist = new LinkedList();

		// Inserte el elemento 6 en la lista, por lo que se convierte 
        // 6-> NUllist 
		llist.append(6);

		// Inserte el elemento 7 al principio de la lista, de modo que se convierta 
		// 7-> 6-> NUllist 
		llist.push(7); 

		// Inserte el elemento 1 al principio de la lista, por lo que se convierte en 
		// 1-> 7-> 6-> NUllist 
		llist.push(1); 

		// Inserte el elemento 4 al final de la lista, por lo que se convierte en 
		// 1-> 7-> 6-> 4-> NUllist 
		llist.append(4); 

		// Inserta el elemento 8 después del elemento 7 en la lista, por lo que se convierte en 
		// 1-> 7-> 8-> 6-> 4-> NUllist 
        llist.insertAfter(llist.head.next, 8);
		System.out.println("\n Lista vinculada creada: "); 
		llist.printList();  
	}  
}

Eliminar nodos de listas vinculadas

El proceso de eliminación de los nodos de las listas vinculadas se realiza de acuerdo con los siguientes pasos:

  1. Busque el nodo anterior del nodo que se va a eliminar.
  2. Cambie el siguiente nodo al nodo anterior.
  3. Vacíe la memoria reservada por el nodo a borrar.

La siguiente figura muestra el proceso de eliminación de un nodo de la lista de subprocesos:

Eliminar nodos de listas vinculadas
Eliminar nodos de listas vinculadas

C reserva dinámicamente memoria para cada nodo en la lista de subprocesos usando la función malloc()‎. Por lo tanto, se debe llamar free()‎ a la función para vaciar la porción de memoria reservada por el nodo a eliminar.

Los siguientes ejemplos muestran cómo eliminar un nodo de la lista de subprocesos en varios lenguajes de programación (C++, Python, Java):

#incluir  <stdio.h>
#incluir  <stdlib.h>

// nodo en la lista encadenada 
struct Node { 
	int data; 
	struct Node *next; 
} 
/* La función inserta un nuevo nodo al principio de la lista 
usando una referencia (puntero a un puntero) al encabezado de la lista y el entero dado */

void push(struct Node** head_ref, int new_data) { 
	struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); 
	new_node->data = new_data; 
	new_node->next = (*head_ref); 
	(*head_ref) = new_node; 
} 
/* La función elimina la primera aparición de la clave dada en la lista encadenada 
usando una referencia (puntero a un puntero) al encabezado de la lista y la clave dada */

void deleteNode(struct Node **head_ref, int key) {  
	// almacena los nodos de encabezado de la lista 
	struct Node* temp = *head_ref, *prev;

    // si el nodo del encabezado de la lista es el nodo que contiene la clave que se eliminará

	if (temp != NULL && temp->data == key) 
	{ 
		*head_ref = temp->next;  // cambiar el encabezado del menú 
		free(temp); 			 // deshacerse del antiguo encabezado de 
		return;   
	} 

    // Encuentre la clave para eliminar mientras continúa 
    // el nodo anterior porque necesitamos 
    // cambiar el nodo anterior al siguiente nodo 
    // 'prev->next' 
	while (temp != NULL && temp->data != key) { 
		prev = temp; 
		temp = temp->next; 
	} 
    // si la clave no está en la lista de subprocesos 
	if (temp == NULL) return;

	// desvincular el nodo de la lista de subprocesos 
	prev->next = temp->next; 

	free(temp); // Free memory 
} 

// Esta función imprime el contenido de la lista encadenada a partir del nodo dado 
void printList(struct Node *node) { 
	while (node != NULL) 
	{ 
		printf(" %d ", node->data); 
		node = node->next; 
	} 
} 
/* Probar las funciones anteriores */ 
int main() {  
	/* comenzar con un nodo vacío */ 
	struct Node* head = NULL; 

	push(&head, 7); 
	push(&head, 1); 
	push(&head, 3); 
	push(&head, 2); 

	puts("Lista vinculada creada: "); 
	printList(head); 
	deleteNode(&head, 1); 
	puts("\nLinked List after Deletion of 1: "); 
	printList(head); 
	return 0; 
}
# nodo de clase
class Node:  

	# Función del constructor para inicializar el objeto de nodo 
	def __init__(self, data): 
		self.data = data 
		self.next = None

class LinkedList:

	# Inicializa el encabezado de la lista 
	def __init__(self): 
		self.head = None

	# La función inserta un nuevo nodo al comienzo de la lista 
	def push(self, new_data): 
		new_node = Node(new_data) 
		new_node.next = self.head 
		self.head = new_node 
    # La función elimina la primera aparición de la clave dada en la lista encadenada 
    # usando una referencia al encabezado de la lista y la clave dada 
	def deleteNode(self, key):  
		
		# almacena la temperatura del nodo 
        temp = self.head  

		# si el nodo principal contiene el valor de la clave dada 
		if (temp is not None): 
			if (temp.data == key): 
				self.head = temp.next
				temp = None
				return
        # Encuentre la clave para eliminar mientras continúa con el 
        # porque la necesitamos para cambiar el nodo posterior del nodo anterior 
        # 'prev.next' 
		while(temp is not None): 
			if temp.data == key: 
				break
			prev = temp 
			temp = temp.next
		# Si la clave no está en la lista de subprocesos 
		if(temp == None): 
			return
		# Desvincular el nodo de la lista de subprocesos 
		prev.next = temp.next

		temp = None
	# Utility function to print the linked LinkedList 
	def printList(self): 
		temp = self.head 
		while(temp): 
			print " %d" %(temp.data), 
			temp = temp.next
# Probar las funciones anteriores 
llist = LinkedList() 
llist.push(7) 
llist.push(1) 
llist.push(3) 
llist.push(2) 

print "Lista vinculada creada: "
llist.printList() 
llist.deleteNode(1) 
print "\nLinked List after Deletion of 1:"
llist.printList()
class LinkedList { 
	Node head; // al principio de la lista 

	// nodo de lista encadenada  
	class Node { 
		int data; 
		Node next; 
		Node(int d) 
		{ 
			data = d; 
			next = null; 
		} 
	} 
    // La función elimina la primera aparición de la clave dada en la lista encadenada 
    
	void deleteNode(int key) { 
		// almacena el nodo principal 
		Node temp = head, prev = null;

        // si el propio nodo principal contiene la clave que se eliminará 
		if (temp != null && temp.data == key) { 
			head = temp.next;  // cambia el encabezado de la lista 
			return;  
		} 

        // Encuentre la clave para eliminar, continuando 
        // el nodo anterior porque necesitamos cambiar el nodo posterior 
        // temp.next 
		while (temp != null && temp.data != key) { 
			prev = temp; 
			temp = temp.next; 
		}	 
		// si la clave no está en la lista de subprocesos 
		if (temp  == null)  return; 

        // Desvincular el nodo de la lista de subprocesos 
		prev.next = temp.next; 
	} 
	// El método inserta un nuevo nodo al comienzo de la lista de subprocesos 
   public void push(int new_data) { 
		Node new_node = new Node(new_data); 
		new_node.next = head; 
		head = new_node; 
	} 

	/* Esta función imprime el contenido de la lista 
	encadenada a partir del nodo dado */ 
  public void printList() { 
		Node tnode = head; 
		while (tnode != null) { 
			System.out.print(tnode.data+" "); 
			tnode = tnode.next; 
		} 
	} 
        // probar funciones anteriores 
	public static void main(String[] args) 
	{ 
		LinkedList llist = new LinkedList(); 

		llist.push(7); 
		llist.push(1); 
		llist.push(3); 
		llist.push(2); 

		System.out.println("\n Lista vinculada creada:"); 
		llist.printList(); 

		llist.deleteNode(1);   // elimina el nodo en la ubicación 1

		System.out.println("\n Lista enlazada después de la eliminación en la posición 4:"); 
		llist.printList(); 
	} 
}

El código anterior da el siguiente resultado:

Lista enlazada creada
 2 3 1 7
Lista encadenada después de eliminar el elemento 1
 2 3 7

Eliminación de un nodo de una lista encadenada en función de la ubicación

Si el nodo a eliminar es el primer nodo, se puede eliminar directamente, de lo contrario debe haber un puntero al nodo anterior del nodo a eliminar. Entonces, si la ubicación es cualquier cosa menos cero, debe repetir iterativamente (ubicación – 1) veces para obtener el puntero al nodo anterior.

Los siguientes ejemplos muestran cómo eliminar un nodo de una lista encadenada según la ubicación:

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

// nodo en la lista encadenada 
struct Node { 
	int data; 
	struct Node *next; 
} 
/* La siguiente función inserta un nuevo nodo al frente de la lista encadenada 
usando un puntero al encabezado de la lista y el entero dado */ 
void push(struct Node** head_ref, int new_data) { 
	struct Node* new_node = (struct Node*) malloc(sizeof(struct Node)); 
	new_node->data = new_data; 
	new_node->next = (*head_ref); 
	(*head_ref) = new_node; 
} 
/* La siguiente función elimina el nodo en la ubicación dada 
usando una referencia (puntero a un puntero) al encabezado de la lista y la ubicación dada */ 
void deleteNode(struct Node **head_ref, int position) { 
// si el la lista 
if (*head_ref == NULL) 
	return; 

// almacenar el nodo de encabezado de lista 
struct Node* temp = *head_ref;

	// si el nodo a eliminar es 
	if (position == 0) { 
		*head_ref = temp->next;  // cambiar el encabezado del menú 
		free (temp); 			 
		return;  
	} 

	// Encuentre el nodo anterior del nodo a eliminar 
	for (int i=0; temp!=NULL && i<position-1; i++) 
		temp = temp->next; 

	// si la ubicación es mayor que el número de nodos 
	if (temp == NULL || temp->next == NULL) 
		return;
	// temp->next 
	// es el nodo a eliminar 
	// almacena el puntero al siguiente nodo a eliminar 
	struct Node *next = temp->next->next; 

	// desvincular el nodo de la lista de subprocesos 
	free(temp->next);  // Vaciar la memoria ocupada por el nodo

	temp->next = next;  // desvincular el nodo de la lista de hilos 
} 

// Esta función imprime el contenido de la lista encadenada a partir del nodo dado 
void printList(struct Node *node) { 
	while (node != NULL) 
	{ 
		printf(" %d ", node->data); 
		node = node->next; 
	} 
} 
// prueba las funciones anteriores 
int main() { 
	// comienza con una lista de subprocesos vacía 
	struct Node* head = NULL; 

	push(&head, 7); 
	push(&head, 1); 
	push(&head, 3); 
	push(&head, 2); 
	push(&head, 8); 

	puts("Lista vinculada creada: "); 
	printList(head); 
	deleteNode(&head, 4); 
	puts("\n Lista enlazada después de la eliminación en la posición 4: "); 
	printList(head); 
	return 0; 
}
# nodo de clase
class Node:

	# Función del constructor para inicializar el objeto de nodo 
	def __init__(self, data): 
		self.data = data 
		self.next = None

class LinkedList: 
	# Inicializa el encabezado de la lista 
	def __init__(self): 
		self.head = None

	# La función inserta un nuevo nodo al frente de la lista 
	def push(self, new_data): 
		new_node = Node(new_data) 
		new_node.next = self.head 
		self.head = new_node

	# La siguiente función elimina el nodo en la ubicación dada 
	# usando una bandera del encabezado de la lista y la ubicación dada */

	def deleteNode(self, position): 

		# si la lista encadenada está vacía 
		if self.head == None: 
			return

		# almacena la temperatura del  nodo 
        temp = self.head

		# si se va a eliminar el encabezado de la lista 
		if position == 0: 
			self.head = temp.next
			temp = None
			return

		# Encuentre el nodo anterior del nodo para eliminar 
		for i in range(position -1 ): 
			temp = temp.next
			if temp is None: 
				break
		# si la ubicación dada es mayor que el número de elementos en la lista 
		if temp is None: 
			return
		if temp.next is None: 
			return
		#temp.next 
		# es el nodo que se eliminará 
		# El puntero se almacena en el nodo que sigue al nodo que se eliminará 
		next = temp.next.next

		# Desvincular el nodo de la lista de subprocesos 
		temp.next = None

		temp.next = next


	# Función de utilidad para imprimir la LinkedList vinculada 
	def printList(self): 
		temp = self.head 
		while(temp): 
			print " %d " %(temp.data), 
			temp = temp.next


# Probar las funciones anteriores 
llist = LinkedList() 
llist.push(7) 
llist.push(1) 
llist.push(3) 
llist.push(2) 
llist.push(8) 

print "Lista vinculada creada: "
llist.printList() 
llist.deleteNode(4) 
print "\n Lista enlazada después de la eliminación en la posición 4: "
llist.printList()
class  LinkedList  {  
	Node head; // al principio de la lista 

	/* Nodo en la lista de hilos*/ 
	class Node { 
		int data; 
		Node next; 
		Node(int d) 
		{ 
			data = d; 
			next = null; 
		} 
	} 
	/* Inserta un nuevo nodo al frente de la lista */ 
	public void push(int new_data) { 
		/* 1: Reserve una ubicación de nodo en la memoria 
		2: agregue datos */ 
		Node new_node = new Node(new_data);

		/* 3: Hacer que el siguiente nodo nuevo sea el encabezado de la lista de subprocesos */ 
		new_node.next = head;

		/* 4: Mover la cabeza para señalar el nuevo nodo */ 
		head = new_node;   
	} 

	/* La función elimina el nodo en la ubicación dada 
	usando un puntero al encabezado y la ubicación dada */ 
	void deleteNode(int position) {  
      // si la lista encadenada está vacía 
      if (head == null) 
			return;
		 
		// almacena el nodo de cabecera de la lista 
		Node temp = head;

		// 
		if (position == 0) { 
			head = temp.next;  // cambia el encabezado de la lista 
			return ;  
		} 

		// Encuentre el nodo que precede al nodo que se eliminará 
		for (int i=0; temp!=null && i<position-1; i++) 
			temp = temp.next;
      
		// si la ubicación solicitada es mayor que el número de nodos en la lista de subprocesos 
		if (temp == null || temp.next == null) 
			return; 

		// temp->next 
		// es el nodo que se eliminará 
		// almacena el puntero al nodo junto al nodo que se eliminará 
		Node next = temp.next.next; 

		temp.next = next;  // desvincular el nodo de la lista de hilos 
	} 

	// Esta función imprime el contenido de la lista encadenada a partir del nodo dado 
      public void printList() { 
		Node tnode = head; 
		while (tnode != null) 
		{ 
			System.out.print(tnode.data+" "); 
			tnode = tnode.next; 
		} 
	} 

// prueba los discípulos anteriores 
	public static void main(String[] args) { 
		/* menú de inicio vacío */ 
		LinkedList llist = new LinkedList(); 

		llist.push(7); 
		llist.push(1); 
		llist.push(3); 
		llist.push(2); 
		llist.push(8); 

		llist.printList(); 

		llist.deleteNode(4);  // elimina el nodo en la posición 4

		System.out.println( "\nLista enlazada después de la eliminación en la posición 4: " );  
		llist.printList(); 
	} 
}

El código anterior da el siguiente resultado:

Lista enlazada establecida: 
 8 2 3 1 7 
La lista encadenada después de eliminar el elemento en la posición 4: 
 8 2 3 1

Buscar un elemento en la lista encadenada

Puede buscar un elemento en la lista encadenada de dos maneras:

  1. método iterativo.
  2. método recursivo.

método iterativo

El método iterativo incluye los siguientes pasos:

  1. inicialización del puntero de nodo, current = head
  2. Realice lo siguiente siempre que el valor current no sea Null
    1. Si es current->key igual a la clave a buscar, devolvemos el valor true.
    2. atribución current->next a current
    3. valor de retorno false.

Los siguientes ejemplos muestran cómo implementar un método iterativo para encontrar un nodo específico en la lista de subprocesos y en varios lenguajes de programación (C++, Python, Java) :

#include <bits/stdc++.h> 
using namespace std; 

/* Nodo en la lista de hilos */ 
class Node { 
	public: 
	int key; 
	Node* next; 
} 
/* Esta función agrega un nuevo nodo al frente de la lista encadenada 
usando una bandera (un puntero a un puntero) al encabezado de la lista y el entero dado */

void push(Node** head_ref, int new_key){ 
	/* Reservar la ubicación del nodo en la memoria */ 
	Node* new_node = new Node();

	/* añadir clave */ 
	new_node->key = new_key;

	/* 
	Separar la lista anterior del nuevo nodo */ 
    new_node->next = (*head_ref); 

	/* Mueve el encabezado de la lista para que apunte al nuevo nodo */ 
	(*head_ref) = new_node;  
} 

/* Verifica que el valor dado esté en la lista de subprocesos */ 
bool search(Node* head, int x) { 
	Node* current = head;  // inicializa el nodo actual 
	while (current != NULL) { 
		if (current->key == x) 
			return true; 
		current = current->next; 
	} 
	return false; 
} 
/* prueba las funciones anteriores*/ 
int  main()  {  
	/* comienza con una lista de subprocesos vacía */ 
	Node* head = NULL; 
	int x = 21; 

	/* push() Usa la función 
	para crear la siguiente lista 
	encadenada 
	: 14->21->11->30->10 */ 
    push(&head, 10); 
	push(&head, 30); 
	push(&head, 11); 
	push(&head, 21); 
	push(&head, 14); 

	search(head, 21)? cout<<"Yes" : cout<<"No"; 
	return 0; 
}
#  nodo de clase  
class Node: 
	
	# Inicializar el objeto de nodo 
	def __init__(self, data): 
		self.data = data # Asignar datos 
		self.next = None  # Inicializar siguiente como nulo
# 
class LinkedList: 
	def __init__(self): 
		self.head = None  # Inicializar el encabezado de la lista

	# Este método inserta un nuevo nodo al comienzo de la lista encadenada 
    def push(self, new_data): 
	
		# crear un nuevo nodo 
		new_node = Node(new_data) 

		# Hacer el encabezado de la lista después de   
		new_node.next = self.head 

		# Mueva el encabezado para que apunte al nuevo nodo 
		self.head = new_node 

	# Esta función verifica si el valor dado existe en la lista de subprocesos 
	def search(self, x): 

		# Inicializa el encabezado 
		current = self.head 

		# Repetir hasta que el valor de 
		# Ninguno para el nodo actual sea 
		while current != None: 
			if current.data == x: 
				return True # datos encontrados
			
			current = current.next
		
		return False  # No se encontraron los datos solicitados


# Probar las funciones anteriores 
if __name__ == '__main__': 

	# comenzar con una lista vacía 
	llist = LinkedList()

	''' Usamos el método 	
        push() para crear la siguiente lista 
		encadenada : 14->21->11->30->10 ''' 
    llist.push(10); 
	llist.push(30); 
	llist.push(11); 
	llist.push(21); 
	llist.push(14); 

	if llist.search(21): 
		print("Si") 
	else: 
		print("No")
//  clase noo
class Node { 
	int data; 
	Node next; 
	Node(int d) { 
		data = d; 
		next = null; 
	} 
} 
class LinkedList { 
	Node head; // al principio de la lista 

	// inserta un nodo al principio de la lista 
	public void push(int new_data) { 
		// reserva una ubicación para el nuevo nodo en la memoria y agrega datos 
		Node new_node = new Node(new_data);

		// Hacer que el encabezado de la lista siga al siguiente nodo 
		new_node.next = head; 

		// mueve el encabezado de la lista para que apunte al nuevo nodo 
		head = new_node; 
	} 

	// Comprueba si el valor dado está en la lista de subprocesos de 
	public boolean search(Node head, int x) { 
		Node current = head; // inicializa el encabezado actual 
        while (current != null) { 
			if (current.data == x) 
				return true; // Se encontraron los datos solicitados 
          current = current.next; 
		} 
		return false;     
	} 

	// Probar las funciones anteriores 
	public static void main(String args[]) { 

		// comenzar con una lista 
		LinkedList llist = new LinkedList();    

		/* Usa el método push() 
		para crear la siguiente lista 
		encadenada 14->21->11->30->10 */ 
		llist.push(10); 
		llist.push(30); 
		llist.push(11); 
		llist.push(21); 
		llist.push(14); 

		if (llist.search(llist.head, 21)) 
			System.out.println("Si"); 
		else
			System.out.println("No"); 
	} 
}

El código anterior da el siguiente resultado:

Método recursivo

La función trabaja search(head, x)‎ de manera recursiva de acuerdo a los siguientes pasos:

  1. Si el vértice es igual, Null la función devuelve el valor false.
  2. Si la clave para el encabezado es la x misma, la función devuelve el valor true.
  3. De lo contrario, la función devuelve el resultado de la llamada a la función search(head->next, x)‎.

Los siguientes ejemplos muestran cómo realizar una búsqueda recursiva en varios lenguajes de programación (C, Python, Java) :

#include<stdio.h> 
#include<stdlib.h> 
#include<stdbool.h> 
/* Nodo en la lista de hilos */ 
struct Node { 
	int key; 
	struct Node* next; 
} 
/* La función inserta un nuevo nodo al frente de la lista encadenada 
usando un puntero al encabezado de la lista y el entero dado 
*/
void push(struct Node** head_ref, int new_key) { 
	/* Reservar la ubicación del nodo en la memoria */ 
	struct Node* new_node = 
			(struct Node*) malloc(sizeof(struct Node));
	/* añadir clave */ 
	new_node->key = new_key;

	/* Desconexión entre la lista de subprocesos y el nuevo nodo */ 
	new_node->next = (*head_ref);

	/* Mueve el encabezado de la lista para que apunte al nuevo nodo */ 
	(*head_ref) = new_node; 
} 
/* Comprobar si el valor dado está en la lista de subprocesos */ 
bool search(struct Node* head, int x) {  
	// Prerequisito 
	if (head == NULL) 
		return false; 
	
	// devuelve verdadero si la clave requerida está en la lista 
	if (head->key == x) 
		return true;

	// La función se ejecuta recursivamente para encontrar la clave requerida 
     return search(head->next, x); 
} 

/* Probar las funciones anteriores*/ 
int  main(){  
	/* comenzar con una lista vacía */ 
	struct Node* head = NULL; 
	int x = 21; 
	/* La función push() se usa 	
    para crear la siguiente lista 
	encadenada 14->21->11->30->10 */ 
	push(&head, 10); 
	push(&head, 30); 
	push(&head, 11); 
	push(&head, 21); 
	push(&head, 14); 

	search(head, 21)? printf("Si") : printf("No"); 
	return 0; 
}
# nodo de clase  
class node : 
	
	# Inicializar el objeto de nodo 
	def __init__(self, data): 
		self.data = data # Asignar datos
		self.next = None  # Inicializar siguiente como nulo

# Ordenar la lista enlazada
class LinkedList: 
	def __init__(self): 
		self.head = None  # Inicializar el encabezado de la lista

	# Este método inserta un nuevo nodo al principio de la lista de subprocesos 
	def push(self, new_data):
	
		# crear un nuevo nodo 
		new_node = Node(new_data)

		# Hacer el encabezado de la lista después de   
		new_node.next = self.head  

		# Mueva el encabezado para que apunte al nuevo nodo 
		self.head = new_node 

	# Esta función comprueba si el valor dado existe en la lista de subprocesos 
	def search(self, li, key):   
		
		# requisito previo 
		if(not li): 
			return False

		# devuelve verdadero 
		# si la clave está en el nodo actual 
		if(li.data == key): 
			return True

		# Ejecuta la función de forma recursiva en el resto de los nodos de la lista de subprocesos 
		return self.search(li.next, key)


# Probar las funciones anteriores 
if __name__ == '__main__': 

	# comenzar con una lista vacía 
	llist = LinkedList()

	''' Usamos el método push() 
	    para crear la siguiente lista 
		encadenada: 14->21->11->30->10 ''' 
    llist.push(10); 
	llist.push(30); 
	llist.push(11); 
	llist.push(21); 
	llist.push(14); 

	if llist.search(21): 
		print("Si") 
	else: 
		print("No")
//  Nodo de clase 
 class Node { 
	int data; 
	Node next; 
	Node(int d) 
	{ 
		data = d; 
		next = null; 
	} 
} 
// Ordenar la lista enlazada
class LinkedList { 
	Node head; // al principio de la lista 

	// inserta un nodo al principio de la lista 
	public void push(int new_data) { 
		// reserva una ubicación para el nuevo nodo en la memoria y agrega datos 
		Node new_node = new Node(new_data);

		// Hacer que el encabezado de la lista siga al siguiente nodo 
		new_node.next = head; 

		// mueve el encabezado de la lista para que apunte al nuevo nodo 
		head = new_node;   
	} 

	// Verifique que el valor dado esté en la lista de subprocesos
	public boolean search(Node head, int x) { 
      // Requisito previo
      if (head == null) 
            return false;
        // devuelve verdadero 
        // si la clave está en el nodo actual 
       if (head.data == x) 
            return true;
        // Ejecuta una función recursiva en el resto de los nodos en la lista de subprocesos
        return search(head.next, x); 
    }  

	// Probar las funciones anteriores 
	public static void main(String args[]) { 

		// comenzar con una lista enlazada vacía 
          LinkedList llist = new LinkedList();   

		/* Usa el método push() 
		para crear la siguiente lista 
		encadenada 14->21->11->30->10 */ 
		llist.push(10); 
		llist.push(30); 
		llist.push(11); 
		llist.push(21); 
		llist.push(14); 

		if (llist.search(llist.head, 21)) 
			System.out.println("Si"); 
		else
			System.out.println("No"); 
	} 
}

Fuente