Introdução aos vetores e listas
[ Vetores | Vetores em C | Vetores em Python ]
Nesta seção examinaremos resumidamente como utilizar vetores tanto em C quanto em Python, mas iniciamos com a questão essencial: por que usar vetor (ou lista, outro possível nome, apesar desse segundo poder implicar em operadores especiais).
Por que precisamos de vetores?
Pense em um problema simples, muito comum, que é extrair informações sobre o comportamento médio de um "conjunto" de dados,
mas apenas a média pode ser pouco informativo (e.g., metade tem valor 10 e a outra metade 0).
Assim, estamos interessados em um software que compute a média e o desvio padrão de um "conunto" de dados.
Lembrando a definição de desvio padrão (DP):
s:=0; |
repetir para i entre 0 e n { ler(x); s:=s+x; } |
Usualmente um vetor é um agregado de dados de um mesmo tipo básico ocupando posições consecutivas de memória. Isso significa que é possível pegar alternadamente o valor armazenado em qualquer das posições do vetor, Usualmente isso é implementado nas linguagens por uma indexamentos, ou seja, sendo vet o nome da variável agregada, pode-se pegar o primeiro elemento fazendo vet[0], o segundo com vet[1] e assim por diante.
Na figura acima representamos a memória do computador com um vetor (agregado) de variáveis (usando 8 bits apenas) e de tamanho 4, ou seja, um vetor para armazenar 4 valores do tipo dado.
Como citado na explicação sobre funções, uma grande vantagem de ter um algoritmo implementado como uma função separada é que o código do programa fica mais organizado e pode-se invocar esse algoritmo (a partir da função) em qualquer outro trecho do programa. Por isso, alguns funções muito úteis são implementadas pelos desenvolvedores para ficarem disponíveis dentro dos ambientes de programação.
Retomando o exemplo do cálculo da média aritmética e do desvio padrão de n valores, poderíamos implementar a função calcula_media e a função calcula_dp, como abaixo.
inteiro calcula_media (vetor, n) {//# declara funcao que devolve 'inteiro' s := 0;//# atencao, dependendo da linguagem, e' melhor declarar ser to tipo "real" repetir para i entre 0 e n { s := s+vetor[i]; } devolve s/n;//# a media - atencao, dependendo da linguagem precisa de alguma forma forcar tratar-se de "reais" }real calcula_dp (vetor, med, n) {//# declara funcao que devolve 'real' s := 0; repetir para i entre 0 e n { aux := med-vetor[i];//# pequeno truque para melhorar desempenho do algoritmo... s := s + aux*aux;//# nao precisa computar 2 vezes med-vetor[i] } devolve raiz_quadrada(s);//# raiz_quadrada(s) devolve s1/2 }
Por exemplo, tanto em C quanto em Python existem implementações para funções matemáticas úteis, como seno, cosseno ou raíz quadrada (respectivamente, sin, cos e sqrt). Mas é preciso indicar ao ambiente que ele deve carregar essas funções, isso é feito com os comandos #include <math.h> em C e import "math".
Vetores em CComo em C deve-se sempre declarar o tipo da variável, no caso de vetor deve-se declarar seu tipo e seu tamanho. No exemplo abaixo ilustramos declaração e uso de vetores dos tipos básicos int, char e float.
Vetores em C | |||
---|---|---|---|
Vetor de inteiros | Vetor de caracteres | Vetor de flutuantes | |
|
#include <stdio.h> #define M 20 |
#include <stdio.h> #define M 20 |
Como já examinado, em C geralmente deve-se carregar a biblioteca stdio mas existem outras, como a stdlib.h que dispõe, entre outras, da função qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*)) que implementa o método ordenador eficiente denominado Quick Sort (ou Ordenador Rápido). Veja um exemplo de código usando o qsort:
#include <stdio.h>// para funcao 'printf' #include <stdlib.h>// para a funcao 'qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))' int vetor[] = { 3, 9, 1, 7, 0, 4, 6, 5, 2, 8 };// por simplicidade usar globais e manter fixo int N = 10; void imprime (int vet[],int n) {// funcao para imprimir em mesma linha int i;for (i=0; i<n; i++) printf(" %d", vet[i]); printf("\n"); }// Esta e' a funcao comparadora: pode-se comparar qualquer coisa, basta codificar seu comparador int comparador (const void *a, const void *b) {// precisa de 2 parametros a serem depois comparados return ( *(int*)a - *(int*)b ); }int main (void) { printf("Testar 'qsort' da biblioteca 'stdlib'\n"); printf("Antes: "); imprime(vetor, N); printf("Inicio: invocar 'qsort' da biblioteca 'stdlib'\n");// Parametros para 'qsort': vetor de dados, numero de elementos no vetor, tamanho em bytes de cada elemento, endereco da funcao comparadora qsort(vetor, N, sizeof(int), &comparador); printf("Ordenado: "); imprime(vetor, N); return 0; }
Atenção. No C padrão NÃO é possível declarar o vetor usando a variável que será usada para informar o número efetivo de posições a serem usadas, ou seja, não tente fazer algo como int n; float vetF[n];. A razão disso é que C é uma linguagem compilada e ao compilar deve-se reservar o espaço máximo a ser usado pelo vetor. Já a variável n só será conhecida durante a execução do programa.
Apesar de algumas implementações de compiladores C permitirem, NÃO usem sob pena de seu programa não funcionar em outros compiladores.
Vetores/listas em Python
Geralmente, na literatura de programação, o termo vetor refere-se a um agregado de dados,
de mesmo tipo e em posições consecutivas de memória. Como em Python, pode-se misturar tipos, então usa-se o
termo lista (ou tuple).
Por exemplo, pode-se declarar
lista = (1, 2, "tres", "VI"); ou tupla = [1, 2, "tres", "VI"];
e alterar ou imprimir um elemento, como em:
lista[3] = 3; tupla[3] = 3;
Como citado na explicação sobre funções, uma grande vantagem de ter um algoritmo genericamente implementado como uma função separada é que o código do programa fica mais organizado e pode-se invocar a função em qualquer outro trecho do programa. Por isso, alguns funções muito úteis acabam sendo implementadas pelos desenvolvedores nos ambientes de programação.
Por exemplo, em Python existe a função sorted(.) que ordena listas (e tuplas), mas também existe um método sobre lista (não sobre tupla) que também ordena lista:
lista = ["tres", "quatro", "um", "dois"];# ['dois', 'quatro', 'tres', 'um'] lista.sort();# nao tente imprimir direto "lista.sort()" senao aparece "None" # ['dois', 'quatro', 'tres', 'um']
Outra observação importante, o método sort() não está definido para tuplas,
ou seja, os comandos
lista = ("tres", "quatro", "um", "dois"); lista.sort();
No exemplo abaixo ilustramos a declaração e uso de listas dos tipos básicos int, char e float. Nesses exemplos utilizamos uma técnica de pré-alocar todo o espaço para a lista, utilizando um valor máximo para o número de posições a serem utilizadas (o M = 20;). Depois solicitamos que o usuário digite o número de elementos que ele deseja inserir na lista (não fazemos um teste, mas nessa técnica esse valor tem que ser menor que M), então utilizamos um laço para solicitar a "entrada" de cada elemento, inserindo-o na posição adequada da lista.
Listas em Python com alocação inicial de todo o espaço à priori | ||
---|---|---|
Vetor de caracteres | Vetor de inteiros | Vetor de flutuantes |
M = 20 |
M = 20 |
M = 20 |
Vale notar que, como em Python o espaço para o vetor é reservado durante a execução, não é necessário
pré-dimensionar o espaço para o "vetor" como nos 3 códigos acima, e pode-se usar como linhas 3 e 4:
nI =
Por fim, vale destacar um detalhe a respeito de como "digitar" os dados usando o comando input. No Python 2, Nos códigos acima, se o usuário digitar SyntaxError: invalid syntax.
Podemos adotar outra técnica para registro dos dados na lista, desta vez não usando alocação a priori de espaço e sim estendendo a lista a cada novo elemento digitado. Mas ainda usando a técnica que obriga o usuário a digitar um único valor por vez (que dizer, digitar um inteiro e teclar ENTER). Esse exemplo está à esquerda da tabela abaixo.
Na coluna da direita da tabela mostramos um exemplo distinto, no qual não é necessário digitar a priori o número de inteiros que comporão a lista. O usuário deverá digitar todos os dados em uma mesma linha, com um único ENTER ao final, e o código decompõe a "string" digitada, utilizando como separadores espaço em branco para deduzir quais são os inteiros.
Listas em Python com alocação dinâmica de espaço e tipos de digitação | ||
---|---|---|
Digitando um elemento por vez | Digitando todos os elementos de uma vez | |
|
|
Leônidas de Oliveira Brandão
http://line.ime.usp.br
Alterações:
2020/08/20: acertos no formato
2020/08/11: acerto formato, pequenos acertos no texto
2020/05/05: acrescentada subseção Por que precisamos de vetores?
2019/06/11: detalhes de forma;
2019/06/04: revisão geral.