Lógica das Listas Encadeadas

Listas Encadeadas

Inserção:

  • Primeiro atualize o novo nó inserido
  • Em seguida modifique os nós desconhecidos (como x)
  • Finalmente ajuste os nós conhecidos (como y, z)

Esta sequência pode ser aplicada a todas as operações lógicas de listas encadeadas

Remoção: Da mesma forma, quando não há novos nós adicionados, os nós desconhecidos são y e z, resultando na remoção do nó x.

Definição usando arrays simulados: Utilize os arrays prev[] e next[] para registrar predecessores e sucessores:

// Definindo nó cabeça
nodes[0].next = 1;
nodes[1].prev = 0, nodes[1].next = 0, nodes[1].value = 1;
// Onde nodes[1].next = 0 indica a cauda, ou seja, o ponto final do programa
// Percorrer
for (int current = nodes[0].next; current != 0; current = nodes[current].next) 
    cout << nodes[current].value << ' ';

Ambas as formas de percorrer verificam diretamente quem é o próximo nó, continuando até que o próximo não seja a cauda

Clique para ver o código

#include <bits/stdc++.h>
using namespace std;
const int MAX_SIZE = 1e5 + 10;
int total, queries, value, position, next_node[MAX_SIZE], active[MAX_SIZE], prev_node[MAX_SIZE];

int main() {
    cin >> total;
    next_node[0] = 1;
    active[1] = 1;
    for(int i = 2; i <= total; ++i) {
        active[i] = 1;
        cin >> value >> position;
        
        if(!position) { // Inserir à esquerda
            next_node[prev_node[value]] = i;
            prev_node[i] = prev_node[value];
            prev_node[value] = i;
            next_node[i] = value;
        }
        else { // Inserir à direita
            prev_node[next_node[value]] = i;
            next_node[i] = next_node[value];
            next_node[value] = i;
            prev_node[i] = value;
        }
    }
    cin >> queries;
    for(int i = 1; i <= queries; ++i) {
        int target;
        cin >> target;
        if(!active[target]) continue;
        active[target] = 0;
        // Remover este elemento
        int temp = prev_node[target];
        next_node[prev_node[target]] = next_node[target];
        prev_node[next_node[target]] = temp;
    }
    // Percorrer a lista
    int current = next_node[0];
    while(current != 0) {
        cout << current << ' ';
        current = next_node[current];
    }
    cout << endl;
}

Usando estrutura de dados:

// Definindo nó cabeça
next_node[0] = 1;
next_node[1] = 0; // Indicando a cauda
// Percorrendo a lista
int current = next_node[0];
while(current != 0) {
    cout << current << ' ';
    current = next_node[current];
}

Clique para ver o código

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

struct ListNode {
    int data, previous, next;
};

ListNode nodes[1000010];
int count, operations, left_pos, right_pos;

void insert_node(int node_id, int reference, int side) { // Insere node_id à esquerda/direita de reference
    nodes[node_id].data = node_id;
    if(side == 0) { // Esquerda
        // Processar lado anterior
        nodes[node_id].previous = nodes[reference].previous;
        nodes[nodes[reference].previous].next = node_id;
        
        nodes[node_id].next = reference, nodes[reference].previous = node_id;
    }
    else { // Direita
        // Processar lado posterior
        nodes[nodes[reference].next].previous = node_id;
        nodes[node_id].next = nodes[reference].next;
        
        nodes[node_id].previous = reference, nodes[reference].next = node_id;
    }
}

void remove_node(int node_id) {
    nodes[node_id].data = -1;
    nodes[nodes[node_id].previous].next = nodes[node_id].next;
    nodes[nodes[node_id].next].previous = nodes[node_id].previous;
}

int main() {
    cin >> count;
    nodes[0].next = 1;
    nodes[1].previous = 0, nodes[1].next = 0, nodes[1].data = 1; // Lembre-se de definir também o valor
    
    for(int i = 2; i <= count; ++i) {
        cin >> left_pos >> right_pos;
        insert_node(i, left_pos, right_pos); // Valor, onde inserir
    }
    
    cin >> operations;
    while(operations--) {
        cin >> left_pos;
        if(nodes[left_pos].data == -1) continue;
        remove_node(left_pos);
    }
    
    for (int i = nodes[0].next; i != 0; i = nodes[i].next) 
        cout << nodes[i].data << ' ';
    
    return 0;
}

Por que existem dois métodos de inicialização do nó cabeça? O array apenas registra posições sem armazenar valores, enquanto a estrutura define uma tripla e next[1] = 0 registra o nó cauda para evitar erros de percurso e garantir a correta remoção dos nós.

Tags: listas-encadeadas estruturas-de-dados Algoritmos programacao-cpp

Publicado em 8-12 11:43