Você está na página 1de 41

Arrays

IPC2
1999/2000
F. Nunes Ferreira

Acetatos baseados no livro


C: How to Program (second edition)
H. M. Deitel
P. J. Deitel
Prentice Hall, 1994
2

Arrays
Introdução

u Array é uma estrutura de dados, todos do mesmo tipo.


Vectores (1D) e Matrizes (2D, 3D, ...) são exemplos
de arrays

u Estrutura/Struct é uma estrutura de dados, os quais


podem ser de tipos diferentes

u Ambos os casos são estruturas que, enquanto existem,


mantêm o mesmo tamanho.

u Mais tarde, também serão consideradas estruras


dinâmicas (listas, filas de espera, pilhas e
árvores)
3

Arrays
Um exemplo

u Um array de 6 elementos

c[0] 6 - O primeiro elemento é c[0] ...


c[1] 742
c[2] -15 - c[4 + 1] += 2; faz c[5] = 20
c[3] 0
c[4] 32
c[5] 18

u Declaração

int c[6];
4

Arrays
Declarações

u Declaração com inicialização

int c[6] = {6, 742, -15, 0, 32, 18};

int n[30] = {9, 45}; /* os 2 primeiros elementos


de n[] são inicializados com 9
e 45,
e os restantes 28 com 0 */

int m[] = {6, 742, -15}; /* cria e inicializa um


array com 3 elementos */
5

Arrays
Um exemplo

u Os elementos de um array são inicializados com


c[j] = 10 + 5 * j;
#include <stdio.h>
#define SIZE 10
int main(void)
{ Indice Valor
int c[SIZE], j; 0 10
1 15
for (j = 0; j <= SIZE - 1; j++) 2 20
c[j] = 10 + 5 * j; 3 25
4 30
printf("%s%10s\n", "Indice", "Valor");
5 35
for (j = 0; j <= SIZE - 1; j++) 6 40
printf("%6d%10d\n", j, c[j]); 7 45
8 50
return 0; 9 55
}
u Numa turma de 40 alunos, foi feito um inquérito à qualidade
da comida de uma cantina: 1- má; ... 10- excelente. As
respostas ao inquérito são colocadas num array de 40
elementos e um programa sumariza o resultado numa tabela de
10 entradas
Nivel Votacao
#include <stdio.h> 1 1
#define N_ALUNOS 40 2 2
#define NIVEIS 11 3 4
int main(void) 4 5
{
int resposta, nivel; 5 11
int respostas[N_ALUNOS] = {5, 6, 4, 8, 6 6
4, 10, 8, 4, 5, 4, 5, 2, 5, 1, 5, 7 5
7, 3, 5, 9, 5, 7, 6, 6, 5, 5, 3, 8 3
6, 7, 6, 8, 2, 5, 7, 6, 4, 3, 9, 9 2
5, 3, 7}; 10 1
int frequencia[NIVEIS] = {0};
for (resposta = 0; resposta <= N_ALUNOS - 1; resposta++)
++frequencia[respostas[resposta]];
printf("%s%10s\n", "Nivel", "Votacao");
for (nivel = 1; nivel <= NIVEIS - 1; nivel++)
printf("%5d%10d\n", nivel, frequencia[nivel]);
return 0;
}
7

Arrays
Algumas considerações

u Definir o tamanho dos arrays com constantes simbólicas


torna os programas mais portáveis

u Utilizar letras maiúsculas para as constantes


simbólicas lembra os programadores que estas
constantes não variáveis

u Garantir que nenhuma referência a um array se fará


para além dos seus limites
8

Arrays
Cadeia de caracteres (string)

u Uma cadeia de caracteres (string) é um array de


caracteres

u char experienc1[] = "um";


cria e inicializa um array de comprimento 3, com os
caracteres 'u' 'm' e '\0'.
É equivalente a char experienc1[] = {'u', 'm', '\0'};

u Quando se preenche um array de caracteres a partir do


teclado, é necessário prever espaço no array até ao
primeiro caracter whitespace (ver exemplo seguinte)
u Inicialização de cadeias de caracteres através de
uma constante literal e do teclado

#include <stdio.h>
int main(void)
{
char cadeia1[20], cadeia2[] = "constante literal";
int i;
printf("Indicar uma cadeia: ");
& não é
scanf("%s", cadeia1); necessário
printf("cadeia1 e': %s\ncadeia2 e': %s\n",
cadeia1, cadeia2);

for (i = 0; cadeia1[i] != '\0'; i++)


printf("%c ", cadeia1[i]);
printf("\n"); Indicar uma cadeia: uma cadeia
cadeia1 e': uma
return 0; cadeia2 e': constante literal
} u m a
u Arrays estáticos e dinâmicos
#include <stdio.h>
void iniEstatica(void);
void iniDinamica(void);
int main(void)
{
printf("Primeira chamada:\n");
iniEstatica();
iniDinamica();
printf("\n\nSegunda chamada:\n");
iniEstatica();
iniDinamica(); Primeira chamada:
return 0; a[0] = 8 a[1] = 7 a[2] = 6
} b[0] = 8 b[1] = 7 b[2] = 6
Segunda chamada:
void iniEstatica(void)
{ a[0] = 13 a[1] = 12 a[2] = 11
static int a[] = {3, 2, 1}; b[0] = 8 b[1] = 7 b[2] = 6
for (i = 0; i <= 2; i++)
printf("a[%d] = %d ", i, a[i] += 5);
}
void iniDinamica(void)
{
int b[] = {3, 2, 1};
for (i = 0; i <= 2; i++)
printf("b[%d] = %d ", i, b[i] += 5);
}
11

Arrays
Arrays como argumentos de funções
u C passa arrays completos para funções, simulando uma
chamada por referência.
u Boa solução em termos de desempenho
u O nome de um array corresponde ao endereço do seu
primeiro elemento, &nome-array[0]

u A especificação de conversão %p é utilizada na


visualização de apontadores em hexadecimal

#include <stdio.h>
int main(void)
{
char cadeia[5];
printf(" cadeia = %p\n&cadeia[0] = %p\n",
cadeia, &cadeia[0]);
cadeia = 0064FDF0
return 0; &cadeia[0] = 0064FDF0
}
#include <stdio.h>
#define TAMANHO 5
void modificArray(int [], int);
int main(void)
{
int i, a[5] = {0, 10, 20, 30, 40};
printf("Valores originais:\n");
for (i = 0; i <= TAMANHO - 1; i++)
printf("%4d", a[i]);

modificaArray(a, TAMANHO);
printf("\nValores modificados:\n");
for (i = 0; i <= TAMANHO - 1; i++) Valores originais:
printf("%4d", a[i]); 0 10 20 30 40
return 0; Valores modificados:
} 0 50 100 150 200
void modificaArray(int x[], int comprimento)
{
int j;
for (j = 0; j <= comprimento - 1; j++)
x[j] *= 5;
}
• O que resultaria se fosse:
modificaArray(&a[2], TAMANHO - 2);
13

Arrays
Qualificador const aplicado a arrays
u Qualificador const utilizado para evitar alterações
(não desejadas) de arrays dentro de funções
void tentaModificar(const int []);
int main(void)
{
int a[] = {10, 20, 30};
tentaModificar(a);
. . .
return 0;
}
void tentaModificar(const int b[]) Erros de compilação, por
{ tentativa de modificar
b[0] *= 10;
constantes ! . . .
b[1] *= 20;
b[2] *= 30;
}
• Desempenho da referência, segurança da passagem por
valor
14

Arrays
Ordenação - bubble sort
u O array vai ser percorrido tantas vezes quantos os
seus elementos menos 1.
Em cada percurso o maior valor encontrado é puxado
para o final...
Valores originais:
5 1 7 3 2 4 0 9 8 6
... Vai comparando Valores em ordenacao:
1 1 5 3 2 4 0 7 8 6 9
pares de valores ... 2 1 3 2 4 0 5 7 6 8 9
... e trocando-os 3 1 2 3 0 4 5 6 7 8 9
4 1 2 0 3 4 5 6 7 8 9
entre si, 5 1 0 2 3 4 5 6 7 8 9
se necessário 6 0 1 2 3 4 5 6 7 8 9
7 0 1 2 3 4 5 6 7 8 9
8 0 1 2 3 4 5 6 7 8 9
9 0 1 2 3 4 5 6 7 8 9

u Pouco eficiente, mas fácil de programar


#include <stdio.h>
#define TAMANHO 10
int main(void)
{
int i, passo, temp;
int array[TAMANHO] = {5, 1, 7, 3, 2, 4, 0, 9, 8, 6};
printf("Valores originais:\n");
for (i = 0; i <= TAMANHO - 1; i++)
printf("%3d", array[i]);
printf("\nValores em ordenacao:\n");
for (passo = 1; passo <= TAMANHO - 1; passo++){
for (i = 0; i <= TAMANHO - 2; i++)
if (array[i] > array[i + 1]){
temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
}
for (i = 0; i <= TAMANHO - 1; i++)
printf("%3d", array[i]);
printf("\n");
}
return 0;
}
5 1 7 3 2 4 0 9 8 65 1 7 3 2 4 0 9 8 6
16

Arrays
Ordenação - bubble sort
u Uma versão em que o bubble sort só trata da
ordenação
- ler nº inteiros a ordenar
- ler vector
- visualizar vector a ordenar
- ordenar vector
#include <stdio.h>
- visualizar vector ordenado
#define DIM_MAX 100
#define N_COL 6
int leVector(int vec[], int dim);
void visuVector(const int vec[], int dim, int nCol);
void bubleSort(int vec[], int dim);
int main(void)
{
...
int main(void)
{
int valores[DIM_MAX], num;

do {
printf("\nNumero valores (< %d):\n", DIM_MAX);
scanf("%d", &num);
} while (num < 1 || num > 100);

printf("\nLeitura dos elementos do vector:");


leVector(valores, num);

printf("\n\nVector a ordenar:\n");
visuVector(valores, num, N_COL);

bubleSort(valores, num);
printf("\nVector ordenado:\n");
visuVector(valores, num, N_COL);

return 0;
}
int leVector(int vec[], int dim)
{
int i;
for(i = 0; i < dim; i++) {
printf("\nInteiro: ");
scanf("%d", &vec[i]);
}
return i;
}

void visuVector(const int vec[], int dim, int nCol)


{
int i, c;
for (i = 0; i <= dim - 1; i++) {
putchar(c = (i % nCol == 0) ? '\n' : ' ');
printf("%6d", vec[i]);
}
}
19

Arrays
Ordenação - A função bubble sort

• Recebe um vector de inteiros e devolve-o


ordenado

void bubleSort(int vec[], int dim)


{
int passo, i, temp;
for (passo = 1; passo <= dim - 1; passo++)
for (i = 0; i <= dim - 2; i++)
if (vec[i] > vec[i + 1]){
temp = vec[i];
vec[i] = vec[i + 1];
vec[i + 1] = temp;
}
}
20

Arrays
Exemplo: pesquisa linear
u Pesquisa linear (arrays pequenos e não
necessariamente ordenados)...
u Pesquisa binária (arrays grandes e necessariamente
ordenados)...

u O programa cria um array com valores inteiros


(vamos supor que são apenas inteiros pares) e
responde da seguinte maneira:
Indicar o valor inteiro a procurar: 36
Valor encontrado na posicao 18

Indicar o valor inteiro a procurar: 37


u Função a usar...
Valor nao encontrado
const

int procuraLin( int a[], int valor, int tamanho)


#include <stdio.h>
#define SIZE 10

int procuraLin (int [], int, int);


int main(void)
{
int a[SIZE], i, valor, indice;

/* criar um array de inteiros */


for (i = 0; i < SIZE; i++)
a[i] = 2 * i;

printf("Valor a procurar: ");


scanf("%d", &valor);
indice = procuraLin(a, valor, SIZE);

if (indice == -1)
printf("Valor nao encontrado\n");
else
printf("Valor encontrado na posicao de indice %d\n", indice);

return 0;
}
int procuraLin (int a[], int valorProcurado,
int comprimento)
{
int i;
for (i = 0; i < comprimento; i++)
if (a[i] == valorProcurado)
return i;

return -1;
}
23

Arrays
Exercício: pesquisa binária
u Idêntido ao anterior, mas com pesquisa binária

int procBin(const int quad[], int valor, int indInf, int indSup)

Indicar um valor entre 0 e 28: 25

i c e 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
índ -------------------------------------------------------------
t o r 0 2 4 6 8 10 12 14* 16 18 20 22 24 26 28
vec 16 18 20 22* 24 26 28
24 26* 28
24*
25 nao foi encontrado
Indicar um valor entre 0 e 28: 6
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
-------------------------------------------------------------
0 2 4 6 8 10 12 14* 16 18 20 22 24 26 28
0 2 4 6* 8 10 12
6 foi encontrado na posicao 3
24

Arrays
arrays multidimensionais
u Array bidimensional: int q [3][4]
Coluna Coluna Coluna Coluna
0 1 2 3
Linha 0 q[0][0] q[0][1] q[0][2] q[0][3]
Linha 1 q[1][0] q[1][1] q[1][2] q[1][3]
Linha 2 q[2][0] q[2][1] q[2][2] q[2][3]

u array de 3 linha e 4 colunas: array 3 x 4

ou int q [3] [4]

u array de 3 elementos, sendo cada um deles um array de


4 elementos (inteiros)
u Exemplo, q[1] corresponde a um array de 4 inteiros
25

Arrays
arrays multidimensionais
u Para percorrer um array (linha a linha, coluna ...)
soma = 0;
for (linha = 0; linha <= 2; linha++)
for (coluna = 0; coluna <= 3; coluna++)
soma += q[linha][coluna];

u Inicialização
int a[2][3] = {{1, 2, 3},{4, 5, 6}}; a: 1 2 3
4 5 6

int b[2][3] = {1, 2, 3, 4, 5}; b: 1 2 3


4 5 0

int c[2][3] = {{1, 2}, {4}}; c: 1 2 0


4 0 0
26

Exercícios
Simulação de um helicóptero digital - 1
u Um helicóptero imaginário é comandado
através do teclado. O helicóptero, quando no
ar, não deixa rasto. Para deixar rasto
deverá estar em contacto com o terreno.
Comando Efeito
1 Põe o helicóptero no ar
2 Põe o helicóptero em contacto com o terreno
3 Faz o helicóptero rodar 90o para a direita
4 Faz o helicóptero rodar 90o para a esquerda
5 d Desloca o helicóptero (pelo ar ou em
contacto com o terreno) d posições para a frente
6 Visualiza o terreno (com os rastos feitos
pelo helicóptero)
7 Limpa os rastos do helicóptero no terreno
9 Termina o programa
27

Exercícios
Simulação de um helicóptero digital - 2
u O terreno é suposto ser um quadrado de dimensão 20 x
20, a que corresponde 20 x 20 células, cada uma
identificada pela linha e coluna respectivas. O
helicóptero é caracterizado pela sua posicao, dada
pela linha e coluna onde se encontra (não
necessariamente uma linha e uma coluna do terreno,
pois o helicóptero pode deslocar-se para fora dos
limites daquele), e é ainda caracterizado pela sua
orientacao (um dos pontos cardeais: N, S, E ou O) e
situacao (no ar ou no plano do terreno).

linha 20 --------------------
-------------------- Helicóptero
-------------------- posição: 16 11
-------------------- situação: terreno
----------H--------- orientação: N
N
...
linha 1 --------------------
28

Exercícios
Simulação de um helicóptero digital - 3
u O helicóptero é visualizado pela letra H, as células
ainda não visistadas por ele são visualizadas com -,
enquanto que as já visitadas serão representadas por
O. Por exemplo, após o comando 5 com d=2, obtém-se:

linha 20 --------------------
-------------------- Helicóptero
----------H--------- posição: 18 11
----------O--------- situação: terreno
----------O--------- orientação: N
...
linha 1 --------------------

• Exemplo de uma sessão com o programa helicoptero-


digital, em que as condições iniciais correspondem a
terreno limpo e o helicóptero com posicao: 16 11;
situacao: no-terreno; orientacao: N.
29

Exercícios
Simulação de um helicóptero digital - 4
u Comando: 3 ; roda para a direita 90o
u Comando: 5 ; avança
u Posicoes em frente: 3 ; 3 posições
u Comando: 4 ; roda para a esquerda 90o
u Comando: 5 ; ...
u Posicoes em frente: 2
u Comando: 4
u Comando: 5
u Posicoes em frente: 6
u Comando: 6
linha 20 --------------------
--------------------
-------HOOOOOO------
-------------O------
----------OOOO------
...
linha 1 --------------------
30

Exercícios
Simulação de um helicóptero digital - 5
u 1- Definir e implementar, se necessário, uma
abstracção de dados compatível com o problema
exposto.
u 2- Fazer uma abordagem de-cima-para-baixo ao
programa helicoptero-digital, para identificar as
suas tarefas e sub-tarefas principais.
u 3- Escrever em C o programa helicoptero-digital,
tomando por base os resultados da abordagem
anterior.

u Nota:
O helicóptero na sua deslocação pode ultrapassar os
limites do terreno, situação em que não deixa rasto.
O programa continuará a actualizar as suas
características, de acordo com os comandos que vai
recebendo.
31

Exercícios
Bubble sort
u A ordenação bubble sort já apresentada é
extremamente ineficiente para arrays de
grandes dimensões. Introduzir os seguintes
melhoramentos àquela solução.

1- Depois do 1º passo é garantido que o maior


valor está na última posição, que não
necessitará de ser visitada no passo
seguinte...

2- O array a ordenar pode já estar próximo da


ordenação pretendida, não sendo necessários
todos os passos. Basta detectar quando, num
dado passo, não se verifique qualquer
alteração de posições...
32

Arrays
Ordenação - A função bubble sort

• Recebe um vector de inteiros e devolve-o


ordenado

void bubleSort(int vec[], int dim)


{
int passo, i, temp;
for (passo = 1; passo <= dim - 1; passo++)
for (i = 0; i <= dim - 2; i++)
if (vec[i] > vec[i + 1]){
temp = vec[i];
vec[i] = vec[i + 1];
vec[i + 1] = temp;
}
}
33

Exercícios
Bucket Sort - 1
u Um array contém n inteiros positivos para ordenar.
Considerar um array auxiliar 10 x n. Cada uma das
suas 10 linhas é designada por bucket. Escrever a
função bucketSort que toma um array de inteiros e o
seu comprimento como argumentos e implementa o
seguinte algoritmo:
1- Percorre o array e coloca os seus elementos nas
linhas do array 10 x n, de acordo com o seu dígito
das unidades. Por exemplo, 97 é colocado na linha 7,
3 é colocado na linha 3, e 100 na linha 0.
2- Percorre o array auxiliar e obtém o array inicial
agora ordenado da seguinte maneira: 100, 3, 97.
3- Repete 1- e 2- agora com o dígito das dezenas,
depois das centenas, ... e termina quando é tratado
o dígito mais significativo do maior número.
34

Exercícios
Bucket Sort - 2

Array a 10 buckets
ordenar B0 B1 B2 B3 B4 B5 B6 B7 B8 B9

97 3 100 100 3 97

100 3 97 100 97
3

100 3 97 3 100
97

3 97 100 <--- termina, pois não há mais dígitos...


Se continuasse, cairiam todos em B0.
35

Exercícios
Selection sort

u O algoritmo Selection sort inicia-se


procurando o elemento mais pequeno de um
array. Esse elemento é trocado com o primeiro
elemento do array. O processo continua com o
sub-array constituido a partir do segundo
elemento do array...
O processo termina quando o sub-array tem
apenas um elemento.
Escrever uma função recursiva para este
algoritmo.
36

Exercícios
Pesquisas linear e binária
u Foi apresentado um exemplo relativo à procura linear
(para arrays pequenos e com os respectivos elementos
não ordenados). Escrever agora uma função recursiva que
faz a mesma pesquisa e recebe como argumentos um array
de inteiros, um inteiro que é o valor a procurar e um
inteiro que é o tamanho daquele array. Se o valor é
encontrado, a função devolve a sua posição. Se não for
encontrado, devolve -1.

u Também foi apresentado um exemplo relativo à procura


binária (para arrays grandes e com os respectivos
elementos ordenados). Escrever a função recursiva que
faz a mesma pesquisa e recebe como argumentos um array
de inteiros, um inteiro que é o valor a procurar, e
dois inteiros que representam, respectivamente, o
índice mais baixo e o índice mais alto do array a
pesquisar. Se o valor é encontrado, a função devolve a
sua posição. Caso não seja encontrado, devolve -1.
37

Exercícios
Recursividade

u Escrever a função recursiva visuArray que


toma um array e o seu tamanho como argumentos
e não devolve nada. A função visualiza os
elementos do array e pára quando recebe um
array de tamanho zero.

u Escrever a função recursiva


visuCadeiaAoContrario que toma um array de
caracteres como argumento e visualiza a
cadeia ao contrário, com um espaço entre
caracteres. A função pára quando encontra o
caracter nulo, '\0'.
#include <stdio.h>
void visuCadeiaAoContrario(char []);
int main(void)
{
char cadeia[] = "123abcdfgh";
printf("\nCadeia original: %s\n", cadeia);
printf("\nCadeia ao contrario: ");
if ('\0' != cadeia[0])
visuCadeiaAoContrario(cadeia);
printf("\n");
return 0;
}

void visuCadeiaAoContrario(char cadeia[])


{
if ('\0' == cadeia[1])
printf("%c ", cadeia[0]);
else {
visuCadeiaAoContrario(&cadeia[1]);
printf("%c ", cadeia[0]);
}
}
39

Exercícios
Recursividade

u Escrever a função recursiva minNoarray que


toma um array de inteiros e um inteiro que é
o seu tamanho como argumentos e devolve o
mais pequeno valor no array. A função pára
quando recebe um array com um valor.

u Escrever a função recursiva capicua que toma


uma cadeia de caracteres como argumento e
devolve 1 se essa cadeia for uma capicua ou
zero, se não for capicua.
#include <stdio.h>
#define TAMANHO 10
int minNoarray(int [], int);
int main(void)
{
int i;
int array[TAMANHO] = {9, 8, 7, 6, -5, 4, 0, 2, 1, 78};
printf("\nValores originais:\n");
for (i = 0; i <= TAMANHO - 1; i++)
printf("%3d", array[i]);
printf("\nValor minimo: %d\n", minNoarray(array, TAMANHO));
return 0;
}

int minNoarray(int quad[], int tamanho)


{
int valorMin;
if (1 == tamanho)
return quad[0];
else{
valorMin = minNoarray(&quad[1], --tamanho);
return
quad[0] < valorMin? quad[0]: valorMin;
}
}
#include <stdio.h>
#include <string.h>
int capicua(char []);
int capicuaAux(char [], size_t);
int main(void)
{
char cadeia[] = "abc d cba";
printf("\nCadeia original: %s\n", cadeia);
if (capicua(cadeia))
printf("E uma capicua\n");
else
printf("Nao e uma capicua\n");
return 0;
}

int capicua(char cadeia[])


{
return capicuaAux(cadeia, strlen(cadeia));
}
int capicuaAux(char cadeia[], size_t comp)
{
if (comp == 0 || comp == 1)
return 1;
else
return cadeia[0] == cadeia[comp - 1]
&& capicuaAux(&cadeia[1], comp - 2);
}

Você também pode gostar