linked list data structure c with illustration
Um estudo detalhado da lista vinculada em C ++.
Uma lista vinculada é uma estrutura de dados dinâmica linear para armazenar itens de dados. Já vimos arrays em nossos tópicos anteriores sobre C ++ básico. Também sabemos que arrays são estruturas de dados lineares que armazenam itens de dados em locais contíguos.
Ao contrário dos arrays, a lista vinculada não armazena itens de dados em locais de memória contíguos.
Uma lista vinculada consiste em itens chamados “Nós” que contêm duas partes. A primeira parte armazena os dados reais e a segunda parte possui um ponteiro que aponta para o próximo nó. Essa estrutura é geralmente chamada de “Lista vinculada única”.
=> Confira os melhores tutoriais de treinamento em C ++ aqui.
O que você aprenderá:
Lista vinculada em C ++
Vamos dar uma olhada na lista vinculada individualmente em detalhes neste tutorial.
O diagrama a seguir mostra a estrutura de uma lista vinculada individualmente.
Conforme mostrado acima, o primeiro nó da lista vinculada é denominado “cabeça”, enquanto o último nó é denominado “Cauda”. Como vemos, o último nó da lista vinculada terá seu próximo ponteiro como nulo, uma vez que não terá nenhum endereço de memória apontado.
Uma vez que cada nó tem um ponteiro para o próximo nó, os itens de dados na lista encadeada não precisam ser armazenados em locais contíguos. Os nós podem estar espalhados na memória. Podemos acessar os nós a qualquer momento, pois cada nó terá um endereço do próximo nó.
melhor bloqueador de anúncios pop-up para Chrome
Podemos adicionar itens de dados à lista vinculada, bem como excluir itens da lista facilmente. Assim, é possível aumentar ou diminuir a lista vinculada dinamicamente. Não há limite máximo de quantos itens de dados podem estar na lista vinculada. Assim, enquanto houver memória disponível, podemos ter tantos itens de dados adicionados à lista vinculada.
Além da fácil inserção e exclusão, a lista vinculada também não desperdiça espaço de memória, pois não precisamos especificar de antemão quantos itens precisamos na lista vinculada. O único espaço ocupado pela lista ligada é para armazenar o ponteiro para o próximo nó que adiciona um pouco de overhead.
A seguir, discutiremos as várias operações que podem ser realizadas em uma lista vinculada.
Operações
Assim como as outras estruturas de dados, podemos realizar várias operações para a lista vinculada também. Mas, ao contrário dos arrays, nos quais podemos acessar o elemento usando o subscrito diretamente, mesmo se estiver em algum lugar no meio, não podemos fazer o mesmo acesso aleatório com uma lista vinculada.
Para acessar qualquer nó, precisamos percorrer a lista vinculada desde o início e só então podemos acessar o nó desejado. Conseqüentemente, acessar os dados aleatoriamente da lista vinculada é caro.
Podemos realizar várias operações em uma lista vinculada conforme a seguir:
# 1) Inserção
A operação de inserção da lista vinculada adiciona um item à lista vinculada. Embora possa parecer simples, dada a estrutura da lista vinculada, sabemos que sempre que um item de dados é adicionado à lista vinculada, precisamos alterar os próximos ponteiros dos nós anterior e seguinte do novo item que inserimos.
A segunda coisa que devemos considerar é o local onde o novo item de dados deve ser adicionado.
Existem três posições na lista vinculada onde um item de dados pode ser adicionado.
# 1) No início da lista vinculada
Uma lista vinculada é mostrada abaixo de 2-> 4-> 6-> 8-> 10. Se quisermos adicionar um novo nó 1, como o primeiro nó da lista, então o cabeçalho apontando para o nó 2 agora apontará para 1 e o próximo ponteiro do nó 1 terá um endereço de memória do nó 2, conforme mostrado abaixo figura.
Assim, a nova lista vinculada torna-se 1-> 2-> 4-> 6-> 8-> 10.
# 2) Após o nó fornecido
Aqui, um nó é fornecido e temos que adicionar um novo nó após o nó fornecido. Na lista vinculada abaixo a-> b-> c-> d -> e, se quisermos adicionar um nó f após o nó c, então a lista vinculada terá a seguinte aparência:
Assim, no diagrama acima, verificamos se o nó fornecido está presente. Se estiver presente, criamos um novo nó f. Em seguida, apontamos o próximo ponteiro do nó c para apontar para o novo nó f. O próximo ponteiro do nó f agora aponta para o nó d.
# 3) No final da Lista Vinculada
No terceiro caso, adicionamos um novo nó no final da lista vinculada. Considere que temos a mesma lista ligada a-> b-> c-> d-> e e precisamos adicionar um nó f ao final da lista. A lista vinculada terá a aparência mostrada abaixo após adicionar o nó.
Assim, criamos um novo nó f. Então, o ponteiro final apontando para nulo é apontado para fe o próximo ponteiro do nó f é apontado para nulo. Implementamos todos os três tipos de funções de inserção no programa C ++ abaixo.
Em C ++, podemos declarar uma lista vinculada como uma estrutura ou como uma classe. Declarar a lista vinculada como uma estrutura é uma declaração de estilo C. tradicional. Uma lista vinculada como uma classe é usada no C ++ moderno, principalmente ao usar a biblioteca de modelos padrão.
No programa a seguir, usamos a estrutura para declarar e criar uma lista vinculada. Ele terá dados e um ponteiro para o próximo elemento como seus membros.
o que é um arquivo .eps
#include using namespace std; // A linked list node struct Node { int data; struct Node *next; }; //insert a new node in front of the list void push(struct Node** head, int node_data) { /* 1. create and allocate node */ struct Node* newNode = new Node; /* 2. assign data to node */ newNode->data = node_data; /* 3. set next of new node as head */ newNode->next = (*head); /* 4. move the head to point to the new node */ (*head) = newNode; } //insert new node after a given node void insertAfter(struct Node* prev_node, int node_data) { /*1. check if the given prev_node is NULL */ if (prev_node == NULL) { coutnext = prev_node->next; /* 5. move the next of prev_node as new_node */ prev_node->next = newNode; } /* insert new node at the end of the linked list */ void append(struct Node** head, int node_data) { /* 1. create and allocate node */ struct Node* newNode = new Node; struct Node *last = *head; /* used in step 5*/ /* 2. assign data to the node */ newNode->data = node_data; /* 3. set next pointer of new node to null as its the last node*/ newNode->next = NULL; /* 4. if list is empty, new node becomes first node */ if (*head == NULL) { *head = newNode; return; } /* 5. Else traverse till the last node */ while (last->next != NULL) last = last->next; /* 6. Change the next of last node */ last->next = newNode; return; } // display linked list contents void displayList(struct Node *node) { //traverse the list to display each node while (node != NULL) { coutnext; } if(node== NULL) cout Resultado:
Lista final vinculada:
30–> 20–> 50–> 10–> 40–> nulo
A seguir, implementamos a operação de inserção de lista vinculada em Java. Na linguagem Java, a lista vinculada é implementada como uma classe. O programa abaixo é semelhante em lógica ao programa C ++, a única diferença é que usamos uma classe para a lista vinculada.
class LinkedList { Node head; // head of list //linked list node declaration class Node { int data; Node next; Node(int d) {data = d; next = null; } } /* Insert a new node at the front of the list */ public void push(int new_data) { //allocate and assign data to the node Node newNode = new Node(new_data); //new node becomes head of linked list newNode.next = head; //head points to new node head = newNode; } // Given a node,prev_node insert node after prev_node public void insertAfter(Node prev_node, int new_data) { //check if prev_node is null. if (prev_node == null) { System.out.println('The given node is required and cannot be null'); return; } //allocate node and assign data to it Node newNode = new Node(new_data); //next of new Node is next of prev_node newNode.next = prev_node.next; //prev_node->next is the new node. prev_node.next = newNode; } //inserts a new node at the end of the list public void append(intnew_data) { //allocate the node and assign data Node newNode = new Node(new_data); //if linked list is empty, then new node will be the head if (head == null) { head = new Node(new_data); return; } //set next of new node to null as this is the last node newNode.next = null; // if not the head node traverse the list and add it to the last Node last = head; while (last.next != null) last = last.next; //next of last becomes new node last.next = newNode; return; } //display contents of linked list public void displayList() { Node pnode = head; while (pnode != null) { System.out.print(pnode.data+'-->'); pnode = pnode.next; } if(pnode == null) System.out.print('null'); } } //Main class to call linked list class functions and construct a linked list class Main{ public static void main(String() args) { /* create an empty list */ LinkedList lList = new LinkedList(); // Insert 40. lList.append(40); // Insert 20 at the beginning. lList.push(20); // Insert 10 at the beginning. lList.push(10); // Insert 50 at the end. lList.append(50); // Insert 30, after 20. lList.insertAfter(lList.head.next, 30); System.out.println('
Final linked list: '); lList. displayList (); } }
Resultado:
Lista final vinculada:
10–> 20–> 30–> 40–> 50–> nulo
Tanto no programa acima, C ++ quanto em Java, temos funções separadas para adicionar um nó na frente da lista, no final da lista e entre as listas fornecidas em um nó. No final, imprimimos o conteúdo da lista criada usando todos os três métodos.
# 2) Exclusão
Como a inserção, excluir um nó de uma lista vinculada também envolve várias posições de onde o nó pode ser excluído. Podemos excluir o primeiro nó, último nó ou um k-ésimo nó aleatório da lista vinculada. Após a exclusão, precisamos ajustar o próximo ponteiro e os outros ponteiros na lista vinculada de forma adequada para manter a lista vinculada intacta.
Na implementação C ++ a seguir, fornecemos dois métodos de exclusão, ou seja, exclusão do primeiro nó da lista e exclusão do último nó da lista. Primeiro criamos uma lista adicionando nós à cabeça. Em seguida, exibimos o conteúdo da lista após a inserção e cada exclusão.
#include using namespace std; /* Link list node */ struct Node { int data; struct Node* next; }; //delete first node in the linked list Node* deleteFirstNode(struct Node* head) { if (head == NULL) return NULL; // Move the head pointer to the next node Node* tempNode = head; head = head->next; delete tempNode; return head; } //delete last node from linked list Node* removeLastNode(struct Node* head) { if (head == NULL) return NULL; if (head->next == NULL) { delete head; return NULL; } // first find second last node Node* second_last = head; while (second_last->next->next != NULL) second_last = second_last->next; // Delete the last node delete (second_last->next); // set next of second_last to null second_last->next = NULL; return head; } // create linked list by adding nodes at head void push(struct Node** head, int new_data) { struct Node* newNode = new Node; newNode->data = new_data; newNode->next = (*head); (*head) = newNode; } // main function int main() { /* Start with the empty list */ Node* head = NULL; // create linked list push(&head, 2); push(&head, 4); push(&head, 6); push(&head, 8); push(&head, 10); Node* temp; cout<<'Linked list created ' Resultado:
Lista vinculada criada
10–> 8–> 6–> 4–> 2–
> NULL
Lista vinculada após exclusão do nó principal
8–> 6–> 4–> 2–
> NULL
Lista vinculada após a exclusão do último nó
8–> 6–> 4–> NULL
A seguir está a implementação Java para excluir nós da lista vinculada. A lógica de implementação é a mesma usada no programa C ++. A única diferença é que a lista vinculada é declarada como uma classe.
class Main { // Linked list node / static class Node { int data; Node next; }; // delete first node of linked list static Node deleteFirstNode(Node head) { if (head == null) return null; // Move the head pointer to the next node Node temp = head; head = head.next; return head; } // Delete the last node in linked list static Node deleteLastNode(Node head) { if (head == null) return null; if (head.next == null) { return null; } // search for second last node Node second_last = head; while (second_last.next.next != null) second_last = second_last.next; // set next of second last to null second_last.next = null; return head; } // Add nodes to the head and create linked list static Node push(Node head, int new_data) { Node newNode = new Node(); newNode.data = new_data; newNode.next = (head); (head) = newNode; return head; } //main function public static void main(String args()) { // Start with the empty list / Node head = null; //create linked list head = push(head, 1); head = push(head, 3); head = push(head, 5); head = push(head, 7); head = push(head, 9); Node temp; System.out.println('Linked list created :'); for (temp = head; temp != null; temp = temp.next) System.out.print(temp.data + '-->'); if(temp == null) System.out.println('null'); head = deleteFirstNode(head); System.out.println('Linked list after deleting head node :'); for (temp = head; temp != null; temp = temp.next) System.out.print(temp.data + '-->'); if(temp == null) System.out.println('null'); head = deleteLastNode(head); System.out.println('Linked list after deleting last node :'); for (temp = head; temp != null; temp = temp.next) System.out.print(temp.data + '-->'); if(temp == null) System.out.println('null'); } }
Resultado:
Lista vinculada criada:
9–> 7–> 5–> 3–> 1–
> nulo
Lista vinculada após a exclusão do nó principal:
7–> 5–> 3–> 1–
> nulo
melhor maneira de converter vídeos do youtube para mp3
Lista vinculada após a exclusão do último nó:
7–> 5–> 3–> nulo
Conte o número de nós
A operação para contar o número de nós pode ser executada enquanto percorre a lista vinculada. Já vimos na implementação acima que sempre que precisamos inserir / excluir um nó ou exibir o conteúdo da lista vinculada, precisamos percorrer a lista vinculada desde o início.
Manter um contador e incrementá-lo à medida que atravessamos cada nó nos dará a contagem do número de nós presentes na lista vinculada. Vamos deixar este programa para os leitores implementarem.
Matrizes e listas vinculadas
Tendo visto as operações e a implementação da lista vinculada, vamos comparar como os arrays e a lista vinculada são comparáveis entre si.
Arrays Listas vinculadas Matrizes têm tamanho fixo O tamanho da lista vinculada é dinâmico A inserção de novo elemento é cara A inserção / exclusão é mais fácil O acesso aleatório é permitido Acesso aleatório não é possível Os elementos estão em localização contígua Os elementos têm localização não contígua Nenhum espaço extra é necessário para o próximo ponteiro Espaço de memória extra necessário para o próximo ponteiro
Formulários
Como as matrizes e as listas vinculadas são usadas para armazenar itens e são estruturas de dados lineares, essas duas estruturas podem ser usadas de maneiras semelhantes para a maioria dos aplicativos.
Alguns dos aplicativos para listas vinculadas são os seguintes:
- Uma lista vinculada pode ser usada para implementar pilhas e filas.
- Uma lista vinculada também pode ser usada para implementar grafos sempre que tivermos que representá-los como listas de adjacência.
- Um polinômio matemático pode ser armazenado como uma lista vinculada.
- No caso da técnica de hashing, os baldes usados no hashing são implementados usando as listas vinculadas.
- Sempre que um programa requer alocação dinâmica de memória, podemos usar uma lista vinculada, já que as listas vinculadas funcionam com mais eficiência neste caso.
Conclusão
Listas vinculadas são as estruturas de dados usadas para armazenar itens de dados de maneira linear, mas em locais não contíguos. Uma lista ligada é uma coleção de nós que contém uma parte de dados e um próximo ponteiro que contém o endereço de memória do próximo elemento na lista.
O último elemento da lista tem seu próximo ponteiro definido como NULL, indicando assim o fim da lista. O primeiro elemento da lista é chamado de Cabeça. A lista vinculada oferece suporte a várias operações, como inserção, exclusão, passagem, etc. No caso de alocação de memória dinâmica, as listas vinculadas têm preferência sobre os arrays.
Listas vinculadas são caras no que diz respeito ao seu percurso, pois não podemos acessar aleatoriamente os elementos como matrizes. No entanto, as operações de exclusão de inserção são menos caras quando comparadas com matrizes.
Aprendemos tudo sobre listas vinculadas lineares neste tutorial. As listas vinculadas também podem ser circulares ou duplas. Teremos uma análise detalhada dessas listas em nossos próximos tutoriais.
=> Verifique aqui a série de treinamento C ++ completa.
Leitura recomendada
- Estrutura de dados de lista vinculada circular em C ++ com ilustração
- Estrutura de dados de lista duplamente vinculada em C ++ com ilustração
- Estrutura de dados da fila em C ++ com ilustração
- Estrutura de pilha de dados em C ++ com ilustração
- Estrutura de dados da fila de prioridade em C ++ com ilustração
- As 15 melhores ferramentas gratuitas de mineração de dados: a lista mais abrangente
- 15 melhores ferramentas ETL em 2021 (uma lista atualizada completa)
- Introdução às estruturas de dados em C ++