1. Universidade Federal de Ouro Preto
Instituto de Ciências Exatas e Biológicas
Departamento de Computação
ALGORITMOS E ESTRUTURAS DE DADOS
Segundo Trabalho Prático
Johnnatan Messias Peixoto Afonso
Professor - David Menotti
Monitor - Kayran dos Santos
Ouro Preto
6 de outubro de 2009
4. 1 Introdução
Este trabalho consiste na implementação do TAD (Tipo Abstrato de Dados)
TBloco para representar as listas encadeadas dos blocos para representarmos o
Mundo dos Blocos com as implementações das funções.
1.1 Considerações iniciais
• Além das explicações citadas acima das funções, favor considerar também os
comentários contidos no programa.
• Ambiente de desenvolvimento do código fonte: Microsoft Visual Studio 2008
Professional.
• Linguagem utilizada: Linguagem C.
• Ambiente de desenvolvimento da documentação: TeXnicCenter 1.0 SRC-Editor
A
de LTEX.
1.2 Especicação do problema
Várias áreas da ciência da computação usam domínios simplicados para abstrair
diversos tipos de problemas. Por exemplo, algumas das primeiras pesquisas de
inteligência articial nas áreas de planejamento e robótica eram feitas utilizando o
mundo dos blocos, no qual um braço robótico realizava tarefas simuladas envolvendo
a manipulação de blocos [2]. Nesse trabalho você vai implementar um mundo de
blocos bem simples [3], que vai funcionar de acordo com certas regras e obedecer
comandos de movimentação de blocos dados pelo usuário, simulando o que seria a
manipulação através um braço robótico. O seu mundo de blocos começa com cada
bloco na sua posição inicial, e depois de uma série de comandos deve terminar em
uma conguração nal.
Os comandos possíveis para a manipulação do mundo de blocos são:
• move a onto b: Move o bloco a para cima do bloco b retornando eventuais
blocos que já estiverem sobre a ou b para as suas posições originais.
• move a over b: Coloca o bloco a no topo do monte onde está o bloco b
retornando eventuais blocos que já estiverem sobre a às suas posições originais.
• pile a onto b: Coloca o bloco a juntamente com todos os blocos que estiverem
sobre ele em cima do bloco b, retornando eventuais blocos que já estiverem
sobre b as suas posições originais.
• pile a over b: Coloca o bloco a juntamente com todos os blocos que estiverem
sobre ele sobre o monte que contem o bloco b.
2 Algoritmo e estruturas de dados
Foi criado um TAD, Tipo Abstrato de Dados para representar as listas en-
cadeadas, bem como a quantidade de blocos e de listas encadeadas e também um
apontador para os blocos.
1
5. 2.1 TAD - TBloco
Para representar as listas encadeadas e os blocos foi criado um TAD TBloco.h
typedef struct Bloco ∗ Apontador ; / ∗ Apontador para a estrutura TBloco
∗/
typedef struct
do tipo Bloco
Bloco
int
{
num ;
5 Apontador pProx ; / ∗ Apontador pProx ; ∗/
} TBloco ; / ∗ Blocos : Célula ∗/
typedef struct
{
10 Apontador pPrimeiro ; / ∗ Apontador para o primeiro da lista ∗/
Apontador pUltimo ; / ∗ Apontador para o último da lista ∗/
} TLista ; / ∗ Lista dos blocos ∗/
typedef struct
15 {
∗vetlista
int
TLista ;
tamanho ;
} TVetlista ; / ∗ Estrutura dos vetores de listas encadeadas ∗/
Programa 1: TVetor
2.1.1 Assinatura das funções
Abaixo as assinaturas do TBloco.h.
void Vazio ( TLista ∗) ; / ∗ Assinatura da função Vazio para criar uma
∗/
void int
lista vazia
Criar ( TVetlista ∗,
numero ) ; / ∗ A s s i n a t u r a da f u n ç ã o C r i a r p a r a
∗ / // q n t d e l i s t a e n c a d e a d a s
double
criar lista encadeada
L e h V a z i o ( T L i s t a ∗ ) ; / ∗ A s s i n a t u r a da f u n ç ã o L e h V a z i o p a r a
v e r i f i c a r s e a l i s t a é ou não v a z i a ∗ /
void I n s e r e ( TLista ∗ , int
) ; / ∗ A s s i n a t u r a da f u n ç ã o I n s e r e p a r a inserir
um b l o c o com um c o n t e ú d o a uma p o s i ç ã o a p o n t a d a ∗ /
5 void I m p r i m e ( T L i s t a ∗ ) ; / ∗ A s s i n a t u r a da f u n ç ã o Imprime q u e i m p r i m e
ATENÇÃO ∗ /
Apontador Busca ( T V e t l i s t a ∗ , , Apontador ∗ , int ∗ ) ; / ∗ A s s i n a t u r a da int
função Busca para receber uma lista encadeada e inserir na lista
∗/
void int int
um bloco antes de uma determinada posição
MoveOnto ( T V e t l i s t a ∗, , ) ; / ∗ Assinatura da função Move
∗/
void int int
Onto
PileOver ( TVetlista ∗, , ) ; / ∗ Assinatura da função Pile
∗/
void int int
Over
MoveOver ( T V e t l i s t a ∗, , ) ; / ∗ Assinatura da função Move
∗/
void int int
Over
10 PileOnto ( TVetlista ∗, , ) ; / ∗ Assinatura da função Pile
∗/
void
Onto
Volta ( TVetlista ∗ , Apontador ) ; / ∗ Assinatura da função que volta
os blocos de acordo com as operações de Pile ou Move ∗/
Programa 2: Assinaturas do TBloco.h
2
6. 2.1.2 Função Vazio
Essa função é chamada pela função Criar, criando uma lista encadeada vazia,
fazendo uma alocação dinâmica (malloc) onde o último da lista passa a ser o primeiro
e o primeiro aponta para o próximo bloco da lista recebendo NULL.
void Vazio ( TLista ∗plista ) / ∗ Essa função é chamada pela função Criar ,
criando uma lista encadeada vazia ∗/
sizeof
{
plista −p P r i m e i r o = ( A p o n t a d o r ) m a l l o c ( ( Bloco ) ) ;
plista −p U l t i m o = p l i s t a −p P r i m e i r o ;
5 plista −p P r i m e i r o −p P r o x = NULL ;
}
Programa 3: Vazio
2.1.3 Função LehVazio
Essa função verica se a lista é vazia, caso o primeiro da lista seja igual ao último
ela retornará 1, caso contrário, 0. Obs.: Essa função não foi usada no programa pois
é muito caro chamar uma função, não sendo, portanto, viável a sua utilização uma
vez que pode ser facilmente implementado os comandos contidos nela em outras
funções.
double LehVazio ( TLista ∗plista ) / ∗ Essa função verifica se a lista
encadeada é vazia ∗/
return
{
( plista −p P r i m e i r o == plista −p U l t i m o ) ;
}
Programa 4: LehVazio
2.1.4 Função Insere
Após criar uma lista vazia, usamos essa função para inserir novos elementos
na lista encadeada, mas deve-se alocar dinamicamente (malloc) a memória para
armazenar o elemento.
void I n s e r e ( TLista ∗ plista , int numero ) / ∗ Essa função insere um novo
bloco em uma lista encadeada ∗/
sizeof
{
plista −p U l t i m o −p P r o x = ( A p o n t a d o r ) m a l l o c ( ( TBloco ) ) ; / ∗ plista
−p U l t i m o −p P r o x r e c e b e r e c e b e a q u a n t i d a d e e bytes alocado ∗/
plista −p U l t i m o = p l i s t a − p U l t i m o −p P r o x ;
5 plista −p U l t i m o − num = numero ;
plista −p U l t i m o −p P r o x = NULL ;
}
Programa 5: Insere
2.1.5 Função Volta
Essa função é responsável por voltar os blocos à suas posições originais após as
operações as operações de pilo e onto na execução do programa. Caso o apontador
seja NULL ele retorna, caso contrário, o primeiro da lista aponta para o próximo
3
7. que recebe p, em seguida o último da lista também recebe p. Fará isso até que p
seja NULL, em seguida executará a próxima instrução que seria: p-pProx=NULL.
void Volta ( TVetlista ∗ pbloco , Apontador p) / ∗ Função para voltar os
blocos depois das operações de M V
O E e PILE ∗/
if
{
return
( p= NULL)
=
;
5 pbloco − v e t l i s t a [ p−num ] . p P r i m e i r o −p P r o x=p ;
p b l o c o − v e t l i s t a [ p− num ] . p U l t i m o=p ;
V o l t a ( p b l o c o , p− p P r o x ) ; / ∗ R e c u r s i v i d a d e : E n q u a n t o −
p p P r o x for igual
a NULL a função será chamada , caso contrário , executa a instrução
abaixo : −
p p P r o x=NULL ; ∗/
−
p p P r o x=NULL ;
}
Programa 6: Volta
2.1.6 Função PileOver
Coloca um bloco a juntamente com todos os blocos que estiverem sobre ele sobre
o monte que contem um bloco b.
void PileOver ( TVetlista ∗ pbloco , int A, int B) / ∗ Coloca um bloco a
juntamente com todos os blocos que estiverem sobre ele sobre o
monte que contem um bloco b. ∗/
{
int
Apontador pantA , pantB , pA , pB ;
5
if
listaA , listaB ;
return
(A =
= B)
;
pA=B u s c a ( p b l o c o , A, pantA , l i s t a A ) ;
if
pB=B u s c a ( p b l o c o , B, pantB , l i s t a B ) ;
10
return
( ( pA =
= NULL) | | ( pB =
= NULL) | | ( l i s t a A==l i s t a B ) )
while −
;
( pB p P r o x !=NULL)
{
−
pB=pB p P r o x ;
15 }
−
pB p P r o x=pA ;
pantA −p P r o x=NULL ;
pbloco − v e t l i s t a [ l i s t a B ] . p U l t i m o=pA ;
}
Programa 7: PileOver
2.1.7 Função MoveOver
Coloca um bloco a no topo do monte onde está um bloco b retornando eventuais
blocos que já estiverem sobre a às suas posições originais.
void MoveOver ( T V e t l i s t a ∗ pbloco , int A, int B) / ∗ Coloca um bloco a no
topo do monte onde está um bloco b retornando eventuais blocos
que já estiverem sobre a às suas posições originais ∗/
{
int
Apontador pantA , pantB , pA , pB ;
5 listaA , listaB ;
4
8. if
return
(A =
= B)
;
pA=B u s c a ( p b l o c o , A, pantA , l i s t a A ) ;
if
pB=B u s c a ( p b l o c o , B, pantB , l i s t a B ) ;
10
return
( ( pA =
= NULL) | | ( pB =
= NULL) | | ( l i s t a A==l i s t a B ) )
if −
;
( pA p P r o x !=NULL)
{
−
V o l t a ( p b l o c o , pA p P r o x ) ;
15 −
pA p P r o x=NULL ;
pbloco − v e t l i s t a [ l i s t a A ] . p U l t i m o=pA ;
}
−
pB p P r o x=pA ;
pantA −p P r o x=NULL ;
20 pbloco − v e t l i s t a [ l i s t a B ] . pUltimo −p P r o x=pA ;
}
Programa 8: MoveOver
2.1.8 Função PileOnto
Coloca um bloco a juntamente com todos os blocos que estiverem sobre ele sobre
o monte que contem um bloco b.
void PileOnto ( TVetlista ∗ pbloco , int A, int B) / ∗ Coloca um bloco a
juntamente com todos os blocos que estiverem sobre ele sobre o
monte que contem um bloco b. ∗/
{
int
Apontador pantA , pantB , pA , pB ;
5
if
listaA , listaB ;
return
(A =
= B)
;
pA=B u s c a ( p b l o c o , A, pantA , l i s t a A ) ;
if
pB=B u s c a ( p b l o c o , B, pantB , l i s t a B ) ;
10
return
( ( pA =
= NULL) | | ( pB =
= NULL) | | ( l i s t a A==l i s t a B ) )
if −
;
( pB p P r o x !=NULL)
{
−
V o l t a ( p b l o c o , pB p P r o x ) ;
15 −
pB p P r o x=NULL ;
pbloco − v e t l i s t a [ l i s t a B ] . p U l t i m o=pB ;
}
−
pB p P r o x=pA ;
pantA −p P r o x=NULL ;
20 pbloco − v e t l i s t a [ l i s t a B ] . p U l t i m o=pA ;
}
Programa 9: PileOnto
2.1.9 Função MoveOnto
Move um bloco a para cima do bloco b retornando eventuais blocos que já es-
tiverem sobre a ou b para as suas posições originais.
void MoveOnto ( T V e t l i s t a ∗ pbloco , int A, int B) / ∗ Move um bloco a para
cima do bloco b retornando eventuais blocos que já estiverem
sobre a ou b para as suas posições originais . ∗/
5
9. {
int
Apontador pantA , pantB , pA , pB ;
5
if
listaA , listaB ;
return
(A =
= B)
;
pA=B u s c a ( p b l o c o , A, pantA , l i s t a A ) ;
if
pB=B u s c a ( p b l o c o , B, pantB , l i s t a B ) ;
10
return
( ( pA =
= NULL) | | ( pB =
= NULL) | | ( l i s t a A==l i s t a B ) )
if −
;
( pA p P r o x !=NULL)
{
−
V o l t a ( p b l o c o , pA p P r o x ) ;
15 −
pA p P r o x=NULL ;
pbloco − v e t l i s t a [ l i s t a A ] . p U l t i m o=pA ;
if
}
−
( pB p P r o x !=NULL)
{
20 −
V o l t a ( p b l o c o , pB p P r o x ) ;
−
pB p P r o x=NULL ;
pbloco − v e t l i s t a [ l i s t a B ] . p U l t i m o=pB ;
}
−
pB p P r o x=pA ;
25 pantA −p P r o x=NULL ;
pbloco − v e t l i s t a [ l i s t a B ] . p U l t i m o=pA ;
}
Programa 10: Move Onto
2.1.10 Função Imprime
Função que percorre a lista até que o próximo elemento aponte para NULL,
imprimindo os valores.
void Imprime ( T L i s t a ∗plista ) / ∗ Função que percorre a lista até que o
próximo elemento aponte para NULL, imprimindo os valores ∗/
{
Apontador paux ;
−p P r i m e i r o −p P r o x ;
while
paux= p l i s t a
5 ( paux !=NULL)
{
p r i n t f ( %d , paux− num ) ;
paux = paux −p P r o x ;
}
10 }
Programa 11: Imprime
2.1.11 Função Busca
Essa função verica se o elemento está na lista, caso esteja, teremos como retorno
um ponteiro que no caso representa o elemento, caso contrário, retornará NULL.
Apontador Busca ( T V e t l i s t a ∗ pblocos , int numero , A p o n t a d o r ∗ pant , int ∗ pla
/ ∗ Ponteiro de inteiro pra lista dele ∗/ )
int
{
i ;
Apontador paux ;
6
10. 5 for ( i = 0 ; i p b l o c o s −tamanho ; i ++) / ∗ Laço de repetição até que o i seja
menor que o o número de listas encadeadas ∗/
{
paux=p b l o c o s − v e t l i s t a [
i ] . pPrimeiro −p P r o x ;
∗ p a n t=p b l o c o s − v e t l i s t a
while
[ i ] . pPrimeiro ;
( paux !=NULL)
10
if
{
( paux −num==numero )
{
∗ p l a= i
return
;
paux ;
15 }
∗ p a n t=paux ;
paux=paux− p P r o x ;
}
}
20 ∗ p l a =−1; / ∗ ∗/
return
Lista q contem num q não existe
NULL ;
}
Programa 12: Busca
2.1.12 Função Criar
Essa a função responsável por criar a lista encadeada, ela chama a função Vazio
para criar uma lista vazia e depois chama a função Insere para inserir os elementos
nos blocos.
void Criar ( TVetlista ∗ blocos , int numero ) / ∗ Essa a função responsável
por criar a lista encadeada , ela chama a função Vazio para criar
uma lista vazia e depois chama a função Insere para inserir os
elementos nos blocos ∗/
int
{
sizeof
i ;
blocos − v e t l i s t a = ( T L i s t a ∗ ) m a l l o c ( ( TLista ) ∗ numero ) ;
5 −tamanho = numero ;
for
blocos
( i = 0 ; i numero ; i ++)
{
V a z i o (( b l o c o s − v e t l i s t a [ i ]) ) ;
I n s e r e ( b l o c o s − v e t l i s t a [ i ] , i ) ;
10 }
}
Programa 13: Criar
2.2 Main
Programa Main abaixo:
// −
TP2AEDSI JOHN . c p p : Defines the entry point for the console
application .
#include s t d a f x . h
5 int int
main ( argc , char ∗ argv [ ] )
{
7
11. system ( c o l o r 1b ) ; / ∗ Função responsável por deixar a tela azul : −)
∗/
int
char
k, i =0 , j =0 , tam , qnt , a , b;
10 word [ 2 1 ] [ 5 ] , c a r a c ;
TVetlista pbloco ;
Apontador paux ;
FILE ∗ arqE ; /∗ Arquivo de entrada ∗/
FILE ∗ a r q S ; /∗ Arquivo de saída ∗/
15
a r q E=f o p e n ( a r g v [ 1 ] , r ) ; // a r q E é para leitura do arquivo (r −r e a d e )
a r q S=f o p e n ( a r g v [ 2 ] , w ) ; // a r q S é para escrever no arquiv (w −w r i t e )
/ ∗ Obs . : argc é um inteiro que indica a quantidade de a r g u m e n t o s ∗/
/ ∗ argv é um ponteiro do tipo char onde : argv [ 0 ] é o nome do arquivo
executável ,
20 arqv [ 1 ] é o primeiro argumento , que no caso é entrada . t x t e o arqgv
[2] é o segundo argumento , que no caso é saida . t x t ∗/
−−−−−−−− −−−−−−−−|n n ) ;
if
p r i n t f ( | Mundo Dos Blocos
( ( ! arqE ) | | ( ! a r q S ) ) / ∗ Caso não seja encontrado os arquivos , será
impresso uma mensagem de erro ∗/
p r i n t f ( Erro ao encontrar os arquivos : %s e %s n , a r g v [ 1 ] , a r g v [ 2 ] ) ;
25
else / ∗ Caso contrário , o programa fará as outras instruções ∗/
{
c a r a c=g e t c ( a r q E ) ; / ∗ carac recebe os caracteres contidos no arquivo ,
∗/
while
um por vez
( c a r a c !=EOF) / ∗ Enquando não chegar no final do arquivo : End Of
File as instruções contidas no while serão executadas ∗/
30 {
while
j =0;
( ( c a r a c ! = 3 2 ) ( c a r a c !=EOF) ( c a r a c ! = 1 0 ) ) ∗
/ Em ASCII 32 é o
space e 10 é o 0 que indica o final da string ∗/
{
word [ i ] [ j ]= c a r a c ;
35 j ++;
c a r a c=g e t c ( a r q E ) ; / ∗ carac recebe os caracteres contidos no
arquivo , um por vez ∗/
}
word [ i ] [ j ]= ' 0 ' ;
if
i ++;
40 ( ( c a r a c ==10) | | ( c a r a c= EOF) )
= / ∗ Caso carac seja igual ao fim da
string , que no caso é o final da linha ou chegue no final do
arquivo qnt recebe a conversão de string para inteiro ,
convertendo −a em numeral ∗/
if
{
( ( word [ 0 ] [ 0 ] 4 8 ) (word [ 0 ] [ 0 ] 5 8 ) )
{
q n t= a t o i ( word [ 0 ] ) ;
45 C r i a r ( p b l o c o , q n t ) ; / ∗ qnt é a quantidade de blocos a serem
criados lidos do arquivo de entrada ∗/
else
}
/ ∗ Com isso será pulada a linha ∗/
if
{
( ( word [ 1 ] [ 0 ] 4 8 ) (word [ 1 ] [ 0 ] 5 8 ) )
50
if
a= a t o i ( word [ 1 ] ) ;
( ( word [ 3 ] [ 0 ] 4 8 ) (word [ 3 ] [ 0 ] 5 8 ) )
b= a t o i ( word [ 3 ] ) ;
8
12. if ( word [ 0 ] [ 0 ] = = 'm ' )
if
{
55 ( ( word [ 2 ] [ 0 ] = = ' o ' ) (word [ 2 ] [ 1 ] = = ' v ' ) ) / ∗ Será lido cada
caracter até montar uma string , nesse caso , se for 'm'=
move e o v= o v e r , será executada a função MoveOver ∗/
else
MoveOver( p b l o c o , a , b) ;
/ ∗ Do contrário , MoveOnto ∗/
MoveOnto( p b l o c o , a , b) ;
else if
}
60 ( word [ 0 ] [ 0 ] = = ' p ' )
if
{
( ( word [ 2 ] [ 0 ] = = ' o ' ) (word [ 2 ] [ 1 ] = = ' v ' ) ) / ∗ Será lido cada
caracter até montar uma string , nesse caso , se for ' p '=
pilee e o v= o v e r , será executada a função PileOver ∗/
else
P i l e O v e r ( p b l o c o , a , b) ;
/ ∗ Do contrário , PileOnto ∗/
65 P i l e O n t o ( p b l o c o , a , b) ;
else if
}
( word [ 0 ] [ 0 ] = = ' q ' ) / ∗ Quando or lido , por final , o
caracter 'q ' , implicará no final das intruções contidas
no arquivo , então , a partir de agora o programa fará as
operações , gerando um arquivo de saída com a solução do
problema proposto , ou seja , com o resultado esperado ∗/
for
{
( j = 0 ; j q n t ; j ++) / ∗ Agora a lista será percorrida até que
o próximo elemento aponte para NULL, gravando no
arquivo de saída o resultado esperado ∗/
70 {
paux=p b l o c o . v e t l i s t a [ j ] . p P r i m e i r o −p P r o x ;
while
f p r i n t f ( arqS , %d : , j ) ;
( paux !=NULL)
{
75 f p r i n t f ( arqS , %d , paux −
num ) ;
paux = paux −p P r o x ;
}
f p r i n t f ( arqS , n ) ;
}
80 f c l o s e ( arqE ) ; / ∗ Por final , arqE e arqS são fechados ∗/
f c l o s e ( arqS ) ;
else
}
{
85 p r i n t f ( Não foi localizado o [ q u i t ] n ) ;
}
}
i =0;
}
90 c a r a c=g e t c ( a r q E ) ;
}
p r i n t f ( nArquivo de saida , %s , gerado com s u c e s s o ! ! ! n , a r g v [ 2 ] ) ;
/ ∗ Por final , caso tudo ocorra bem , será impresso essa msg
informando ao usuário que o arquivo de saida foi gerado com
sucesso com o resultado esperado por ele ∗/
}
95
return
s y s t e m ( PAUSE ) ;
0;
9
13. }
Programa 14: Main
2.2.1 Função STDAFX.H
No stdafx.h foi incluido todos os arquivos .h que serão usados pelo programa, os
.h estão listados no programa abaixo:
#pragma once
#include
#include
t a r g e t v e r . h
#include
s t d i o . h
5
#include
t c h a r . h
#include
s t d l i b . h
TBloco . h
10 / ∗ Todas as eferências adicionais dos programas foram colocadas no
stdafx .h ∗/
Programa 15: Stdafx
3 Análise de complexidade dos algoritmos
Considerando todas por comparação e no pior caso:
3.1 Função Volta
T (n) = 1 + T (n)T (0) = 0 (1)
O(n)
3.2 Função PileOver
f (n) = 5 (2)
O(5)
3.3 Função MoveOver
f (n) = 5 (3)
O(5)
10
15. 4 Testes
Alguns testes com o programa:
Argumentos: entrada.txt saida.txt
Figura 1: Argumentos
Comando: TP2AEDSI-JOHN.exe entrada.txt johnnatan.txt
Figura 2: Comando
12
16. Arquivo de entrada: entrada.txt
Figura 3: Arquivo de entrada
Execução do comando
Figura 4: Execuxão do comando
Arquivo de saída: johnnatan.txt
13
17. Figura 5: Arquivo de saída
5 Conclusão
Neste trabalho foram revistos conceitos sobre alocação dinâmica, TAD(Tipos
Abstratos de Dados), listas encadeadas, argumentos argv, argc, pratica de edição
A
de textos em LTEX, bem como o melhor entendimento sobre ordem de complexidade
e maturidade na linguagem C. A maior diculdade foi a abstração para a resolução
do problema proposto, mas, uma vez que entendido o que se pede, tornou-se simples
a implementação. Muito dos algoritmos são extraídos de [?].
Referências
[1] David Menotti Algoritmos e Estruturas de Dados I: Listas En-
cadeadas. http://www.decom.ufop.br/prof/menotti/aedI092/slides/
aula09-10-ListaEnc.ppt, visitado em 03/10/2009.
[2] Márcio Santi Wikipédia, 2009 http://pt.wikipedia.org/wiki/Lista_
ligada/, visitado em 01/10/2009.
[3] Aldrovando Luís Azeredo Araújo Os Argumentos argc e argv, 1999. http://www.
mtm.ufsc.br/~azeredo/cursoC/aulas/c790.html, visitado em 30/08/2009.
[4] Paulo Feolof Projeto de Algoritmos: Listas Encadeadas, 2009 http://www.
ime.usp.br/~pf/algoritmos/aulas/lista.html, visitado em 28/09/2009.
14