Академический Документы
Профессиональный Документы
Культура Документы
1. Estrutura bsica
Uma lista encadeada simples uma estrutura de dados composta de uma seqncia de estruturas elementares chamadas ns. Cada n contm a) uma informao til (um dado) e b) a localizao na memria do prximo n na seqncia. Naturalmente, a informao da localizao do prximo n deve ser guardada em um ponteiro. Assim, cada n deve ser uma struct que contenha estes dois campos a) e b). Vamos dar exemplos de tais structs, variando o tipo de informao contida nos ns: 1. A informao um nmero inteiro. Neste caso, podemos escrever a struct como
struct no { int info; struct no *prox; };
A informao guardada no campo info, que um int, e a localizao do prximo n guardada no campo prox, que um ponteiro. Este ponteiro deve ser do tipo struct no, j que vai apontar para o prximo n. 2. A informao uma string:
struct no { char info[80]; struct no *prox; };
Neste caso, o campo info uma string de 80 caracteres. 3. A informao consiste de vrios dados, por exemplo nome e nmero de alunos:
struct no { char nome[80]; int ra; struct no *prox; };
Neste caso, a informao guardada em cada n consiste do conjunto da string nome e do inteiro ra. Alm da definio da struct no, definiremos tambm um tipo para o ponteiro que aponta para um n como pno
typedef struct no * pno;
Vamos representar por meio de um diagrama o primeiro caso. No diagrama abaixo est representada uma estrutura elementar e uma lista encadeada cujos dois primeiros elementos so 7 e 5 e o ltimo 9. O acesso ao primeiro elemento da lista feito atravs do ponteiro inicial. O ltimo elemento marcado por seu ponteiro prox ter o valor invlido NULL, ao invs de apontar para um prximo elemento:
int main() { /* Chamamos o ponteiro inicial de lista */ /* inicializamos com NULL, o que significa que a lista vazia */ pno lista = NULL;
pno n; /* usado para alocar um novo n */ pno p; /* usado para imprimir a lista */
/* A lista imprimida */ printf("Imprimindo lista:\n"); p = lista; /* comeamos com o elemento inicial */ while(p != NULL) { printf("%d ", p->info); /* imprimimos a info de cada elemento */ p = p->prox; /* avanamos para o prximo elemento da lista */ } printf("\n");
system("pause"); return 0; }
2. Repita na main() apenas a parte de criao de um novo n e de adio lista para que sejam inseridos os valores 20 e 30. 3. No programa resultante da questo 2, isole a criao de um novo n dentro de uma funo chamada get_node(). A funo deve ser chamada assim: n = get_node(10). Esta chamada cria um novo n cujo info 10 e retorna um ponteiro para a localizao deste n. Isole tambm a adio de um novo n dentro de uma funo chamada push(). Esta funo deve ser chamada assim: push(&lista, 10); para inserir o nmero 10 no incio da lista (note que o argumento lista passado por referncia). Dica: os prottipos das funes devem ser:
pno get_node(int); void push(pno *, int);
A funo push () deve chamar a funo get_node() e a funo main() dever apenas chamar a funo push(). 4. Isole a impresso da lista em uma funo chamada print_list() que deve ser chamada assim: print_list(lista); 5. Exerccio resolvido: modifique a estrutura de dados para que a informao de cada n seja um float. Escreva um programa que l nmeros digitados pelo usurio em qualquer quantidade, usando um lao (em cada lao, o programa deve perguntar se mais um nmero deve ser inserido). Dica: o lao deve ter uma forma assim:
do { /* inserir aqui a entrada de dados na lista */ printf("Mais um numero? (s/n): "); scanf(" %c", &c); /* ateno, o espao antes do %c importante */ } while(c != 'n');
Crie duas funes, uma que calcula a mdia e outra que calcula o desvio padro dos valores da lista. Estas funes devem ser usadas assim:
m = media(lista); s = desvio_padrao(lista, media); printf("media = %f, desvio padrao = %f\n", m, s);
Dica: estas duas funes percorrem toda a lista, at o final, e portanto so parecidas com a print_list(). No final, o programa deve imprimir a lista de valores digitados, sua mdia e seu desvio padro. Soluo: veja no final.
Usando as funes definidas nos exerccios 3 e 4, podemos escrever um exemplo em que se retira o primeiro elemento de uma lista:
main() { /* Ponteiro inicial da lista, inicialmente vazia: */ pno lista = NULL;
/* Remoo do primeiro elemento ------------------------------*/ /* guarda a localizao do primeiro elemento: */ p = lista; /* imprime o primeiro elemento: */ printf("Removendo o elemento %d.\n", p->info); /* faz com que o ponteiro inicial aponte para o segundo elemento: */ lista = p->prox; /* devolve a memria ocupada pelo primeiro elemento: */ free(p);
Soluo: veja no final. 8. Exerccio resolvido: crie uma funo que l uma quantidade qualquer de nmeros entrados pelo usurio e os imprime na ordem inversa de entrada, usando as funes push() e pop() (observao: com estas funes, implementamos uma pilha (LIFO)). Soluo: veja no final.
6. Exerccios resolvidos
Soluo do exerccio 5:
#include <stdio.h> #include <stdlib.h> #include <math.h>
void print_list(pno p) { printf("Imprimindo lista:\n"); while(p != NULL) { printf("%f ", p->info); p = p->prox; } printf("\n"); }
} return m / n; }
float desvio_padrao(pno p, float m) { float s = 0; int n = 0; while(p != NULL) { s = s + (p->info - m) * (p->info - m); n = n + 1; p = p->prox; } return sqrt(s / n); }
float x; char c;
float m, s;
do { printf("Digite um numero: "); scanf("%f", &x); push(&lista, x); printf("Mais um numero? (s/n): "); scanf(" %c", &c); } while(c != 'n');
print_list(lista);
system("pause"); return 0; }
Soluo do exerccio 7 (apenas a funo pop() e a funo main(), as outras funes, a struct e o typedef devem ser iguais aos do exerccio acima).
/* A funo de remoo. */ /* l (o ponteiro inicial da lista) e n so passados por referncia. */ int pop(pno *l, int *n) { /* guarda o endereo do elemento a ser retirado: */ pno p = *l; /* verifica se a lista era vazia: */ if(p == NULL) return 0; /* passa o valor a ser retirado referncia n: */ *n = p->info; /* altera o ponteiro inicial para apontar ao segundo elemento: */ *l = p->prox; /* libera a memria ocupada pelo primeiro elemento */ free(p); /* retorna 1, pois a lista no era vazia: */ return 1; }
int main() { /* Ponteiro inicial da lista, inicialmente vazia: */ pno lista = NULL; /* usados para guardar os valores recebidos pelo pop: */ int status, x;
/* Remoo do primeiro elemento */ status = pop(&lista, &x); printf("status = %d, elemento removido: %d\n", status, x);
system("pause"); return 0; }
Soluo do exerccio 8 (apenas a funo main(). O programa deve ser completado com o que falta)
int main() { pno lista = NULL; int x; char c;
/* Insere nmeros na lista at que o usurio digite n */ do { printf("Digite um numero: "); scanf("%d", &x); push(&lista, x); printf("Mais um numero? (s/n): "); scanf(" %c", &c); /* ateno, o espao antes de %c importante! */ } while(c != 'n');
/* retira os elementos da lista e os imprime um por um */ /* at que pop() retorne 0 (isto , a lista fique vazia) */ printf("Numeros na ordem inversa: "); while(pop(&lista, &x) != 0) { printf("%d ", x); } printf("\n");
system("pause"); return 0; }