Olá, caro(a) aluno(a), até aqui, estudamos diferentes conceitos básicos de algoritmos, como: variáveis, estruturas condicionais, laços de repetição etc. Nesta lição, vamos iniciar alguns conceitos avançados no processo de construção de algoritmos, que são as estruturas de dados.
As estruturas de dados são essenciais para a construção de algoritmos complexos e manipulação de dados. A primeira estrutura que vamos estudar são os vetores, que consistem em uma estrutura de dados homogênea que permite a representação de diversas informações do mesmo tipo.
No decorrer do nosso curso, aprendemos a utilizar variáveis para guardar os nossos dados. Porém, como você sabe, variáveis armazenam apenas um valor por vez; por isso, quando precisamos armazenar um novo valor, substituímos o valor atual da variável ou criamos outra.
Estruturas de dados homogêneas permitem armazenar mais de um valor em uma mesma variável, essas estruturas podem ser divididas em duas categorias: unidimensional, que chamaremos de vetores, e multidimensionais, que chamaremos de matrizes (LOPES; GARCIA, 2002). Ambas as estruturas trabalham de forma semelhante, porém vamos conhecer uma de cada vez.
Na programação, normalmente, vamos desenvolver algoritmos que utilizam listas de dados; para representar os itens dessas listas, podemos utilizar variáveis, porém isso fará com que o algoritmo fique “sobrecarregado” de variáveis. Neste contexto, o seu maior aliado são os vetores que permitem que, com apenas uma variável, você armazene diversos valores, por exemplo, imagine que precisamos criar um algoritmo que recebe uma lista de compras; neste caso, criamos um vetor em que, em cada posição, ele guarda um item da lista.
Vamos descobrir como podemos programar isso?
Antes de você conhecer como funcionam as estruturas de dados, é importante relembrar um pouco sobre arquitetura de computadores e a organização de dados na memória. Em nosso computador, temos a memória RAM que armazena temporariamente os dados do nosso sistema e aplicações que estão sendo executadas. A memória RAM pode ser imaginada como uma estante, onde em cada bloco contém um dado armazenado e existe um endereço de identificação.
Quando uma variável é declarada em um algoritmo, o processador solicita um espaço na memória que será reservado para armazenar os dados referentes à variável declarada, sendo que esse espaço é representado por um endereço que indica o local onde o dado está armazenado e, consequentemente, onde ele deve ser procurado, quando necessário.
Quando trabalhamos com estruturas de dados, armazenamos diversos dados em uma mesma variável, porém, em cada espaço da memória, é possível alocar apenas um dado. Desse modo, quando declaramos uma estrutura, por exemplo, um vetor, estamos alocando diversos blocos da memória de forma sequencial que serão conhecidos pelo mesmo nome, porém com endereços diferentes. Esses endereços normalmente são sequenciais, de forma que, na memória, todos os blocos referentes ao vetor estão armazenados um ao lado do outro.
Conforme define Ascencio e Campos (2008), vetor é uma estrutura de dados primitiva e base para outras estruturas, como matrizes, listas, cadeias etc. Um vetor é uma estrutura homogênea, isto é, uma estrutura de dados do mesmo tipo, que podem ser identificados por um identificador único. Você pode imaginar um vetor como um trem, onde cada um dos vagões do trem são elementos do vetor, e cada item (vagão) da estrutura é identificado pela sua posição. Observe a Figura 1, ela representa um vetor de números do tipo inteiro, este vetor tem 5 posições, isso é, ele pode armazenar 5 números diferentes, cada um em uma posição. Essas posições são identificadas por um índice, que é o número representado em baixo de cada bloco.
Figura 1 - Representação gráfica de vetores / Fonte: o autor.
#PraCegoVer: a imagem ilustra um trem que representa um vetor de dados. Da esquerda para a direita, a imagem apresenta uma locomotiva puxando 5 vagões, onde cada vagão representa uma posição do vetor. O primeiro vagão representa a posição 1 do vetor que armazena o valor 5. O segundo vagão representa a posição 2 do vetor que armazena o valor 7. O terceiro vagão representa a posição 3 que armazena o valor 3. O quarto vagão representa a posição 4 que armazena o valor 1. Por fim, o quinto vagão representa a posição 5 que armazena o valor 2.
Agora que você sabe o que é um vetor, vamos analisar a sintaxe de declaração:
SINTAXE:
<Nome> [<Dimensão>] : <Tipo>
Em que:
<nome> representa o nome da variável.
<dimensão> representa o tamanho do valor.
<tipo> tipo dos dados.
Vamos analisar como seria a declaração do vetor apresentado na Figura 1, que consiste em um vetor de 5 posições de elementos do tipo inteiro.
trem[1..5] : inteiro.
Observe, neste caso, o nosso vetor foi denominado como trem, dentro dos colchetes declaramos a dimensão do vetor, neste caso [1 ... 5], onde 1 indica o início do vetor e 5 o fim. Por fim, após os “:” declaramos o tipo deste vetor que é de inteiros.
Para realizar a gravação e leitura de dados em um vetor, é necessário informar o nome do vetor seguido pela posição na qual a operação será realizada; por exemplo, para gravar um dado em uma posição de um vetor, utilizamos a seguinte sintaxe:
trem[1] <- 9
Nesta linha, estamos declarando que queremos armazenar o valor 9 na posição 1 do vetor trem. A Figura 2 apresenta de forma gráfica a operação exemplificada.
Figura 2 - Representação vetor trem / Fonte: o autor.
#PraCegoVer: a imagem ilustra um trem que representa um vetor de dados denominado trem com 5 posições. Da esquerda para a direita, a imagem apresenta uma locomotiva puxando 5 vagões, em que cada vagão representa uma posição do vetor. O primeiro vagão representa a posição 1 do vetor que armazena o valor 9 que foi atribuído no exemplo apresentado. O segundo vagão representa a posição 2 do vetor que está vazia. O terceiro vagão representa a posição 3 que está vazia. O quarto vagão representa a posição 4 que está vazia. Por fim, o quinto vagão representa a posição 5 que está vazia.
Para a leitura de um dado de uma posição do vetor, utilizamos a mesma ideia da gravação por exemplo:
ESCREVA(trem[1])
Neste exemplo, estamos indicando para o algoritmo que ele deve escrever na tela o valor que está armazenado na posição 1 do vetor.
Como sabemos, utilizamos vetores quando desejamos armazenar diversos valores do mesmo tipo de dados. Vamos imaginar que fomos contratados para desenvolver um aplicativo de cardápio eletrônico de uma sorveteria. O aplicativo, simplesmente, apresenta na tela os sabores de sorvetes que temos disponíveis. Considere que, na sorveteria, vende os seguintes sabores de sorvete: chocolate, morango, baunilha e napolitano. Utilizando vetores, podemos escrever o algoritmo da seguinte forma:
VARIAVEIS
sabores[1..4] : caractere
INICIO
sabores[1] <- chocolate
sabores[2] <- morango
sabores[3] <- baunilha
sabores[4] <- napolitano
PARA inteiro i DE 1 ATÉ 4 PASSO 1 FAÇA
ESCREVA(sabores[i])
FIM_PARA
FIM
Vamos analisar linha a linha:
Linha 1: abertura do bloco de variáveis.
Linha 2: declaração do vetor sabores com 4 posições do tipo caractere.
Linha 3: início do algoritmo.
Linhas 4 a 7: atribuição dos sabores de sorvetes nas posições do vetor, isto é, em cada posição está armazenado o nome de um sabor.
Linha 8: início do laço de repetição PARA. Vamos utilizar o laço de repetição para correr todas as posições do vetor e escrever na tela os sabores. Inicialmente, declaramos a variável de controle i, e então definimos o início e o fim do laço, no caso de 1 até 4, pois o vetor tem 4 posições. Definimos, também, o passo como 1, visto que desejamos percorrer todas as posições do vetor de sabores.
Linha 9: comando escreva para imprimir os sabores na tela. Dentro do índice de sabores, indicamos a posição i, isso porque, a cada iteração do laço, queremos que imprima o valor que está armazenado na posição que o contador i representa.
Linha 10: fim do laço para.
Linha 11: fim do algoritmo.
Importante, os vetores devem ter um tamanho fixo, que é indicado na declaração. Este tamanho não pode ser alterado no decorrer do algoritmo ou durante a execução.
Utilizar vetores apresenta diversas vantagens. Essa estrutura de dados permite reduzir, de forma significativa, o número de variáveis necessárias em um código, portanto, aumenta a legibilidade do código. Outra vantagem é que os elementos dos vetores são acessados por meio da sua posição (índice), e os dados são armazenados na memória de forma sequencial. Portanto, em questão de desempenho, o tempo que leva para ler os valores armazenados em um vetor é sempre o mesmo, independentemente do tamanho.
Apesar das vantagens, você deve se atentar a alguns pontos: os vetores armazenam, apenas, dados do mesmo tipo. Sendo assim, você não pode utilizar o mesmo vetor para armazenar alguns dados do tipo inteiro e outros do tipo caractere. Também, é importante sempre prestar atenção em criar um vetor do tamanho exato que será necessário, visto que declarar um vetor muito grande pode desperdiçar memória.
ASCENCIO, F.; CAMPOS, E. Fundamentos da programação de computadores. São Paulo: Pearson Education, 2008.
LOPES, A.; GARCIA, G. Introdução à programação. Rio de Janeiro: Elsevier, 2002.