Guia de referência e estudo das estruturas de dados no C#
Ter um guia das estruturas de dados no C# ajuda desenvolvedores a desenvolver melhores códigos. Após uma leitura do livro C# Data Structures and Algorithms, percebi uma grande oportunidade de estudo sobre o tema. Sem dúvidas, hoje, entender de forma profunda estrutura de dados e algoritmos é uma oportunidade para se diferenciar no mercado.
Quais são as estruturas de dados no C#?
No C# podemos encontrar diversas estruturas de dados. Algumas delas, como a lista genérica, List<T> é a mais conhecida e mais utilizada entre os programadores, mas as estruturas de dados no C# vão além da List<T>.
Desenvolvedores precisam ir além do uso listas genéricas, como List<T>
Sempre entendi que nós desenvolvedores, precisamos ir além do uso de listas genéricas, por exemplo List<T>. Frequentemente, em nossos código percebemos uma utilização demasiada.
Uma boa oportunidade para aprender como o List<T> funciona, sugiro a leitura desse post Utilize List<T> com capacity e tenha performance no .NET. Nesse post, falo como garantir a performance de uma aplicação .NET utilizando o List<T> do jeito certo.
Maslow diz que “Para quem só tem o martelo todo problema será um prego”, na prática, quem só conhece o List<T> não irá utilizar nada além do List<T>.
Definindo estrutura de dados
Estrutura de dados, segundo Marcello La Rocca, pode ser definida como – “uma solução específica para organizar coleções tanto de valores quanto de operações“, também como, “uma implementação concreta de um tipo abstrato ou um tipo de dados básico ou primitivo“.
Há uma diferença entre vetor e matriz, entenda
Vetor e matriz, embora sejam coleções que são acessadas por um índice, elas possuem diferenças em sua estrutura. Enquanto o vetor é considerado unidimensional, ou seja, de única dimensão, a matriz é multidimensional, que pode ter várias dimensões. Mesmo com essa diferença elas podem ser utilizadas com tipos de dados primitivos e também objetos.
Arrays
Arrays são utilizados para armazenar dados de diversos tipos, entretanto, sempre da mesma definição. Assim sendo, se a declaração for do tipo int
, todo seu array será do tipo int
. Também podem ser tratadas como unidimensionais, multidimensionais e denteadas.
Vetor, array unidimensional
Um array unidimensional armazena uma coleção de itens do mesmo tipo, que são acessíveis por um índice.
1 |
int[] números = new int[5]; |
Matriz, array multidimensional
Um array multidimensional armazena possibilita criar arrays bidimensionais ou tridimensionais.
1 |
int[,] números = new int[5, 2]; |
Conhecendo as estruturas de dados no C#
List<T>
A List<T> é amplamente utilizada entre programadores C# devido à sua implementação simples e à sua abrangência. Embora seja muito útil e geralmente eficaz, é importante que sejam tomados alguns cuidados na sua aplicação.
Cuidados que os programadores devem ter ao utilizar List<T>.
Inserir ou remover itens na lista pode ser extremamente custoso
Quando você precisa inserir ou remover um item no meio da lista, todos os itens subsequentes precisam ser deslocados para frente ou para trás, o que pode ser uma operação cara em termos de desempenho.
Não definir a no C# com capacidade inicial e tenha performance no .NET capacidade inicial pode trazer problemas de performance
Naturalmente listas genéricas são redimensionáveis quando o limite de sua capacidade é atingido. Ao iniciar uma lista sem capacidade inicial – lembrando que por de trás das listas genéricas temos um array – será criado um array com quatro posições. Na medida que a lista cresce e a capacidade de armazenamento se esgota, um novo array é criado com o dobro da capacidade do array inicial. Por isso é importante, sempre que possível, determinar a capacidade inicial da lista.
A importância de definir a capacidade inicial de uma lista genérica.
Ao estabelecer a capacidade inicial de sua lista, você evita o ajuste de seu tamanho ao inserir novos elementos. O uso desta capacidade aumenta a eficiência da sua aplicação, pois o processo de redimensionamento gera custos relevantes.
O que está por trás da lista é um array. Array não são passíveis de redimensionamento. Dessa forma, quando uma lista é aumentada, um novo array será criado com uma capacidade maior, os dados serão copiados do array antigo para o novo e a lista antiga será descartada pelo Garbage Collector.
Como criar uma lista genérica com capacidade inicial?
Como falamos, listas genéricas são altamente utilizadas entre os programadores C# pela sua facilidade de implementação. Para criação de uma lista com capacidade inicial não é diferente, para isso, ao instanciar uma lista você deve informar a capacidade.
1 |
var customers = new List<Customer>(10); |
Qual exemplo prático de utilização de listas com capacidade inicial?
São diversos exemplos que podemos utilizar listas com capacidade inicial, entretanto a mais assertiva é o processo de paginação. Ao trabalharmos com processo de paginação é mandatório saber quantos itens terá em uma página, por esse motivo, é a escolha mais assertiva.
SortedList
A SortedList, por definição, é uma coleção de pares de chave e valor que são ordenados pela chave. Esta estrutura de dados fornece um alto nível de controle sobre os dados que estão sendo armazenados, já que as chaves são únicas e a ordem é garantida. A capacidade de acessar dados por uma chave ou um índice torna a SortedList uma ferramenta extremamente útil para desenvolvedores.
1 2 3 4 5 6 7 8 9 10 11 |
SortedList mySL = new SortedList(); mySL.Add("Terceiro", "!"); mySL.Add("Segundo", "Mundo"); mySL.Add("Primeiro", "Olá"); // Remover um elemento por chave mySL.Remove("Terceiro"); // Limpar a lista mySL.Clear(); |
O poder da SortedList realmente brilha quando começamos a acessar e manipular seus elementos. Graças à interface IEnumerable, podemos percorrer a lista usando um loop foreach. Além disso, a SortedList nos permite acessar um valor ou chave por um índice específico, uma característica única que diferencia a SortedList de outras coleções.
1 2 3 4 5 6 7 8 9 10 11 12 |
SortedList mySL = new SortedList(); mySL.Add("Terceiro", "!"); mySL.Add("Segundo", "Mundo"); mySL.Add("Primeiro", "Olá"); foreach (DictionaryEntry de in mySL) { Console.WriteLine($"Chave: {de.Key}, Valor: {de.Value}"); } Console.WriteLine($"Chave: {mySL.GetKey(0)}, Valor: {mySL.GetByIndex(0)}"); |
O SortedList oferece uma combinação única de características de arrays e dicionários e fornece uma série de métodos úteis para a manipulação eficiente dos dados. Este artigo esperançosamente desmistificou a SortedList e demonstrou a eficiência e flexibilidade que ela pode trazer para o seu programa. Independentemente do tamanho ou da complexidade de seu programa, há sempre espaço para melhorar e otimizar – e a SortedList pode ser o componente chave para essa otimização.