sexta-feira, 12 de agosto de 2011

Listas Encadeadas em C


Olá pessoal,

hoje trabalharemos com um assunto muito interessante em C, que são listas encadeadas. Faremos um pequeno programa onde vamos inserir elementos em uma lista Encadeada, excluir elementos, imprimir e contá-los.

Para isso, vamos ter em mente como ficará a configuração em nossa memória de uma lista encadeada:


Veja que a estrutura consiste de um “valor” e um ponteiro que aponta para a próxima estrutura. Para inserir um dado, veja, é muito fácil, apenas o que devemos fazer é criar um novo elemento com um valor associado que aponte para NULL.

Assim pegamos o último elemento de nossa lista, e apontamos para ele:

Para excluir, devemos fazer com que o elemento anterior ao que desejamos excluir, aponte, para o campo “proximo” do elemento que desejamos excluir. Devemos salvar, antes quem desejamos excluir, para que depois possamos usar a função para liberar memória.



As operações para imprimir e contar que são mostradas apenas percorremos a lista, tendo cuidado para não usar um elemento NULL.

Vamos ao código:

#include <stdio.h>
#include <stdlib.h>

typedef struct listaDeDados
{
int dado;
struct listaDeDados * proximo;

}listaDeDados;
int ImprimeOpcoes()
{
/*
Funcao imprimirá na tela as opções que nosso programa realizará
A opção é retornada com o auxílio da variável op
*/
int op;
printf("\n\t1 - Insere Elemento");
printf("\n\t2 - Deleta Elemento");
printf("\n\t3 - Imprime Lista");
printf("\n\t4 - Conta Numero de elementos.");
printf("\n\t5 - Sair\n\t");
scanf("%d",&op);
return op;
}

listaDeDados * CriaElemento(int valor)
{
/*
Função cria um novo elemento e o retorna para ser acrescentado na lista
Para a criação do novo elemento você precisa informar seu valor, ou seja,
o valor do campo dado
*/
listaDeDados * novoElemento = (listaDeDados*)malloc(sizeof(listaDeDados));
novoElemento->proximo = NULL; //não esqueça que o novo elemento aponta para NULL
novoElemento->dado = valor;
return novoElemento;
}

listaDeDados * InsereNovoElemento(listaDeDados * listaAtual, int valor)
{
/*
Função que insere um elemento em uma lista.
Ele considera o caso da lista estar vazia, ou seja, NULL
Veja que devemos procurar pelo elemento que aponta para NULL, e fazer com que ele aponte para o novo elemento
Veja que criamos uma lista para ficar armazenando o primeiro endereço da lista, pois do contrário
iríamos perder a referência da lista.
*/
listaDeDados * listaComEnderecoInicial;
listaComEnderecoInicial = listaAtual;
if(listaAtual == NULL)
return CriaElemento(valor);
else
{
while(listaComEnderecoInicial->proximo != NULL)
listaComEnderecoInicial = listaComEnderecoInicial->proximo;

listaComEnderecoInicial->proximo = CriaElemento(valor);
return listaAtual;
}
}

void ImprimeLista(listaDeDados* listaAtual)
{
/*
Vamos imprimir os valores da lista. Aqui percorremos a lista até encontrarmos um valor NULL
*/
if(listaAtual!=NULL)
{
printf(" %d ", listaAtual->dado);
ImprimeLista(listaAtual->proximo);
}

else
return;


}

listaDeDados * DeletaElemento(int valor, listaDeDados * listaAtual)
{
/*
Essa função será responsável por deletar um elemento da lista
Veja que não é necessário apenas desfazer o apontamento,
precisamos liberar o espaço de memória
*/

listaDeDados * listaEnderecoInicial, * listaElementoAnterior;
listaEnderecoInicial = listaElementoAnterior = listaAtual;
if(listaAtual == NULL)
return listaAtual;
if(listaEnderecoInicial->dado == valor)
{
listaElementoAnterior = listaEnderecoInicial;
listaEnderecoInicial = listaEnderecoInicial->proximo;
free(listaElementoAnterior);
return listaEnderecoInicial;
}
else
{
listaEnderecoInicial = listaEnderecoInicial->proximo;
while(listaEnderecoInicial != NULL)
{

if (listaEnderecoInicial->dado == valor)
{
listaElementoAnterior->proximo = listaEnderecoInicial->proximo;
free(listaEnderecoInicial);
return listaAtual;
}
else
{
listaElementoAnterior = listaEnderecoInicial;
listaEnderecoInicial = listaEnderecoInicial->proximo;
}
}
}
return listaAtual;
}

int ContaElementos(listaDeDados * listaAtual)
{
/*
Função vai contar o número de elementos da lista
*/
int contador = 0;
if(listaAtual == NULL)
return 0;
else
{
while(listaAtual!=NULL)
{
contador++;
listaAtual= listaAtual->proximo;
}
}
return contador;
}
/*
Nosso programa main será bem simples pois apena iremos testar as funções criadas acima
*/
int main()
{
int op, valor;
listaDeDados * listaPrincipal = NULL;
do
{
op = ImprimeOpcoes();
switch(op)
{
case 1: printf("\n\tInforme o valor do novo elemento: ");
scanf("%d", &valor);
listaPrincipal = InsereNovoElemento(listaPrincipal,valor);
break;
case 2: printf("\n\tInforme um elemento a ser excuido:\n");
ImprimeLista(listaPrincipal);
printf("\n\tValor: ");
scanf("%d",&valor);
listaPrincipal = DeletaElemento(valor, listaPrincipal);
printf("\n\tLista Resultamte:");
ImprimeLista(listaPrincipal);
break;
case 3: printf("\n\tImprimindo lista\n\t");
ImprimeLista(listaPrincipal);
break;
case 4: printf("\n\tNumero de elementos: %d\n", ContaElementos(listaPrincipal));
break;

}
}while(op <5);
return 0;
}