Algoritmos e estruturas de dados em C#: na prática
\n\nCompreender algoritmos e estruturas de dados é uma habilidade fundamental para qualquer desenvolvedor. Independentemente de você estar escrevendo um serviço de alta carga, um aplicativo desktop ou um jogo, o gerenciamento eficiente de dados impacta diretamente o desempenho e a escalabilidade do seu código. Neste artigo, vamos explorar as principais estruturas de dados e algoritmos na linguagem C# (.NET) com exemplos práticos que você pode aplicar imediatamente em seus projetos.
\n\n1. Arrays dinâmicos e trabalho com List<T>
\n\nEm C#, o array dinâmico básico é a classe List<T>. Diferentemente do array clássico, ele se expande automaticamente ao adicionar elementos. Vamos analisar suas operações principais e uma das mais importantes — a busca binária.
Busca Binária (Binary Search) funciona apenas em dados ordenados. Sua complexidade é O(log n). O algoritmo divide o intervalo de busca pela metade a cada etapa.
\n\nusing System;\nusing System.Collections.Generic;\n\npublic class BinarySearchExample\n{\n public static int BinarySearch(List<int> sortedList, int target)\n {\n int left = 0;\n int right = sortedList.Count - 1;\n\n while (left <= right)\n {\n int mid = left + (right - left) / 2;\n\n if (sortedList[mid] == target)\n return mid; // Elemento encontrado, retorna o índice\n else if (sortedList[mid] < target)\n left = mid + 1; // Busca na metade direita\n else\n right = mid - 1; // Busca na metade esquerda\n }\n return -1; // Elemento não encontrado\n }\n\n public static void Main()\n {\n var numbers = new List<int> { 2, 5, 8, 12, 16, 23, 38, 45, 56, 67 };\n int target = 23;\n int result = BinarySearch(numbers, target);\n Console.WriteLine(result != -1 ? $"Elemento {target} encontrado no índice {result}" : "Elemento não encontrado");\n }\n}\n\nPor que isso é importante? List<T> é usado em 90% dos projetos. Saber pesquisar rapidamente dados nele é a chave para o desempenho.
\n\n2. Pilha e Fila: LIFO e FIFO na prática
\n\nPilha (Stack) e fila (Queue) são coleções com uma ordem de acesso bem definida. Elas são indispensáveis no processamento de chamadas, análise sintática e trabalho com tarefas.
\n\nPilha (LIFO — Last In, First Out)
\nÉ usada, por exemplo, para verificar a validade de parênteses no código.
\n\nusing System;\nusing System.Collections.Generic;\n\npublic class StackExample\n{\n public static bool IsValidBrackets(string input)\n {\n Stack<char> stack = new Stack<char>();\n foreach (char ch in input)\n {\n if (ch == '(' || ch == '{' || ch == '[')\n {\n stack.Push(ch);\n }\n else if (ch == ')' || ch == '}' || ch == ']')\n {\n if (stack.Count == 0) return false;\n\n char top = stack.Pop();\n if ((ch == ')' && top != '(') ||\n (ch == '}' && top != '{') ||\n (ch == ']' && top != '['))\n {\n return false;\n }\n }\n }\n return stack.Count == 0;\n }\n\n public static void Main()\n {\n string test1 = "({[]})";\n string test2 = "({[})";\n Console.WriteLine($"'{test1}' — parênteses válidos: {IsValidBrackets(test1)}");\n Console.WriteLine($"'{test2}' — parênteses válidos: {IsValidBrackets(test2)}");\n }\n}\n\nFila (FIFO — First In, First Out)
\nIdeal para processar tarefas na ordem em que chegam (por exemplo, fila de impressão).
\n\nusing System;\nusing System.Collections.Generic;\n\npublic class QueueExample\n{\n public static void Main()\n {\n