Home Algoritmos e estrutura de dados com C#
Post
Cancelar

Algoritmos e estrutura de dados com C#

Neste post, vou mostrar alguns exemplos de algoritmos e estruturas de dados comuns em C#, como arrays, listas, listas ligadas, hashsets, quicksort, tabela hash, fila, pilha, árvore e grafos.

Arrays

Um array é uma coleção de elementos do mesmo tipo, que são armazenados em posições consecutivas da memória. Para criar um array em C#, usamos a seguinte sintaxe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Criar um array de inteiros com 10 elementos
int[] array = new int[10];

// Atribuir valores aos elementos do array
array[0] = 1;
array[1] = 2;
array[2] = 3;
// ...

// Acessar os elementos do array
Console.WriteLine(array[0]); // Imprime 1
Console.WriteLine(array[1]); // Imprime 2
Console.WriteLine(array[2]); // Imprime 3
// ...

Para percorrer todos os elementos de um array, podemos usar um laço for ou um laço foreach:

1
2
3
4
5
6
7
8
9
10
11
// Usando um laço for
for (int i = 0; i < array.Length; i++)
{
    Console.WriteLine(array[i]); // Imprime cada elemento do array
}

// Usando um laço foreach
foreach (int element in array)
{
    Console.WriteLine(element); // Imprime cada elemento do array
}

Listas

Uma lista é uma coleção de elementos que podem ser de tipos diferentes, e que permite adicionar e remover elementos dinamicamente. Para criar uma lista em C#, usamos a classe List<T>, onde T é o tipo dos elementos da lista. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Criar uma lista de strings
List<string> list = new List<string>();

// Adicionar elementos à lista
list.Add("Bing");
list.Add("Google");
list.Add("Yahoo");

// Remover elementos da lista
list.Remove("Yahoo");

// Acessar os elementos da lista
Console.WriteLine(list[0]); // Imprime Bing
Console.WriteLine(list[1]); // Imprime Google
Console.WriteLine(list[2]); // Imprime uma exceção, pois o índice é inválido

Para percorrer todos os elementos de uma lista, podemos usar um laço for ou um laço foreach, da mesma forma que para um array:

1
2
3
4
5
6
7
8
9
10
11
// Usando um laço for
for (int i = 0; i < list.Count; i++)
{
    Console.WriteLine(list[i]); // Imprime cada elemento da lista
}

// Usando um laço foreach
foreach (string element in list)
{
    Console.WriteLine(element); // Imprime cada elemento da lista
}

Listas Ligadas

Uma lista ligada é uma coleção de elementos que são armazenados em nós, que possuem uma referência para o próximo nó da lista. Uma lista ligada permite inserir e remover elementos em qualquer posição da lista, sem precisar mover os outros elementos. Para criar uma lista ligada em C#, usamos a classe LinkedList<T>, onde T é o tipo dos elementos da lista. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Criar uma lista ligada de inteiros
LinkedList<int> linkedList = new LinkedList<int>();

// Adicionar elementos à lista ligada
linkedList.AddFirst(1); // Adiciona o elemento 1 no início da lista
linkedList.AddLast(2); // Adiciona o elemento 2 no final da lista
linkedList.AddAfter(linkedList.First, 3); // Adiciona o elemento 3 após o primeiro elemento da lista

// Remover elementos da lista ligada
linkedList.RemoveLast(); // Remove o último elemento da lista

// Acessar os elementos da lista ligada
Console.WriteLine(linkedList.First.Value); // Imprime 1
Console.WriteLine(linkedList.Last.Value); // Imprime 3
Console.WriteLine(linkedList.First.Next.Value); // Imprime 3

Para percorrer todos os elementos de uma lista ligada, podemos usar um laço foreach ou um laço while:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Usando um laço foreach
foreach (int element in linkedList)
{
    Console.WriteLine(element); // Imprime cada elemento da lista ligada
}

// Usando um laço while
LinkedListNode<int> node = linkedList.First; // Começa pelo primeiro nó da lista
while (node != null)
{
    Console.WriteLine(node.Value); // Imprime o valor do nó atual
    node = node.Next; // Avança para o próximo nó da lista
}

Hashsets

Um hashset é uma coleção de elementos que não permite elementos duplicados, e que usa uma função de hash para armazenar e recuperar os elementos de forma eficiente. Para criar um hashset em C#, usamos a classe HashSet<T>, onde T é o tipo dos elementos do hashset. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Criar um hashset de strings
HashSet<string> hashset = new HashSet<string>();

// Adicionar elementos ao hashset
hashset.Add("Bing"); // Retorna true, pois o elemento não estava no hashset
hashset.Add("Google"); // Retorna true, pois o elemento não estava no hashset
hashset.Add("Bing"); // Retorna false, pois o elemento já estava no hashset

// Remover elementos do hashset
hashset.Remove("Google"); // Retorna true, pois o elemento estava no hashset

// Verificar se um elemento está no hashset
Console.WriteLine(hashset.Contains("Bing")); // Imprime true
Console.WriteLine(hashset.Contains("Yahoo")); // Imprime false

Para percorrer todos os elementos de um hashset, podemos usar um laço foreach:

1
2
3
4
5
// Usando um laço foreach
foreach (string element in hashset)
{
    Console.WriteLine(element); // Imprime cada elemento do hashset
}

Quicksort

Quicksort é um algoritmo de ordenação que usa a estratégia de dividir e conquistar. Ele escolhe um elemento como pivô, e particiona o array em dois subarrays, um com os elementos menores ou iguais ao pivô, e outro com os elementos maiores que o pivô. Em seguida, ele aplica o mesmo processo recursivamente aos subarrays, até que o array esteja ordenado. Para implementar o quicksort em C#, podemos usar o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Método que ordena um array usando o quicksort
public static void Quicksort(int[] array, int low, int high)
{
    if (low < high)
    {
        // Encontra o índice do pivô após a partição
        int pivot = Partition(array, low, high);

        // Ordena os subarrays à esquerda e à direita do pivô
        Quicksort(array, low, pivot - 1);
        Quicksort(array, pivot + 1, high);
    }
}

// Método que particiona o array em torno de um pivô
public static int Partition(int[] array, int low, int high)
{
    // Escolhe o último elemento como pivô
    int pivot = array[high];

    // Inicializa o índice do menor elemento
    int i = low - 1;

    // Percorre os elementos do array, exceto o pivô
    for (int j = low; j < high; j++)
    {
        // Se o elemento atual é menor ou igual ao pivô
        if (array[j] <= pivot)
        {
            // Incrementa o índice do menor elemento
            i++;

            // Troca o elemento atual com o elemento no índice do menor elemento
            int temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
    }

    // Troca o pivô com o elemento no índice do menor elemento + 1
    int temp2 = array[i + 1];
    array[i + 1] = array[high];
    array[high] = temp2;

    // Retorna o índice do pivô
    return i + 1;
}

Para testar o algoritmo, podemos usar o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
// Criar um array de inteiros desordenados
int[] array = new int[] { 5, 3, 7, 2, 9, 1, 4, 6, 8 };

// Ordenar o array usando o quicksort
Quicksort(array, 0, array.Length - 1);

// Imprimir o array ordenado
foreach (int element in array)
{
    Console.WriteLine(element); // Imprime 1, 2, 3, 4, 5, 6, 7, 8, 9
}

Tabela Hash

Uma tabela hash é uma estrutura de dados que associa chaves a valores, usando uma função de hash para calcular o índice de cada chave no array interno da tabela. Uma tabela hash permite inserir, remover e buscar pares

Ok, vamos continuar com o exemplo de tabela hash em C#. Uma tabela hash é uma estrutura de dados que associa chaves a valores, usando uma função de hash para calcular o índice de cada chave no array interno da tabela. Uma tabela hash permite inserir, remover e buscar pares chave-valor de forma rápida e eficiente.

Fila

Uma fila é uma coleção de elementos que segue o princípio FIFO (first-in, first-out), ou seja, o primeiro elemento a entrar na fila é o primeiro a sair. Para criar uma fila em C#, usamos a classe Queue<T>, onde T é o tipo dos elementos da fila. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Criar uma fila de strings
Queue<string> queue = new Queue<string>();

// Adicionar elementos à fila
queue.Enqueue("Bing"); // Adiciona o elemento "Bing" no final da fila
queue.Enqueue("Google"); // Adiciona o elemento "Google" no final da fila
queue.Enqueue("Yahoo"); // Adiciona o elemento "Yahoo" no final da fila

// Remover elementos da fila
string first = queue.Dequeue(); // Remove e retorna o primeiro elemento da fila, ou seja, "Bing"
string second = queue.Dequeue(); // Remove e retorna o segundo elemento da fila, ou seja, "Google"

// Verificar o próximo elemento da fila sem remover
string next = queue.Peek(); // Retorna o próximo elemento da fila, ou seja, "Yahoo"

// Verificar se um elemento está na fila
bool contains = queue.Contains("Bing"); // Retorna false, pois o elemento "Bing" já foi removido da fila

Para percorrer todos os elementos de uma fila, podemos usar um laço foreach:

1
2
3
4
5
// Usando um laço foreach
foreach (string element in queue)
{
    Console.WriteLine(element); // Imprime cada elemento da fila
}

Pilha

Uma pilha é uma coleção de elementos que segue o princípio LIFO (last-in, first-out), ou seja, o último elemento a entrar na pilha é o primeiro a sair. Para criar uma pilha em C#, usamos a classe Stack<T>, onde T é o tipo dos elementos da pilha. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Criar uma pilha de inteiros
Stack<int> stack = new Stack<int>();

// Adicionar elementos à pilha
stack.Push(1); // Adiciona o elemento 1 no topo da pilha
stack.Push(2); // Adiciona o elemento 2 no topo da pilha
stack.Push(3); // Adiciona o elemento 3 no topo da pilha

// Remover elementos da pilha
int top = stack.Pop(); // Remove e retorna o elemento do topo da pilha, ou seja, 3
int second = stack.Pop(); // Remove e retorna o segundo elemento da pilha, ou seja, 2

// Verificar o próximo elemento da pilha sem remover
int next = stack.Peek(); // Retorna o próximo elemento da pilha, ou seja, 1

// Verificar se um elemento está na pilha
bool contains = stack.Contains(3); // Retorna false, pois o elemento 3 já foi removido da pilha

Para percorrer todos os elementos de uma pilha, podemos usar um laço foreach:

1
2
3
4
5
// Usando um laço foreach
foreach (int element in stack)
{
    Console.WriteLine(element); // Imprime cada elemento da pilha
}

Árvore

Uma árvore é uma estrutura de dados hierárquica que consiste em um nó raiz e vários nós filhos, que por sua vez podem ter seus próprios nós filhos. Cada nó pode armazenar um valor e uma referência para seus nós filhos. Uma árvore binária é um tipo especial de árvore em que cada nó pode ter no máximo dois filhos, chamados de filho esquerdo e filho direito. Para criar uma árvore binária em C#, podemos usar uma classe personalizada que representa um nó da árvore. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Classe que representa um nó de uma árvore binária
class TreeNode
{
    // Valor do nó
    public int Value { get; set; }

    // Referência para o filho esquerdo do nó
    public TreeNode Left { get; set; }

    // Referência para o filho direito do nó
    public TreeNode Right { get; set; }

    // Construtor que recebe o valor do nó
    public TreeNode(int value)
    {
        Value = value;
        Left = null;
        Right = null;
    }
}

Para criar uma árvore binária, podemos instanciar objetos da classe TreeNode e atribuir as referências dos filhos. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Criar uma árvore binária com os valores 1, 2, 3, 4, 5, 6, 7
// A estrutura da árvore é a seguinte:
//       1
//      / \
//     2   3
//    / \ / \
//   4  5 6  7

// Criar o nó raiz com o valor 1
TreeNode root = new TreeNode(1);

// Criar os nós filhos do nó raiz com os valores 2 e 3
root.Left = new TreeNode(2);
root.Right = new TreeNode(3);

// Criar os nós filhos do nó esquerdo do nó raiz com os valores 4 e 5
root.Left.Left = new TreeNode(4);
root.Left.Right = new TreeNode(5);

// Criar os nós filhos do nó direito do nó raiz com os valores 6 e 7
root.Right.Left = new TreeNode(6);
root.Right.Right = new TreeNode(7);

Para percorrer todos os elementos de uma árvore binária, podemos usar diferentes métodos de travessia, como pré-ordem, em-ordem e pós-ordem. Esses métodos usam a recursão para visitar os nós da árvore em uma determinada ordem. Por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Método que percorre uma árvore binária em pré-ordem
// A ordem de visita é: raiz, esquerda, direita
public static void PreOrder(TreeNode node)
{
    // Se o nó é nulo, retorna
    if (node == null)
    {
        return;
    }

    // Imprime o valor do nó
    Console.WriteLine(node.Value);

    // Percorre o filho esquerdo do nó
    PreOrder(node.Left);

    // Percorre o filho direito do nó
    PreOrder(node.Right);
}

// Método que percorre uma árvore binária em ordem
// A ordem de visita é: esquerda, raiz, direita
public static void InOrder(TreeNode node)
{
    // Se o nó é nulo, retorna
    if (node == null)
    {
        return;
    }

    // Percorre o filho esquerdo do nó
    InOrder(node.Left);

    // Imprime o valor do nó
    Console.WriteLine(node.Value);

    // Percorre o filho direito do nó
    InOrder(node.Right);
}

// Método que percorre uma árvore binária em pós-ordem
// A ordem de visita é: esquerda, direita, raiz
public static void PostOrder(TreeNode node)
{
    // Se o nó é nulo, retorna
    if (node == null)
    {
        return;
    }

    // Percorre o filho esquerdo do nó
    PostOrder(node.Left);

    // Percorre o filho direito do nó
    PostOrder(node.Right);

    // Imprime o valor do nó
    Console.WriteLine(node.Value);
}

Para testar os métodos de travessia, podemos usar o seguinte código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Criar uma árvore binária com os valores 1, 2, 3, 4, 5, 6, 7
// A estrutura da árvore é a seguinte:
//       1
//      / \
//     2   3
//    / \ / \
//   4  5 6  7

// Criar o nó raiz com o valor 1
TreeNode root = new TreeNode(1);

// Criar os nós filhos do nó raiz com os valores 2 e 3
root.Left = new TreeNode(2);
root.Right = new TreeNode(3);

// Criar os nós filhos do nó esquerdo do nó raiz com os valores 4 e 5
root.Left.Left = new TreeNode(4);
root.Left.Right = new TreeNode(5);

// Criar os nós filhos do nó direito do nó raiz com os valores 6 e 7
root.Right.Left = new TreeNode(6);
root.Right.Right = new TreeNode(7);

// Percorrer a árvore em pré-ordem
Console.WriteLine("Pre-order traversal:");
PreOrder(root);

// Percorrer a árvore em ordem
Console.WriteLine("In-order traversal:");
InOrder(root);

em construção

Esta postagem está licenciada sob CC BY 4.0 pelo autor.

Deploy ASP .NET no Linux [WSL]

-