Algoritmos relacionados con la lista vinculada

Recientemente encontré un curso de alta calidad en una estación, las siguientes son las notas del curso.

Operación básica

Estructura de nodo

typedef struct{
    int val;
    Node* next;
}Node;

Encontrar operación

Node* search(int val){
    Node* pNode = root; // 根结点
    while(pNode != nullptr)
         if(pNode->val == val){
             return pNode;
          }
         pNode = pNode->next;
        }
     return nullptr;
 }

Operación de eliminación: proporcione el nodo anterior del nodo que se va a eliminar

void delNode(Node* prev){
	Node* curr = prev->next;
	prev->next = curr->next;
	delete curr;
}

Operación de eliminación: dé al nodo que se va a eliminar

void delNode(Node* curr){
	if(curr->next != nullptr){
		Node* temp = curr->next;
		curr->val = temp->val;
		curr->next = temp->next;
		delete temp;
	}else{
		Node* pNode = root; // 头节点
		while(pNode->next != curr){
			pNode = pNode->next;
		}
		pNode->next = nullptr;
		delete curr;
	}
}

Algoritmos relacionados

Desduplicación de elementos de lista vinculados

Eliminar duplicados de la lista
ordenada Dada una lista vinculada ordenada, elimine todos los duplicados de modo que cada elemento aparezca solo una vez. Por ejemplo, Dado 1-> 1-> 2, devuelva 1-> 2.Dado 1-> 1-> 2-> 3-> 3, devuelve 1-> 2-> 3

Node* deleteDuplicates(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* node = head;
	while(node->next != nullptr){
		if(node->val == node->next->val){
			Node* temp = node->next;
			node->next = temp->next;
			delete temp;
		}else{
			node = node->next;
		}
	}
	return head; 
}

Consejos sobre nodos ficticios
Considere:
a. El siguiente puntero que se verá afectado, debe modificar el puntero
b. Si el nodo que se va a eliminar es un espacio de memoria que se abre dinámicamente, debe liberar esta parte de la memoria (c / c ++)
usando el nodo ficticio. un truco muy útil: siempre y cuando la incertidumbre involucrada en la operación del nodo principal, la operación nodo principal, podría crear el muñeco nodo:
NodoLista
ficticia = new nueva NodoLista (0);
dummy-> = la cabeza Siguiente;
*
.
.

Eliminar duplicados de la lista ordenada ||
Dada una lista vinculada ordenada, elimine todos los nodos que tengan números duplicados, dejando solo números distintos de la lista original.
Por ejemplo,
Dado 1-> 2-> 3-> 3-> 4-> 4-> 5, regrese 1-> 2-> 5.
Dado 1-> 1-> 1-> 2-> 3, devuelve 2-> 3

Node* deleteDuplicates(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* dummy = new Node(0);
	dummy->next = head;
	Node* node = dummy;
	while(node->next != nullptr && node->next->next != nullptr){
		if(node->next->val == node->next->next->val){
			int val_pre = node->next->val;
			while(node->next != nullptr && val_pre == node->next->val){
				Node* temp = node->next;
				node->next = temp->next;
				delete temp;
			}
		}else{
			node = node->next;
		}
	}
	return dummy->next;
}

Dada una lista vinculada y un valor, escriba un reordenamiento para reorganizar la lista vinculada de modo que la relación pequeña esté todo a la izquierda y la relación grande esté a la derecha

Node* partition(Node* head, int x){
	if(head == nullptr){
		return nullptr;
	}
	Node* dummyleft = new Node(0);
	Node* dummyright = new Node(0);
	Node* left = dummyleft;
	Node* right = dummyright;
	Node* node = head;
	while(node->next != nullptr){
		if(node->val < x){
			left->next = node;
			left = left->next;
		}else{
			right->next = node;
			right = right->next;
		}
		node = node->next;
	}
	left->next = dummyright->next;
	right->next = nullptr;
	return dummyleft->next;
}

Capturar habilidades de puntero

Para el problema de encontrar una posición específica de la lista, puede usar dos cazadores y corredores para recorrer la lista a diferentes velocidades para encontrar la posición de destino: Nodo chaser = head, runner = head. Y puede usar un pequeño caso de prueba simple para verificar

Encuentra el punto medio de una lista vinculada

Node* midpoint(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* chaser = head, runner = head;
	while(runner && runner->next){
		runner = runner->next->next;
		chaser = chaser->next;
	}
	return chaser;
}

Encuentre el penúltimo nodo k de la lista vinculada

Node* findkthtoLast(Node* head, int k){
	if(head == nullptr || k < 0){
		return nullptr;
	}
	Node* runner = head;
	Node* chaser = head;
	while(k){
		runner = runner->next;
	}
	if(runner == nullptr){
		return nullptr;
	}
	while(runner->next != nullptr){
		runner = runner->next;
		chaser = chaser->next;
	}
	return chaser;
}

Dada una lista vinculada con anillos, busque el nodo donde comienza el anillo

Análisis: para encontrar una ubicación específica, utilice la técnica del corredor. El corredor atraviesa al doble de la velocidad, suponiendo que haya un bucle, entonces el corredor y el perseguidor deben poder encontrarse en cierto punto. Después del encuentro, deje que el perseguidor se dispare desde la cabeza para alcanzar al corredor nuevamente, y el nodo del segundo encuentro es la posición donde comienza el bucle.

Cómo juzgar si dos listas enlazadas individualmente tienen una intersección

Mueva el nodo después del elemento k de la lista vinculada al frente

Ejemplo:
lista = 10-> 20-> 30-> 40-> 50-> 60 k = 4
cambio a 50-> 60-> 10-> 20-> 30-> 40

void rotate(Node** root, int k){
	if(k == 0){
		return;
	}
	Node* current = root;
	for(int count = 1; count < k && current != nullptr;count++){
		current = current->next;
	}
	if(current == nullptr){
		return;
	}
	Node *kthNode = current;
	while(current->next != nullptr){
		current = current->next;
	}
	current->next = root;
	root = kthNode->next;
	kthNode->next = nullptr;
}

.
Reconocimiento de Patrones
1. cuando se atraviesa una lista enlazada, nota que cada asas de bucle sólo uno o un par de nodos. El nodo central solo maneja el actual, de lo contrario es fácil tener problemas de procesamiento repetidos.

.

Lista vinculada inversa

Invertir lista vinculada
Invierta la lista vinculada y devuelva el nuevo encabezado.

- 递归 版本 -

Node* reverseList(Node* head){
	if(head == nullptr){
		return nullptr;
	}
	Node* prev = nullptr;
	while(head != nullptr){
		Node* curr = head;
		head = head->next;
		curr->next = prev;
		prev = curr;
	}
	return prev;
}

—Versión no recursiva—

Node* reverseList(Node* head){
	if(head == nullptr){
		return head;
	}
	if(head->next == nullptr){
		return head;
	}
	Node* newHead = reverseList(head->next);
	head->next->next = head;
	head->next = nullptr;
	return newhead;
}

.
Reconocimiento de Patrones
2. Intercambio de interrogación Nodo
3. canje de los dos nodos, no hay supresión de las palabras, al lado del puntero prev dos nodos linfáticos, y el siguiente puntero de estos dos nodos se verán afectados. Siempre es posible
a. Primero intercambie los valores de los siguientes punteros de los dos nodos previos
b. Luego intercambie los valores de los siguientes punteros de los
dos nodos Independientemente de las posiciones relativas y absolutas de los dos nodos, el método de procesamiento anterior siempre es válido

.

Intercambia dos nodos adyacentes

Intercambiar nodos adyacentes
Dada una lista vinculada, intercambiar cada dos nodos adyacentes y devolver su cabecera.

Node* swapPairs(Node* head){
	if(head == nullptr){
		return head;
	}
	Node* dummy = new Node(0);
	dummy->next = head;
	Node* prev = dummy;
	Node* node1 = head;
	Node* node2 = head->next;
	while(node1 && node1->next != nullptr){
		node2 = node1->next;
		prev->next = node1->next;
		
		node1->next = node2->next;
		node2->next = node1;

		prev = node1;
		node1 = prev->next;
	}
	return dummy->next;
}

.
Reconocimiento de patrones
3. El proceso de dos problemas lista de enlaces, las condiciones circulatorias generalmente pueden utilizar mientras que (L1 && L2), y luego manejar el resto de la lista de no-NULL En este caso, el caso límite de un tratamiento especial, el caso convencional el tratamiento convencional.

.

Adición de lista vinculada

Agregar suma de lista
Dadas dos listas vinculadas, cada elemento de las listas es un número entero. Escriba una función para devolver una nueva lista, que es la "suma" de las dos listas dadas.
Parte a. Dada la entrada (7-> 1-> 6) + (5-> 9-> 2), salida 2-> 1-> 9.
Parte B. Dada la entrada (6-> 1-> 7) + (2-> 9-> 5), salida 9-> 1-> 2.

Parte a–

Node* addTwoNumbers(Node* l1, Node* l2){
	Node dummy(0);
	Node* p = &dummy;
	int cn = 0;
	while(l1 || l2){
		int val = cn + (l1 ? l1->val : 0) + (l2 ? l2->val : 0);
		cn = val / 10;
		val = val % 10;
		p->next = new Node(val);
		p = p->next;
		if(l1){
			l1 = l1->next;
		}
		if(l2){
			l2 = l2->next;
		}
	}
	if(cn != 0){
		p->next = new Node(cn);
		p = p->next;
	}
	return dummy->next;
}

Parteb-
Análisis del problema: para a, la solución del nodo frontal no depende del nodo posterior, por lo que es suficiente para atravesar la solución en secuencia. Para b, la solución del nodo frontal depende del nodo posterior (carry), por lo que debe procesarse por recursividad o pila. Y, el resultado devuelto por un subproblema puede ser una estructura personalizada (carry + sub-list). Por supuesto, también puede usar la solución de a después de resolver la lista inversa.

Combina dos o más listas vinculadas ordenadas

Combinar dos
listas ordenadas Combine dos listas vinculadas ordenadas y devuélvalas como una nueva lista.

Node* mergeTwoLists(Node* l1, Node* l2){
	Node* dummy = new Node(0);
	Node* curr = dummy;
	while(l1 && l2){
		if(l1->val <= l2->val){
			curr->next = l1;
			l1 = l1->next;
		}{
			curr->next = l2;
			l2 = l2->next;
		}
		curr = curr->next;
	}
	curr->next = (l1 != nullptr) ? l1 : l2;
	return dummy->next;
}

Combinar K Lista ordenada

Node* mergeKLists(vector<Node*>&lists){
	if(lists.size() == 0)return nullptr;
	Node* p = lists[0];
	for(int i = 0; i < l1sts.size(); i++){
		p = mergeTwoLists(p, lists[i]);
	}
	return p;
} 

¡No terminado!

21 artículos originales publicados · Me gusta0 · Visitas 163

Supongo que te gusta

Origin blog.csdn.net/qq_45227330/article/details/105060058
Recomendado
Clasificación