Вы находитесь на странице: 1из 48

Estrutura de Dados

Aula 06
Vetores como parmetros; Diferena entre vetores e ponteiros; Atividade de laboratrio.

Problema 25
Implemente uma funo que classifique os elementos de um vetor em ordem crescente usando o algoritmo de ordenao por seleo.

ordenao por seleo: procure pelo menor elemento no vetor e permute com o primeiro elemento do vetor; repita este processo para o subvetor que se inicia no segundo elemento e, assim, sucessivamente; o processo termina quando o subvetor contiver apenas um elemento.
Teste a funo com dados aleatrios.
2

Anlise do programa
Para haver a troca, os parmetros no devem ser passados por referncia (endereo)?

Observe como um vetor passado como parmetro de uma funo: o nmero de elementos do vetor no precisa ser declarado.

Anlise do programa
#define INFINITO 999999 #define TAM_MAX 50 int main(int args, char * arg[]) { int i,n,a[TAM_MAX]; // Inicializar gerador de nmeros aleatrios srand((unsigned)time(NULL)); // Vetor gerado aleatoriamente n = (rand() % TAM_MAX)+1; printf("Vetor original: "); for (i = 0; i < n; i++) { a[i] = (rand() % 100); printf("%d ",a[i]); } printf("\n"); // Classificar vetor ordenar_por_selecao(a,n); printf("Vetor ordenado: "); for (i = 0; i < n; i++) printf("%d ",a[i]); printf("\n"); system("PAUSE"); return 0; }

Passagem de parmetros
Quando deve ser feita este tipo de passagem? Veja o exemplo:

Exibe: x = 2 y = 5 Passagem por Valor

Exibe: x = 5 y = 2 Passagem por Referncia


5

Vetores como parmetros


No caso de uma funo ter como parmetro um vetor, temos um caso particular de grande importncia.

Por qu? Porque o nome de um vetor nada mais que um ponteiro para sua primeira posio. Exemplo:
char v[8];
F17 F18 F19 F1A F1B F1C F1D F1E

v F17

C
0

O
1

R
2

D
3

I
4

A
5

L
6

\0
7
6

Vetores como parmetros


Mas, ento como possvel usarmos a notao:
nome_do_vetor[ndice]

Isto pode ser facilmente explicado, desde que se entenda que a notao acima absolutamente equivalente a:
*(nome_do_vetor + ndice)

Mas, o que significa somar (ou subtrair) um valor a um ponteiro?


7

Vetores como parmetros


Quando incrementamos um ponteiro, ele passa a apontar para o prximo valor do mesmo tipo. Exemplo: ao incrementar um ponteiro para char, ele anda 1 byte na memria e ao incrementar um ponteiro para double ele anda 8 bytes.
0 1

C
v

D
v+3

v &v[0] *v v[0] = 'C' *(v + 3) v[3] = 'D'

So equivalentes!!!
8

Vetores como parmetros


Logo, como o nome de um vetor tambm um ponteiro, a passagem de parmetro para vetores sempre por referncia. Assim, qualquer modificao ocorrida no vetor dentro da funo ser, na realidade, feita sobre o parmetro usado na chamada.

...

Alteraes no vetor x dentro da funo ordenar_por_selecao sero tambm realizadas no vetor a. Na definio da funo, podemos substituir int x[ ] por int x[TAM_MAX] ou ainda int *x.

...

Vetores como parmetros


O que devemos fazer se desejarmos que os elementos de um vetor, passado como parmetro para uma funo, no sejam alterados?

Resposta: dentro da funo preciso atribuir os elementos do vetor a uma varivel local. Considere o exemplo mostrado a seguir.

10

Vetores como parmetros

Sim! A passagem por referncia. Os elementos do vetor a tero seus valores modificados pela funo quadrado?
11

Vetores como parmetros


Ateno! Observe que a cpia dos elementos foi feita um a um. O que aconteceria se fizssemos: x = v?

No! Foi feita uma cpia de v em x.

E agora, os elementos do vetor a tero seus valores modificados pela funo quadrado?
12

Diferena entre vetores e ponteiros


Ateno!! H uma diferena importante entre o nome de um vetor e um ponteiro: um ponteiro uma varivel, mas o nome de um vetor no uma varivel. Isto significa, que no se consegue alterar o endereo que apontado pelo "nome do vetor". Exemplo:
Operaes invlidas

int v[10]; int *p, i; p = &i;

Operaes vlidas

v = v + 2; v++; v = p;

p = v; p = v + 2;
13

Qualificador const
Para indicar que um parmetro de funo no deve ser alterado, usa-se o qualificador const. Exemplo:
Se existir na funo uma atribuio de valor a um parmetro declarado como constante, a compilao indicar um erro.

14

Problema 26
Implemente uma funo que classifique os elementos de um vetor em ordem crescente usando o algoritmo quicksort:
1. 2. 3. Seja m o elemento na posio central no vetor; Seja i o ndice do primeiro e j, o ndice do ltimo elemento do vetor; Enquanto i for menor ou igual a j, faa com que: a) O valor de i cresa at encontrar um elemento maior que m; b) O valor de j diminua at encontrar um elemento menor que m; c) Haja a troca entre os elementos que ocupam as posies i e j.

15

Problema 26
Ao final desses passos, a situao do vetor ser a seguinte: esquerda da posio central, existem somente elementos menores do que m; direita da posio central, existem somente elementos maiores do que m; Assim, o problema de ordenar o vetor se reduz ao problema de ordenar cada uma dessas metades. Os mesmos passos sero aplicadas repetidas vezes cada nova metade, at que cada metade contenha um nico elemento (caso trivial).
16

Problema 26
Considere o exemplo abaixo:
Ordenar {4,1,3,5,2}

4
Ordenar {2,1}

2
Ordenar {5,4}

1 2
Ordenar {2}

5 4
Ordenar {4}

4 5
Ordenar {5}

1
Ordenar {1}

Como a natureza dos problemas sempre a mesma (ordenar um vetor), o mesmo mtodo pode ser usado para cada subproblema.
17

Anlise do programa

Veja que interessante: a funo quicksort chama a si mesma!!!


18

Recursividade
A funo quicksort implementada um exemplo de funo recursiva: funo que chama a si mesma.

19

Funes recursivas
A recursividade muitas vezes torna o algoritmo mais simples. Veja, por exemplo, o Problema 27, que implementa uma soluo recursiva para o jogo Torre de Hani.

Desafio: escrever um algoritmo no-recursivo para resolver o jogo Torre de Hani.

20

Funes recursivas
// Programa p27.c #include <stdio.h> #include <stdlib.h> void mover(int n, int a, int b, int c); int main(int args, char * arg[]) { int n; printf("Numero de discos: "); scanf("%d",&n); printf("Solucao da Torre de Hanoi com %d discos:\n",n); mover(n,0,2,1); system("pause"); return 0; } void mover(int n, int a, int b, int c) { if (n > 0) { mover(n-1,a,c,b); printf("%d -> %d\n",a,b); mover(n-1,c,b,a); } }

21

Problema 28
Considere que um polinmio representado como um vetor de valores do tipo float (vetor de coeficientes). Por economia de memria, o vetor deve conter apenas o nmero necessrio e suficiente de elementos para representar o polinmio. Implemente a funo mostrar_polinomio que exibe um polinmio representado desta maneira.

22

Anlise do programa
Note que o vetor declarado como um ponteiro.

Note que o tamanho do vetor de coeficientes definido em tempo de execuo, aps o usurio fornecer o grau do polinmio.
23

Alocao esttica de memria


J discutimos que o nome de um vetor nada mais que um ponteiro para sua primeira posio. Exemplo:
char v[8];
F17 F18 F19 F1A F1B F1C F1D F1E

v F17

C
0

O
1

R
2

D
3

I
4

A
5

L
6

\0
7

Portanto, uma outra forma de declarar o vetor :


char *v;
24

Alocao esttica de memria


Ento, qual a diferena entre declarar o vetor v como um ponteiro para char ou como um vetor de elementos do tipo char?
char *v; ou
char v[8];
F17 F18 F19 F1A F1B F1C F1D F1E

v F17

C
0

O
1

R
2

D
3

I
4

A
5

L
6

\0
7

A diferena est na alocao de memria.


25

Alocao esttica de memria


Ao declarar v como um vetor de elementos do tipo char, o compilador aloca automaticamente o espao de memria necessrio.

Para o exemplo:

char v[8];

O compilador aloca 8 * N bytes de memria para v, onde N corresponde ao nmero de bytes usado pelo compilador para armazenar o tipo char.

Normalmente, N = 1 byte, para o tipo char.


26

Alocao esttica de memria


A linguagem C utiliza a funo sizeof para determinar o nmero de bytes reservado pelo compilador para um determinador tipo.
a = sizeof(int); Por exemplo, no gcc: b = sizeof(float); c = sizeof(double); a = 4 b = 4 c = 8

Ao calcular o espao de memria de um vetor, use a funo sizeof, pois o espao de memria de um determinado tipo, pode variar entre compiladores.
10 * 4 bytes int w[10]; 10 * sizeof(int)
gcc qualquer compilador
27

Alocao esttica de memria


Se o programador define a quantidade de memria necessria a um vetor (especificando o tipo e o nmero de elementos), a alocao de memria pode ser feita em tempo de compilao: alocao esttica. Declarando um vetor como ponteiro, a alocao de memria no pode ser feita pelo compilador, pois a declarao no especifica o nmero de elementos. Neste caso, a alocao dever ser feita em tempo de execuo: alocao dinmica de memria.
porque feita em tempo de execuo
28

Alocao dinmica de memria


Para fazer a alocao dinmica de memria, podemos usar as funes calloc ou malloc. A funo calloc requer dois parmetros: o nmero de posies de memria e o tamanho em bytes de cada posio.

J a funo malloc requer apenas um parmetro: o espao total em bytes de memria necessrio. Estas funes retornam um ponteiro do tipo void para o incio do espao de memria alocado.
29

Alocao dinmica de memria


Portanto, este ponteiro deve ser convertido (type casting) para o tipo de dado desejado. Para fazer com que w aponte para um espao de memria capaz de acomodar 10 elementos do tipo int, podemos escrever:
int *w; w = (int *)calloc(10,sizeof(int));

ou ento:

No caso do gcc, esta converso no precisa ser explcita.

int *w; w = (int *)malloc(10*sizeof(int));


30

Alocao dinmica de memria


Qual a vantagem de declarar um vetor como ponteiro? Neste caso, no necessrio definir, a priori, o nmero de posies de memria necessrias. No programa p28.c, por exemplo, o vetor c usado para armazenar os coeficientes de um polinmio. Porm, no possvel saber o nmero exato de coeficientes, pois este nmero depende do grau do polinmio, que fornecido em tempo de execuo.
31

Alocao dinmica de memria


Obviamente, seria possvel declarar o vetor c como:
int c[MAX_TAM];

sendo MAX_TAM uma constante definida previamente. Neste caso, MAX_TAM deveria ser estimado e poderamos ter duas situaes possveis: a) Desperdcio de memria; b) Erro devido subestimao de MAX_TAM. O programa p28.c declara o vetor c como um ponteiro e aloca o espao de memria somente depois de conhecido o grau do polinmio.
c = (float *)calloc(n+1,sizeof(float));
32

Alocao dinmica de memria


Outra vantagem da alocao dinmica de memria a possibilidade de reduzir ou aumentar a quantidade de memria alocada anteriormente. Isto pode ser feito com a funo realloc, cujos parmetros so um ponteiro para o incio do bloco de memria e a quantidade de bytes a ser alocada.

Essa funo retorna um ponteiro para o incio do novo bloco de memria. Este ponteiro pode ser igual ao ponteiro para o bloco de memria original. Caso seja diferente, a funo realloc copia os dados armazenados no bloco de memria original para o novo bloco de memria.

33

Alocao dinmica de memria

Criao do vetor.

Aumentando o espao alocado.


Diminuindo o espao alocado.
34

Strings como ponteiros


Considere o seguinte programa:

Neste caso, msg um ponteiro para char, ou equivalentemente, um vetor de caracteres.


Note que no h alocao de memria chamandose a funo calloc ou a funo malloc.
35

Strings como ponteiros


Isto possvel porque, para strings, o espao de memria necessrio e suficiente alocado, dinamicamente, no momento da atribuio.

Assim, a instruo: msg = "Linguagem C\n"; atribui msg treze posies de memria:
msg
L i n g u a g e m C \n \0

Se em seguida, o programa atribui:


msg = "Programao na Linguagem C\n"; ou O espao alocado para msg ser diminudo ou aumentado 36 automaticamente.

msg = "C\n";

Strings como ponteiros


Este tipo de alocao dinmica ocorre apenas no caso de atribuies para strings. Se o valor do string no for atribudo diretamente (por exemplo, valor lido pelo comando gets), a alocao deve ser feita usando calloc ou malloc.

37

Strings como ponteiros


A leitura de um string deve ser feita pela funo gets, pois usando-se scanf, os espaos em branco so entendidos como separadores de valores.

Por exemplo, se o usurio digita:


Sao Paulo Futebol Clube

Ento, a instruo:
scanf("%s",nome);

atribuiria varivel nome apenas o valor Sao.


38

Entrada de Dados String com espaos em branco

Entrada de Dados String com espaos em branco

Entrada de Dados String com espaos em branco

scanf(%[^\n]s, nome);
%s
Leitura

de string

^
Ler

qualquer caractere um enter

\n
At

Alocao dinmica para matrizes


Como no caso de vetores, o nome de uma matriz tambm um ponteiro para a primeira posio de memria alocada para esta matriz.

Portanto, uma matriz tambm pode ser declarada como um ponteiro. Considere, por exemplo, o caso de uma matriz bidimensional com m linhas e n colunas.

42

Alocao dinmica para matrizes


Uma matriz pode ser imaginada como um vetor de m elementos, em que cada elemento um ponteiro para o incio de um vetor de n elementos. Exemplo: int mat[3][4];
F1A F1B F1C F1D

mat
F17

F17

F1A
A01 A02 A03 A04

F18

A01
B01 B02 B03 B04

Vetores que armazenam os elementos da matriz.

F19

B01

Vetor que armazena os endereos das linhas da matriz.

43

Alocao dinmica para matrizes


Portanto, inicialmente, preciso alocar um vetor com trs elementos, correspondentes aos endereos das linhas da matriz.

Isto pode ser feito como a seguir:


mat = (int **)calloc(3,sizeof(int *));

A seguir, deve-se alocar, para cada elemento de mat, um vetor com quatro elementos do tipo int.
for (i = 0; i < 3; i++) mat[i] = (int *)calloc(4,sizeof(int));
44

Alocao dinmica para matrizes


Portanto, no caso geral de uma matriz de m linhas e n colunas, a alocao dinmica de memria pode ser feita como:
mat = (int **)calloc(m,sizeof(int *)); for (i = 0; i < m; i++) mat[i] = (int *)calloc(n,sizeof(int));

A alocao de memria para matrizes com mais dimenses pode ser feita de forma anloga.
Como seria, por exemplo, para uma matriz tridimensional?
45

Alocao dinmica para matrizes


Neste caso, teramos o cdigo:

Para este cdigo, podemos abstrair a representao da matriz a como a seguir.


46

Alocao dinmica para matrizes


Exemplo: float ***a;
Sejam: n1=2, n2=3, n3=4
20 A0 A0 A1 A2 A3

23 18

a
10 10 20

B0 B1 B2 B3 21 B0

15

19 51

22

C0

C0 C1 C2 C3

76 12

11

30 D0 D1 D2 D3 30
D0

43

Exemplo: a[0][0][0] = 23 a[1][2][3] = 90

E0 E1 E2 E3 31 E0

21 56

32

F0

F0 F1 F2 F3

23 90

47

EXERCCIO Problema 29
Um professor mantm as notas dos alunos das classes em que leciona em tabelas, onde as linhas correspondem aos alunos e as colunas correspondem s avaliaes. Para cada classe, o professor pode fazer quantas avaliaes desejar. Implemente as funes:
maior_nota: retorna a maior nota obtida pela classe; deve retornar tambm o nmero do aluno e o nmero da avaliao correspondente maior nota da classe; media_classe: retorna a mdia das notas obtidas pela classe, considerando todas as avaliaes realizadas.

Testar o programa com notas geradas aleatoriamente.


48

Вам также может понравиться