Anda di halaman 1dari 66

Edwar Saliba J nior

Novembro de 2007
















Estruturas de Dados

Notas de Aula











Faculdade de Tecnologia INED
Belo Horizonte - MG

Sumrio

1. Nota: ................................................................................................................................... 3
2. Tipos de Dados e Tipo Abstrato de Dados ......................................................................... 4
2.1. Comuns: ....................................................................................................................... 4
2.2. Modificados: ................................................................................................................ 4
2.3. Tipo Abstrato de Dados (TDA): .................................................................................. 4
2.4. Tipo Enumerado: ......................................................................................................... 5
2.5. Constantes: ................................................................................................................... 6
2.6. Variveis (Locais e Globais):....................................................................................... 7
3. Estruturas de Dados (Registros) ....................................................................................... 10
3.1. Inicializando Estruturas ............................................................................................. 12
4. Exerccios ......................................................................................................................... 14
5. Ponteiros (ou Apontadores) .............................................................................................. 16
5.1. Por que ponteiros so usados? ................................................................................... 16
5.2. Por que evitar o uso de ponteiros? ............................................................................. 16
5.3. Utilizando Ponteiros................................................................................................... 17
5.4. Exemplo de Utilizao de Ponteiros .......................................................................... 17
5.5. Outros Exemplos de Utilizao de Ponteiros............................................................. 18
5.6. Exerccios ................................................................................................................... 22
6. Listas, Filas e Pilhas atravs de Arranjos ......................................................................... 23
6.1. Lista ........................................................................................................................... 23
6.2. Pilha ........................................................................................................................... 27
6.3. Fila ............................................................................................................................. 30
6.4. Exerccios ................................................................................................................... 33
7. Lista, Pilha e Fila atravs de Ponteiros ............................................................................. 37
7.1. Lista ........................................................................................................................... 37
7.1.1. Lista Duplamente Encadeada ............................................................................. 41
7.2. Pilha ........................................................................................................................... 42
7.3. Fila ............................................................................................................................. 45
7.4. Exerccio .................................................................................................................... 47
8. rvores de Pesquisa ......................................................................................................... 48
8.1. rvores Binrias de Pesquisa Sem Balanceamento ................................................... 48
8.2. rvores Binrias de Pesquisa Com Balanceamento .................................................. 53
8.3. rvores SBB (Symmetric Binary B-trees) ................................................................ 54
8.3.1. Manuteno da rvore SBB ................................................................................ 56
8.4. Exerccio .................................................................................................................... 65
9. Bibliografia ....................................................................................................................... 66

eddiesaliba@yahoo.com ICQ-45923544 3
1. Nota:

Os cdigos em Linguagem C apresentados neste trabalho foram criados utilizando a
ferramenta conhecida por Dev-C++ verso 4.9.9.2. Esta ferramenta poder ser
adquirida gratuitamente no site abaixo:

http://www.bloodshed.net/devcpp.html


eddiesaliba@yahoo.com ICQ-45923544 4

2. Tipos de Dados e Tipo Abstrato de Dados

Segundo Mizrahi (1990) e o Centro Tecnolgico de Mecatrnica de Caxias do
Sul (1997), a Linguagem C possui cinco tipos bsicos de dados. Seus tipos,
tamanho, intervalos e uso podem ser vistos abaixo:


2.1. Comuns:

Tipo Tamanho Intervalo Uso
char 1 byt e - 128 a 127 Nmero muito pequeno e caracter ASCII
i nt 2 byt es - 32768 a 32767 Contador, controle de lao
f l oat 4 byt es 3. 4e- 38 a 3. 4e38 Real (preciso de 7 dgitos)
doubl e 8 byt es 1. 7e- 308 a 1. 7e308 Cientfico (preciso de 15 dgitos)
voi d 0 byt es SemVal or Ponteiro para nulo

2.2. Modificados:

Tipo Tamanho (bytes) Intervalo
unsi gned char 1 0 a 255
unsi gned i nt 2 0 a 65 535
l ong i nt 4 - 2. 147. 483. 648 a 2. 147. 483. 647
unsi gned l ong i nt 4 0 a 4. 294. 967. 295
l ong doubl e 10 3. 4e- 4932 a 1. 1e4932


2.3. Tipo Abstrato de Dados (TDA):

De acordo com Tenenbaum et al. (1995), o mecanismo conhecido como TDA,
uma ferramenta muito til para especificar as propriedades lgicas de um tipo de
dado. Fundamentalmente, um tipo de dado significa um conjunto de valores e uma
seqncia de operaes que podem ser realizadas sobre estes valores.
Para deixar mais claro esse assunto ser tratado mais adiante, em nosso
curso, quando estivermos definindo, com o auxlio de ponteiros, os TDA's: Pilha, lista
e fila e suas respectivas operaes.




eddiesaliba@yahoo.com ICQ-45923544 5

2.4. Tipo Enumerado:

O tipo enumerado muito utilizado para facilitar a criao e, principalmente o
entendimento do programa. Vamos supor a seguinte situao: Um cliente pediu-nos
que desenvolvssemos um programa onde o usurio digite um nmero entre 1 e 7
(inclusive) e, o software retorne o dia da semana correspondente. Apesar de muito
simples, didaticamente falando este programa excelente para o que queremos
demonstrar.
No cdigo a seguir, voc poder observar que, para atender a solicitao de
nosso cliente, foi criado um software que solicita a entrada de um nmero de 1 a 7 e
logo em seguida, atravs de uma estrutura switch, o programa devolve o dia da
semana ao usurio, de acordo com o nmero digitado. Por exemplo, se o usurio
digitar o nmero 3 (trs), automaticamente aparecer na tela a palavra tera-feira.
Agora, se observarmos atentamente a estrutura switch, veremos que ao
invs de testarmos a varivel num com nmeros (1, 2, 3 e etc.), estamos testando
com as iniciais dos dias da semana (seg, ter, qua e etc.).
Isto foi possvel devido criao de um tipo enumerado chamado
dias_semana e, logicamente, uma varivel chamada dia do tipo dias_semana.
Ao criarmos um tipo enumerado na Linguagem C, temos que ter em mente
que todas as palavras que comporem o tipo correspondero a um nmero inteiro e
seqencial, iniciado em zero. No exemplo abaixo, dom vale zero, seg vale um,
ter vale dois e assim por diante.


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

typedef enum { dom, seg, ter, qua, qui, sex, sab } dias_semana;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
di as_semana di a;
i nt num;

cout << " Di gi t e umnmer o de 1 a 7: " ;
ci n >> num;

cout << " \ n\ n" ;

swi t ch ( num- 1) {
case dom:
cout << " Domi ngo" ;
br eak;
case seg:
cout << " Segunda- f ei r a" ;
br eak;
case ter:
cout << " Ter a- f ei r a" ;
br eak;
case qua:

eddiesaliba@yahoo.com ICQ-45923544 6
cout << " Quar t a- f ei r a" ;
br eak;
case qui:
cout << " Qui nt a- f ei r a" ;
br eak;
case sex:
cout << " Sext a- f ei r a" ;
br eak;
case sab:
cout << " Sbado" ;
}

cout << " \ n\ n" ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

2.5. Constantes:

A declarao de valores constantes pode ser efetuada de duas formas. A primeira
delas usando a diretiva do pr-processador conhecida como #define. E a segunda
usando a palavra reservada const.

No exemplo a seguir, poderemos verificar que sero criadas duas constantes atravs do uso
da diretiva #define. Uma constante se chama INICIO e tem seu valor igual a 1 (um) e a
outra constante tem o nome FIM e tem seu valor igual a 1000 (mil).

O software apresentado a seguir imprime no vdeo os nmeros de 1 a 1000:


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

#define INICIO 1
#define FIM 1000

usi ng namespace st d;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
i nt i ;

f or ( i = I NI CI O; i <= FI M; i ++)
cout << " \ n" << i ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


No exemplo a seguir, poderemos verificar que sero criadas duas constantes atravs do uso
da palavra reservada const. Como no software anterior, uma constante se chama INICIO e
tem seu valor igual a 1 (um) e a outra constante tem o nome FIM e tem seu valor igual a
1000 (mil).


eddiesaliba@yahoo.com ICQ-45923544 7
Contudo, podemos observar no cdigo abaixo que, diferentemente de quando usamos
define, agora, para criar uma constante usando a palavra reservada const, faz-se
necessrio tambm a declarao do tipo da constante. No exemplo a seguir nossas
constantes so do tipo inteiro (int).

O software abaixo apresenta no vdeo os nmeros de 1 a 1000:


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

const int INICIO = 1,
FIM = 1000;

usi ng namespace st d;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
i nt i ;

f or ( i = I NI CI O; i <= FI M; i ++)
cout << " \ n" << i ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


2.6. Variveis (Locais e Globais):

Uma varivel pode ser declarada localmente a uma funo, ou global a todas as
funes de um mdulo do programa.

Quando declarada dentro da funo, a varivel tem seu escopo limitado prpria
funo onde foi declarada.
No software a seguir, veremos que sero declaradas duas variveis A e B, ambas
do tipo inteiro. O objetivo deste software simplesmente: Receber dois valores inteiros via
teclado, somar os dois valores recebidos e imprimir o total da soma no monitor.
As variveis A e B, tm seus escopos iniciados aps o sinal de ponto-e-vrgula
que completam suas declaraes, at o final da funo main.

Vejamos um exemplo de declarao de variveis locais.


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
int A = 0,
B = 0;

cout << " Di gi t e o pr i mei r o val or : " ;
ci n >> A;

eddiesaliba@yahoo.com ICQ-45923544 8

cout << " \ nDi gi t e o segundo val or : " ;
ci n >> B;

cout << " \ n\ nO r esul t ado da soma: " << A + B << " \ n\ n\ n" ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}



Quando declarada fora da funo, a varivel tem seu escopo limitado ao mdulo
onde foi declarada, podendo se estender a outros mdulos, desde que estes referenciem o
mdulo onde a varivel global est declarada, atravs da diretiva #include, da mesma
forma que fazemos com as bibliotecas de funes.

Se observarmos atentamente o software a seguir, veremos que ele faz exatamente o que o
software anterior fazia.

Contudo, poderemos notar tambm, que neste novo software, no temos apenas uma nica
funo declarada. Temos duas funes. A primeira funo se chama soma e a segunda
funo se chama main (que obrigatria para todos os programas construdos em
Linguagem C).

Poderemos observar tambm que, as variveis A e B (ambas do tipo inteiro), so
declaradas antes da declarao das funes, o que as torna variveis globais. E como
veremos no exemplo a seguir, ambas as funes declaradas utilizam as mesmas variveis
globais, ou seja, A e B.

Vejamos um exemplo de declarao de variveis globais.


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

int A = 0,
B = 0;

i nt soma ( ) {
r et ur n ( A + B) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
cout << " Di gi t e o pr i mei r o val or : " ;
ci n >> A;

cout << " \ nDi gi t e o segundo val or : " ;
ci n >> B;

cout << " \ n\ nO r esul t ado da soma : " << soma ( ) << " \ n\ n\ n" ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

eddiesaliba@yahoo.com ICQ-45923544 9


Note que no software acima, nem a funo soma e tampouco a funo main declaram
variveis locais.



IMPORTANTE:

Apesar de prtico, o uso de variveis globais no considerado uma boa prtica de
programao, pois, dificulta extremamente a anlise e o entendimento do software.
Portanto, evite ao mximo a utilizao desta prtica.

Saiba que 99,9% das variveis Globais, podem ser facilmente substitudas por
variveis locais.



Para provarmos o que acabamos de dizer, vamos refazer o software anterior eliminando as
variveis globais.

Veja no exemplo a seguir que a funo soma no deixou de existir, contudo, agora ela
possui duas variveis inteiras PrimeiroValor e SegundoValor (que por estarem declaradas
na assinatura da funo levam o nome de parmetros) que recebero os valores coletados
pela funo principal (main) atravs das variveis A e B.

Em seguida a funo soma far a soma dos valores a ela passados e devolver o
resultado funo que a chamou (main).

Vejamos:

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

int soma (int PrimeiroValor, int SegundoValor) {
return (PrimeiroValor + SegundoValor);
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
i nt A = 0,
B = 0;

cout << " Di gi t e o pr i mei r o val or : " ;
ci n >> A;

cout << " \ nDi gi t e o segundo val or : " ;
ci n >> B;

cout << " \ n\ nO r esul t ado da soma : " << soma (A,B) << " \ n\ n\ n" ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


eddiesaliba@yahoo.com ICQ-45923544 10

3. Estruturas de Dados (Registros)

De acordo com Mizrahi (1990), uma estrutura de dados um conjunto de variveis,
possivelmente de tipos diferentes, agrupadas sob um nico nome. Estas estruturas tambm
so conhecidas por registros.
Uma estrutura um tipo de dado cujo formato definido pelo programador.

Exemplos de Estruturas Simples:

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
struct endereco {
char logradouro[50];
int numero;
char complemento[15];
char bairro[30];
char cidade[100];
char estado[40];
char cep[8];
};

struct endereco end_cliente1;
struct endereco end_cliente2;

st r cpy ( end_cl i ent e1. l ogr adour o, " Rua Ant ni o de Souza" ) ;
end_cl i ent e1. numer o = 18;
st r cpy ( end_cl i ent e1. compl ement o, " Apt o 102" ) ;
st r cpy ( end_cl i ent e1. bai r r o, " Bel a Vi st a" ) ;
st r cpy ( end_cl i ent e1. ci dade, " Bel o Hor i zont e" ) ;
st r cpy ( end_cl i ent e1. est ado, " Mi nas Ger ai s" ) ;
st r cpy ( end_cl i ent e1. cep, " 30810540" ) ;

st r cpy ( end_cl i ent e2. l ogr adour o, " Rua Al f r edo Bal ei a" ) ;
end_cl i ent e2. numer o = 83;
st r cpy ( end_cl i ent e2. compl ement o, " Apt o 303" ) ;
st r cpy ( end_cl i ent e2. bai r r o, " Li nda Vi st a" ) ;
st r cpy ( end_cl i ent e2. ci dade, " Bel o Hor i zont e" ) ;
st r cpy ( end_cl i ent e2. est ado, " Mi nas Ger ai s" ) ;
st r cpy ( end_cl i ent e2. cep, " 30830503" ) ;

cout << " Logr adour o: " << end_cl i ent e1. l ogr adour o;
cout << " \ nNmer o: " << end_cl i ent e1. numer o;
cout << " \ nCompl ement o: " << end_cl i ent e1. compl ement o;
cout << " \ nBai r r o: " << end_cl i ent e1. bai r r o;
cout << " \ nCi dade: " << end_cl i ent e1. ci dade;
cout << " \ nEst ado: " << end_cl i ent e1. est ado;
cout << " \ nCEP: " << end_cl i ent e1. cep;

cout << " \ n\ n" ;

cout << " Logr adour o: " << end_cl i ent e2. l ogr adour o;

eddiesaliba@yahoo.com ICQ-45923544 11
cout << " \ nNmer o: " << end_cl i ent e2. numer o;
cout << " \ nCompl ement o: " << end_cl i ent e2. compl ement o;
cout << " \ nBai r r o: " << end_cl i ent e2. bai r r o;
cout << " \ nCi dade: " << end_cl i ent e2. ci dade;
cout << " \ nEst ado: " << end_cl i ent e2. est ado;
cout << " \ nCEP: " << end_cl i ent e2. cep;

cout << " \ n\ n\ n" ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

No cdigo acima, nota-se claramente que, para declararmos uma estrutura ou registro em
Linguagem C, utilizamos a palavra reservada struct, seguido do nome que queremos dar
para a estrutura, este, muitas vezes chamado de etiqueta e que em nosso exemplo
endereco.

O exemplo apresentado mostra uma das formas de se declarar e utilizar uma estrutura
dentro de um programa escrito em Linguagem C, contudo, o leitor poder encontrar no dia-a-
dia, cdigos como este com algumas diferenas. O que no alterar o resultado final.

Veja a seguir outros exemplos de maneiras diferentes de se fazer a mesma coisa:

- No cdigo abaixo, podemos notar que a palavra reservada struct no foi utilizada na
declarao das variveis end_cliente1 e end_cliente2.


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
st r uct ender eco {
char l ogr adour o[ 50] ;
i nt numer o;
char compl ement o[ 15] ;
char bai r r o[ 30] ;
char ci dade[ 100] ;
char est ado[ 40] ;
char cep[ 8] ;
};

endereco end_cliente1, end_cliente2;

st r cpy ( end_cl i ent e1. l ogr adour o, " Rua Ant ni o de Souza" ) ;
end_cl i ent e1. numer o = 18;
st r cpy ( end_cl i ent e1. compl ement o, " Apt o 102" ) ;

.
.
.

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


eddiesaliba@yahoo.com ICQ-45923544 12

- No cdigo a seguir, veremos que as variveis end_cliente1 e end_cliente2, foram
declaradas antes de finalizarmos a declarao da estrutura, e ainda, podemos notar tambm
que esta estrutura no tem etiqueta, ou seja, foi omitido o nome da estrutura; apenas foram
criadas duas variveis end_cliente1 e end_cliente2 do tipo desta estrutura.

No h necessidade de voc dar um nome para a estrutura, a no ser que voc tenha que
declarar, em outras partes do cdigo, outras variveis desta estrutura.


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
st r uct {
char l ogr adour o[ 50] ;
i nt numer o;
char compl ement o[ 15] ;
char bai r r o[ 30] ;
char ci dade[ 100] ;
char est ado[ 40] ;
char cep[ 8] ;
} end_cliente1, end_cliente2;

st r cpy ( end_cl i ent e1. l ogr adour o, " Rua Ant ni o de Souza" ) ;
end_cl i ent e1. numer o = 18;
st r cpy ( end_cl i ent e1. compl ement o, " Apt o 102" ) ;

.
.
.

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


3.1. Inicializando Estruturas

Uma estrutura poder ser inicializada facilmente. Basta seguir o exemplo abaixo:


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;


i nt mai n( i nt ar gc, char *ar gv[ ] )
{
st r uct l i vr o {
i nt codi go;
char nome[ 40] ;
};

eddiesaliba@yahoo.com ICQ-45923544 13

livro liv1 = { 1, "Algoritmos e Tcnicas de Programao" };
livro liv2 = { 2, "Estruturas de Dados Usando C" };

cout << " Cdi go: " << l i v1. codi go;
cout << " \ nNome: " << l i v1. nome;

cout << " \ n\ n" ;

cout << " Cdi go: " << l i v2. codi go;
cout << " \ nNome: " << l i v2. nome;

cout << " \ n\ n" ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

Observe que a disposio dos valores passados para inicializao das variveis liv1 e
liv2, seguem a seqncia de variveis que compem a estrutura livro, ou seja, primeiro
um valor inteiro e depois um valor string.



eddiesaliba@yahoo.com ICQ-45923544 14

4. Exerccios

1) Escreva um software onde seja solicitado do usurio, que entre com 30 valores
reais quaisquer. Armazene estes valores num vetor. Em seguida, aplique um
aumento de 20% a todos os valores digitados pelo usurio, armazenando estes
novos valores num segundo vetor, na ordem inversa qual foi digitada. Crie um
terceiro vetor para receber, em suas posies, o somatrio do valor contido nas
respectivas posies dos dois vetores anteriores. Apresente os resultados obtidos
nas posies do terceiro vetor. Faa uso de constantes para delimitar o valor
mximo e mnimo dos vetores, para a aplicao do percentual de reajuste e em
tudo mais que voc julgar ser til.

2) Modifique as constantes criadas no software anterior para que o programa
anterior solicite do usurio, que entre com 100 valores reais quaisquer. Armazene
estes valores num vetor. Em seguida, aplique um aumento de 23,7% a todos os
valores digitados pelo usurio, armazenando este novo resultado num segundo
vetor, na ordem inversa a qual foi digitada. Crie um terceiro vetor para receber,
em suas posies, o somatrio do valor contido nas respectivas posies dos
dois vetores anteriores. Apresente os resultados obtidos nas posies do terceiro
vetor.

Ateno! Para resoluo deste problema extremamente importante que voc s
modifique as constantes criadas no exerccio 1. Se voc tiver que modificar algo
mais alm das constantes, altere a soluo do exerccio 1 para que ela passe a
aceitar o tipo de alteraes propostas neste exerccio.

3) Construa um software que simule uma calculadora com as seguintes operaes:
Soma, subtrao, diviso, multiplicao e potenciao. O usurio da calculadora
dever entrar sempre com dois valores. Em seguida o usurio dever escolher a
operao a ser efetuada nos valores que foram digitados e o programa dever
apresentar: os nmeros digitados, a operao escolhida e o resultado da
operao.

a. Resolva o exerccio 3 utilizando uma nica funo (main).

b. Resolva o exerccio 3 utilizando uma funo para cada operao criada
e tambm variveis globais.

c. Resolva o exerccio 3 utilizando uma funo para cada operao
criada, porm, sem utilizao de variveis globais.


4) Construa um software para cadastrar livros. Os dados que devero ser
armazenados de cada livro so: Cdigo, ttulo do livro, nome do autor, data de
publicao, edio, cidade e editora. Utilize a estrutura de dados conhecida como

eddiesaliba@yahoo.com ICQ-45923544 15
registro para definir os dados que sero armazenados. Seu software dever
permitir que o usurio cadastre 3 livros.

5) Construa um software para cadastro de veculos. Os dados que devero ser
armazenados sobre veculos so: Marca, modelo, ano de fabricao, cor e placa.
Use a estrutura conhecida como registro para compor os dados sobre o veculo.
Seu software dever ser capaz de armazenar os dados de 50 veculos. Para isto,
use a estrutura registro combinada com um vetor. O software dever permitir a
entrada de quantos veculos o usurio quiser cadastrar. Crie um flag para que o
usurio possa interromper o cadastro a qualquer momento (desde que no esteja
no meio de um cadastro de veculo). Crie uma opo para o usurio visualizar os
veculos cadastrados. No se esquea de usar constantes para nmeros que se
repetem (em um mesmo contexto).

6) Construa um software para cadastro de alunos. Os dados que devero ser
armazenados sobre alunos so: Matrcula, nome, idade, sexo e curso. Use a
estrutura conhecida como registro para compor os dados sobre o aluno. Seu
software dever ser capaz de armazenar os dados de 100 alunos. Para isto, use
a estrutura registro combinada com uma matriz 10 x 10. O software dever
permitir a entrada de quantos alunos o usurio quiser cadastrar. Crie um flag para
que o usurio possa interromper o cadastro a qualquer momento (desde que no
esteja no meio de um cadastro de aluno). Crie uma opo para o usurio
visualizar os alunos cadastrados.

7) Crie um outro programa baseado no anterior (Exerccio 6), onde se possa
armazenar, alm dos dados do aluno, tambm o seu endereo. Para isto crie
uma nova estrutura chamada endereco que conter os campos: Logradouro,
nmero, bairro e cidade. Feito isto, dentro da estrutura criada para armazenar os
dados do aluno crie uma nova varivel chamada ender do tipo endereco. O
restante do programa dever respeitar o que pede o exerccio 6. Fazendo isto
voc estar utilizando estruturas aninhadas.

eddiesaliba@yahoo.com ICQ-45923544 16
5. Ponteiros (ou Apontadores)

Segundo Mizrahi (1990), uma das caractersticas mais poderosas oferecidas
pela Linguagem C, a utilizao de ponteiros. Os ponteiros so vistos pela maioria
das pessoas como um dos tpicos mais difceis de qualquer linguagem de
programao.
Um ponteiro, ainda segundo Mizrahi (1990), proporciona um modo de acesso
as variveis sem referenci-las diretamente. O mecanismo usado para isto o
endereo da varivel na memria do computador. De fato, o endereo age como
intermedirio entre a varivel e o programa que a acessa.
Mizrahi (1990) simplifica a explicao de ponteiros dizendo que: Um ponteiro
pode ser entendido como sendo uma representao simblica de um endereo da
memria do computador.

5.1. Por que ponteiros so usados?

Ponteiros so usados em situaes em que a passagem de valores difcil ou
indesejvel. A seguir, Mizrahi (1990) lista algumas razes para o uso de ponteiros:

a) Fornecem maneiras com as quais as funes podem realmente modificar os
argumentos que recebem.
b) Para passar matrizes e strings mais convenientemente de uma funo para
outra, isso , usa-los ao invs de matrizes.
c) Para manipular matrizes mais facilmente atravs da movimentao de
ponteiros para elas (ou parte delas), em vez de a prpria matriz;
d) Para criar estruturas de dados complexas, como listas encadeadas e rvores
binrias, onde uma estrutura de dados deve conter referncias sobre outra.
e) Para comunicar informaes sobre memria, como na funo malloc() que
retorna a localizao de memria livre atravs do uso de ponteiro.
f) Uma outra razo importante para o uso de ponteiros que notaes de
ponteiros compilam mais rapidamente tornando o cdigo mais eficiente.

5.2. Por que evitar o uso de ponteiros?

O uso de ponteiros pelas linguagens de programao foi muito debatido e
questionado por muitos que eram contra e a favor de seu uso.
Contudo, podemos citar alguns bons motivos para se evitar o uso de ponteiros
mesmo que a linguagem de programao que voc est utilizando, o provenha com
recursos para utilizao dos mesmos.
O uso de ponteiros:

a) Torna a programao de um cdigo qualquer muito mais complexa.
b) Dificulta o entendimento de um cdigo.
c) Dificulta a manuteno de um cdigo, principalmente se no foi voc quem o
escreveu, pois, ao tornar o entendimento mais difcil, consequentemente, o
uso de ponteiros torna a manuteno do cdigo, tambm, mais difcil.

eddiesaliba@yahoo.com ICQ-45923544 17
d) A eficincia que se ganha no cdigo com o uso de ponteiros, torna-se
irrelevante diante da velocidade das mquinas atuais. E tambm, claro, se o
cdigo for bem escrito usando as estruturas alternativas.
e) As linguagens de programao mais recentes no mercado atualmente no
provem recursos para a utilizao de ponteiros. (Ex.: J ava e .Net).

5.3. Utilizando Ponteiros

Sabemos como fazer para declaramos uma varivel normal, do tipo inteiro por
exemplo, ou seja:

int NUM;

O cdigo acima uma declarao tpica de uma varivel de nome NUM do tipo
inteiro em Linguagem C.

A declarao de ponteiros tem, segundo Mizrahi (1990), um sentido diferente da de
uma varivel normal, pois, a declarao:

Int *PNUM;

Declara que *PNUM do tipo inteiro e um ponteiro, isto PNUM conter
endereos de variveis do tipo inteiro, e no valores armazenados (como nas
variveis normais).


5.4. Exemplo de Utilizao de Ponteiros


O software abaixo, adiciona 3 ao valor da varivel X, sem a sua utilizao
direta.

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
i nt X = 10;
i nt *PX;

PX = &X;

cout << " O val or da var i vel X : " << X;

*PX = *PX + 3;

cout << " \ n\ nO val or da var i vel X : " << X << " \ n\ n" ;


eddiesaliba@yahoo.com ICQ-45923544 18
syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


Uma rpida explicao sobre o software acima:

Foram criadas duas variveis: X e PX, ambas do tipo inteiro.

Contudo, quando fizemos a seguinte declarao:

Int *PX;

Na verdade fizemos a declarao de um ponteiro para uma varivel do tipo inteiro, e
no uma declarao de uma varivel do tipo inteiro.

Em seguida veio a declarao de atribuio de valores:

PX = &X;

Nesta declarao, no estamos passando para PX o valor armazenado em X (que
at ento era 10). Ao contrrio, estamos passando o endereo da memria da
mquina (computador) ocupado pela varivel X. Ou seja, acabamos de criar um
ponteiro, de nome PX, para a varivel X.

Em seguida foi impresso no vdeo o valor da varivel X (at aqui, 10).

Logo feita a seguinte declarao:

*PX = *PX + 3;

A atribuio acima parece estar adicionando ao valor de PX o valor 3. Contudo, PX
no uma varivel, e sim um ponteiro, que aponta para o endereo da varivel X.
Neste caso, como se estivssemos atribuindo o valor 3 para a varivel X, pois,
apesar de no estarmos trabalhando diretamente com a varivel X, estamos
trabalhando com o valor contido na posio de memria que a varivel X ocupa.

E para finalizar, ao imprimirmos novamente o valor da varivel X no vdeo, veremos
que este ser igual a 13, pois, seu valor foi acrescido de 3 atravs da utilizao de
uma operao de adio utilizando o ponteiro PX.


5.5. Outros Exemplos de Utilizao de Ponteiros

O software a seguir faz a utilizao de ponteiros, atravs de variveis globais,
para simular uma calculadora de quatro operaes. Passando os valores atravs de
ponteiros para a respectiva funo solicitada pelo usurio.

#i ncl ude <cst dl i b>

eddiesaliba@yahoo.com ICQ-45923544 19
#i ncl ude <i ost r eam>

usi ng namespace st d;

int *P1Valor, *P2Valor;

i nt Adi cao ( ) {
r et ur n ( *P1Valor + *P2Valor) ;
}

i nt Subt r acao ( ) {
r et ur n ( *P1Valor - *P2Valor) ;
}

f l oat Di vi sao ( ) {
r et ur n ( *P1Valor / *P2Valor) ;
}

i nt Mul t i pl i cacao ( ) {
r et ur n ( *P1Valor * *P2Valor) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
int PrimeiroValor, SegundoValor;
i nt opcao;

P1Valor = &PrimeiroValor;
P2Valor = &SegundoValor;

cout << " Ent r e como pr i mei r o val or : " ;
ci n >> PrimeiroValor;
cout << " \ nEnt r e como segundo val or : " ;
ci n >> SegundoValor;

cout << " \ n\ nEscol ha a oper ao a ser ef et uada comos val or es
di gi t ados: " ;
cout << " \ n 1 - Adi o" ;
cout << " \ n 2 - Subt r ao" ;
cout << " \ n 3 - Di vi so" ;
cout << " \ n 4 - Mul t i pl i cao" ;
cout << " \ n\ n\ n Opo: " ;
ci n >> opcao;

swi t ch ( opcao) {
case 1:
cout << " \ n\ nO val or da Adi o : " << Adicao ();
br eak;
case 2:
cout << " \ n\ nO val or da Subt r ao : " << Subtracao ();
br eak;
case 3:
cout << " \ n\ nO val or da Di vi so : " << Divisao ();
br eak;
case 4:
cout << " \ n\ nO val or da Mul t i pl i cao : " << Multiplicacao ();
}

cout << " \ n\ n\ n" ;


eddiesaliba@yahoo.com ICQ-45923544 20
syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


O software a seguir cria um vetor de quatro posies, preenche as quatro
posies de memria e depois, atravs de ponteiros, faz a inverso do mesmo e
imprime os valores no vdeo.
Se observarmos atentamente o cdigo abaixo, notaremos a falta do caracter
* (asterisco), que representa ponteiro em Linguagem C. Contudo vlido explicar
que o nome de uma matriz, segundo Mizrahi (1990), um ponteiro constante, ou
seja, diferente dos ponteiros que criamos para acessar outras variveis e que podem
ter o endereo apontado modificado, o nome da matriz aponta sempre para um
mesmo endereo, por isto o nome de ponteiro constante. Resumindo, ao criarmos
uma matriz, na verdade estamos criando um ponteiro para um endereo fixo na
memria (vale lembrar que fixo em quanto a matriz existir dentro do programa),
assim sendo, quando passamos uma matriz como argumento em uma funo, no
precisamos na funo, especificar o argumento com o caracter *.


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

#def i ne MAX 4

usi ng namespace st d;

voi d I nver t eVal or esVet or ( int VX[]) {
VX [ 0] = 4;
VX [ 1] = 3;
VX [ 2] = 2;
VX [ 3] = 1;
}

voi d I mpr i meVet or ( int VX[]) {
cout << " \ n\ n" ;
f or ( i nt P = 0; P < MAX; P++) {
cout << " \ nVal or Vet or Posi o: " << P << " = " << VX [ P] ;
}
cout << " \ n\ n" ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
int Vetor [MAX];

Vet or [ 0] = 1;
Vet or [ 1] = 2;
Vet or [ 2] = 3;
Vet or [ 3] = 4;

I mpr i meVet or ( Vet or ) ;

I nver t eVal or esVet or ( Vet or ) ;

I mpr i meVet or ( Vet or ) ;


eddiesaliba@yahoo.com ICQ-45923544 21
syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


A seguir temos um software que cria uma matriz 2 x 2 de nmeros inteiros. As
posies da matriz so preenchidas com os nmeros de 1 a 4. Temos tambm uma
funo de inverso dos valores e uma de impresso da matriz. Repare que neste
caso, os parmetros das funes InverteValoresMatriz e ImprimeMatriz so
ponteiros mas, sem o uso do caracter * (asterisco). Essa uma particularidade dos
vetores e das matrizes. Observe tambm que nos primeiros colchetes dos
parmetros de ambas as funes, no existe um valor fixo delimitando a quantidade
de colunas da matriz, contudo, existe um valor fixo delimitando a quantidade de
linhas da matriz. Essa outra particularidade das matrizes, ou seja, da segunda
dimenso em diante necessrio especificar o valor da dimenso. Para vetores,
passados como parmetros em funes, no necessrio especificar valor algum.
Por terem somente uma dimenso, somente a presena dos colchetes j o
suficiente para que o compilador entenda que receber um vetor como parmetro.


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

#def i ne MAXCOL 2
#def i ne MAXLI N 2

usi ng namespace st d;

voi d I nver t eVal or esMat r i z ( i nt MX[ ] [ MAXLI N] ) {
MX [ 0] [ 0] = 4;
MX [ 0] [ 1] = 3;
MX [ 1] [ 0] = 2;
MX [ 1] [ 1] = 1;
}

voi d I mpr i meMat r i z ( i nt MX[ ] [ MAXLI N] ) {
cout << " \ n\ n" ;
f or ( i nt C = 0; C < MAXCOL; C++) {
f or ( i nt L = 0; L < MAXLI N; L++) {
cout << " \ nVal or Mat r i z Col una: " << C << " Li nha: " << L << "
= " << MX [ C] [ L] ;
}
}
cout << " \ n\ n" ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
i nt Mat r i z [ MAXCOL] [ MAXLI N] ;

Mat r i z [ 0] [ 0] = 1;
Mat r i z [ 0] [ 1] = 2;
Mat r i z [ 1] [ 0] = 3;
Mat r i z [ 1] [ 1] = 4;

I mpr i meMat r i z ( Mat r i z) ;


eddiesaliba@yahoo.com ICQ-45923544 22
I nver t eVal or esMat r i z ( Mat r i z) ;

I mpr i meMat r i z ( Mat r i z) ;

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

5.6. Exerccios

1) Construa um software em que um valor qualquer seja digitado e armazenado em
uma varivel inteira. Atravs de ponteiros para esta varivel, voc dever
adicionar ao valor contido na varivel, seu prprio valor elevado a 5 potncia.

2) Desenvolva um software que crie um vetor de 5 posies do tipo aluno. Onde
aluno deve ser um registro contendo matrcula, nome, curso, idade. Permita
que estes dados possam ser cadastrados pelo usurio do software. Construa
uma funo que receba o vetor criado como parmetro e que inverta a ordem dos
registros no vetor. Por final, apresente a posio e o registro nela alocado.

3) Crie um software onde se tenha uma matriz de estruturas veculo 3x3. Onde a
estrutura veculo deve armazenar os seguintes dados: Placa, marca, modelo, cor
e ano. Possibilite que o usurio do software cadastre e consulte cada veculo (ou
todos simultaneamente). Crie uma funo que receba essa matriz atravs de
parmetros e que troque os registros da matriz seguindo a seguinte ordem: Se o
registro estiver na posio (0,1) da matriz, ento ele dever ser trocado com o
registro que estiver na posio (1,0), e assim por diante. Desta forma, somente os
registros que estiverem em posies onde tanto a linha quanto a coluna possuem
o mesmo nmero, no sero trocados. Apresente os dados aps a troca.

4) Modifique o exerccio nmero 2 para que o mesmo passe a aceitar o cadastro de
20 alunos. Se voc utilizou constantes no desenvolvimento do exerccio 2, ento
a alterao ser simples.

eddiesaliba@yahoo.com ICQ-45923544 23
6. Listas, Filas e Pilhas atravs de Arranjos

As listas, filas e pilhas, so tipos abstratos de dados os quais nos criamos, em
grande parte dos casos, para gerenciamento de estruturas de dados (registros).
Cada qual dos tipos acima citados tem sua particularidade, as quais sero
descritas separadamente, a seguir:

6.1. Lista

De acordo com Ziviani (1996:35), uma das formas mais simples de interligar
os elementos de um conjunto atravs de uma lista. Lista uma estrutura onde as
operaes inserir, retirar e localizar so definidas.
Para criarmos uma Lista, faz-se necessrio a definio de um conjunto de
operaes sobre os objetos do tipo Lista. Estas operaes dependero de cada
aplicao, no existindo um conjunto de operaes que seja adequado a todas
aplicaes.



Fig. 01 Implementao de uma lista atravs de arranjo
Fonte: Ziviani (1996:37)


Ziviani (1996:36) apresenta um conjunto de operaes, atribudos ao tipo
Lista, encontradas na maioria das aplicaes que fazem uso deste tipo. So elas:

1) Criar uma lista linear vazia.
2) Inserir um novo item imediatamente aps o um determinado item.
3) Retirar um determinado item.
4) Localizar um determinado item para examinar e/ou alterar o contedo de seus
componentes.
5) Combinar duas ou mais listas lineares em uma lista nica.
6) Partir uma lista linear em duas ou mais listas.
7) Fazer uma cpia da lista linear.
8) Ordenar os itens da lista em ordem ascendente ou descendente, de acordo
com alguns de seus componentes.
9) Pesquisar a ocorrncia de um item com um valor particular em alguns
componentes.

eddiesaliba@yahoo.com ICQ-45923544 24

Para a implementao das operaes citadas anteriormente, so implementadas
cinco operaes que resolvero a maior parte dos problemas que podero ser
encontrados nas diversas aplicaes existentes. Estas operaes devero ser
implementadas atravs das funes:

- FazListaVazia (Lista) Faz uma lista ficar vazia.
- InsereNaLista (X, Lista) Insere o item X aps o ltimo item da Lista.
- RetiraDaLista (P, Lista, X) Retorna o item X que est na posio P da Lista,
retirando-o da lista e deslocando os itens a partir da posio P +1 para as
posies anteriores.
- ListaVazia (Lista) Retorna VERDADEIRO se Lista estiver vazia e FALSO
caso contrrio.
- ImprimeLista (Lista) Imprime os itens da lista na ordem de ocorrncia.


A seguir, um exemplo de software para inserir, excluir, alterar e imprimir uma
estrutura contendo o cdigo e o nome de pessoas, implementada em uma lista
atravs de arranjo:

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>
#i ncl ude <coni o. h>

#def i ne I ni ci oAr r anj o 0
#def i ne MaxTam100

usi ng namespace st d;

t ypedef i nt Apont ador ;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 10] ;
};

t ypedef st r uct Ti poLi st a {
Ti poI t emI t em[ MaxTam] ;
Apont ador Pr i mei r o;
Apont ador Ul t i mo;
};

voi d FazLi st aVazi a ( Ti poLi st a &Li st a) {
Li st a. Pr i mei r o = I ni ci oAr r anj o;
Li st a. Ul t i mo = I ni ci oAr r anj o;
}

voi d Consul t aI t em( Ti poLi st a &Li st a, Ti poI t em&I t em, Apont ador P) {
I t em. Codi go = Li st a. I t em[ P] . Codi go;
st r cpy ( I t em. Nome, Li st a. I t em[ P] . Nome) ;
}

i nt Li st aVazi a ( Ti poLi st a &Li st a) {
r et ur n ( Li st a. Pr i mei r o == Li st a. Ul t i mo) ;
}


eddiesaliba@yahoo.com ICQ-45923544 25
voi d I nser i r NaLi st a ( Ti poI t emX, Ti poLi st a &Li st a) {
i f ( Li st a. Ul t i mo > MaxTam) {
cout << " Li st a chei a! " ;
}
el se {
Li st a. I t em[ Li st a. Ul t i mo] = X;
Li st a. Ul t i mo++;
}
}

voi d Ret i r aDaLi st a ( Apont ador P, Ti poLi st a &Li st a, Ti poI t em&I t em) {
i f ( Li st aVazi a ( Li st a) | | ( P >= Li st a. Ul t i mo) ) {
cout << " Er r o: Posi o no exi st e! " ;
}
el se {
I t em= Li st a. I t em[ P] ;
Li st a. Ul t i mo- - ;

f or ( i nt Aux = P; Aux < Li st a. Ul t i mo; Aux++)
Li st a. I t em[ Aux] = Li st a. I t em[ Aux + 1] ;
}
}

voi d I nser i r Li st aPosi cao ( Apont ador P, Ti poLi st a &Li st a, Ti poI t em&I t em) {
i f ( Li st aVazi a ( Li st a) | | ( P >= Li st a. Ul t i mo) ) {
cout << " Er r o: Posi o no exi st e! " ;
}
el se {
Li st a. I t em[ P] . Codi go = I t em. Codi go;
st r cpy ( Li st a. I t em[ P] . Nome, I t em. Nome) ;
}
}

voi d I mpr i meLi st a ( Ti poLi st a &Li st a) {
f or ( i nt Aux = Li st a. Pr i mei r o; Aux < Li st a. Ul t i mo; Aux++) {
cout << " \ nCdi go: " << Li st a. I t em[ Aux] . Codi go;
cout << " \ nNome : " << Li st a. I t em[ Aux] . Nome << " \ n" ;
}
}

i nt Menu ( ) {
i nt Opcao = 5;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - I nser i r " ;
cout << " \ n 2 - Excl ui r " ;
cout << " \ n 3 - Al t er ar " ;
cout << " \ n 4 - I mpr i mi r " ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 4) ) ;

r et ur n ( Opcao) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )

eddiesaliba@yahoo.com ICQ-45923544 26
{
Ti poLi st a Li st a; / * Cr i a uma l i st a. */
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
i nt Opcao,
Posi cao;

/ * Faz a l i st a f i car vazi a. */
FazLi st aVazi a ( Li st a) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
swi t ch ( Opcao) {
case 1: / * I nser i r */
syst em( " CLS" ) ;
cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
cout << " \ nDi gi t e umNome: " ;
ci n >> Aux. Nome;

I nser i r NaLi st a ( Aux, Li st a) ;
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e a posi o a ser r emovi da: " ;
ci n >> Posi cao;

Ret i r aDaLi st a ( Posi cao, Li st a, Aux) ;

cout << " \ nO i t ema segui r f oi r emovi do da l i st a: \ n\ n" ;
cout << " \ nCdi go: " << Aux. Codi go;
cout << " \ nNome : " << Aux. Nome;
br eak;

case 3: / * Al t er ar */
syst em( " CLS" ) ;
cout << " Al t er ar I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e a posi o a ser al t er ada: " ;
ci n >> Posi cao;
cout << " \ n\ n" ;

Consul t aI t em( Li st a, Aux, Posi cao) ;

cout << " Val or es at uai s" ;
cout << " \ n==============\ n\ n" ;
cout << " Cdi go: " << Aux. Codi go;
cout << " \ nNome : " << Aux. Nome << " \ n" ;

cout << " \ nDi gi t e o novo Cdi go: " ;
ci n >> Aux. Codi go;
cout << " \ nDi gi t e o novo Nome : " ;
ci n >> Aux. Nome;

I nser i r Li st aPosi cao ( Posi cao, Li st a, Aux) ;
br eak;

eddiesaliba@yahoo.com ICQ-45923544 27

case 4: / * I mpr i mi r */
syst em( " CLS" ) ;
cout << " I t ens da Li st a" ;
cout << " \ n==============\ n\ n" ;

I mpr i meLi st a ( Li st a) ;

f f l ush( st di n) ;
get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

6.2. Pilha

A pilha, de acordo com Tenenbaum et al. (1995:86) e Ziviani (1996:48),
quando implementada em arranjos, um conjunto ordenado de itens no qual se
aplicam basicamente, duas operaes para manuteno dos dados e/ou estruturas
nela armazenada.
Devido s suas caractersticas, na pilha, a operao de insero e retirada de
itens devem ocorrer sempre no topo.
A pilha tambm conhecida como LIFO (Last In, First Out, do ingls, ltimo
que entra o primeiro que sai).
Um exemplo tpico para facilitar o entendimento da estrutura Pilha, o de uma
pilha de pratos.
Numa pilha de pratos, nunca retiramos o primeiro prato (de baixo para cima) e
tampouco qualquer posio do meio da pilha. A retirada ou insero pratos se d
sempre no topo da pilha.

Fig. 02 Pilha de Pratos
Fonte: <http://www.linhadecodigo.com.br/ArtigoImpressao.aspx?id=975>Acesso em:
26 nov. 2007

A seguir, foram feitas alteraes no software apresentado na estrutura Lista,
para que este passasse a armazenar as pessoas numa estrutura de pilha.

eddiesaliba@yahoo.com ICQ-45923544 28
Poderemos observar tambm que as operaes utilizadas na estrutura de Pilha so
em nmero menor e bem mais simples de serem desenvolvidas do que na estrutura
de Lista. Primeiramente vamos s operaes realizadas sobre a estrutura de Pilha:

- FazPilhaVazia (Pilha) Faz uma Pilha ficar vazia.
- PilhaVazia (Pilha) Retorna VERDADEIRO se Pilha estiver vazia e FALSO
caso contrrio.
- Empilhar (X, Pilha) Insere o item X no topo da Pilha.
- Desempilhar (Pilha, X) Retorna o item X que est no topo da Pilha,
removendo-o da Pilha.
- TamanhoPilha (Pilha) Retorna quantos itens existem armazenados na Pilha.

Vejamos um exemplo do software j citado anteriormente:

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>
#i ncl ude <coni o. h>

#def i ne MaxTam100

usi ng namespace st d;

t ypedef i nt Apont ador ;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 10] ;
};

t ypedef st r uct Ti poPi l ha {
Ti poI t emI t em[ MaxTam] ;
Apont ador Topo;
};

voi d FazPi l haVazi a ( Ti poPi l ha &Pi l ha) {
Pi l ha. Topo = - 1;
}

i nt Pi l haVazi a ( Ti poPi l ha &Pi l ha) {
r et ur n ( Pi l ha. Topo == - 1) ;
}

voi d Empi l har ( Ti poI t emX, Ti poPi l ha &Pi l ha) {
i f ( Pi l ha. Topo == MaxTam) {
cout << " Pi l ha chei a! " ;
}
el se {
Pi l ha. Topo++;
Pi l ha. I t em[ Pi l ha. Topo] = X;
}
}

voi d Desempi l har ( Ti poPi l ha &Pi l ha, Ti poI t em&I t em) {
syst em( " CLS" ) ;
i f ( Pi l haVazi a ( Pi l ha) ) {
cout << " Er r o: Pi l ha est vazi a! " ;
I t em. Codi go = - 1;

eddiesaliba@yahoo.com ICQ-45923544 29
}
el se {
I t em= Pi l ha. I t em[ Pi l ha. Topo] ;
Pi l ha. Topo- - ;
}
}

i nt TamanhoPi l ha ( Ti poPi l ha &Pi l ha) {
r et ur n ( Pi l ha. Topo + 1) ;
}

i nt Menu ( ) {
i nt Opcao = 5;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - Empi l har " ;
cout << " \ n 2 - Desempi l har " ;
cout << " \ n 3 - Ver i f i car Tamanho da Pi l ha" ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 3) ) ;

r et ur n ( Opcao) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
Ti poPi l ha Pi l ha; / * Cr i a uma Pi l ha. */
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
i nt Opcao;

/ * Faz a Pi l ha f i car vazi a. */
FazPi l haVazi a ( Pi l ha) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
swi t ch ( Opcao) {
case 1: / * I nser i r */
syst em( " CLS" ) ;
cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;
cout << " \ nDi gi t e umNome: " ;
get s ( Aux. Nome) ;

Empi l har ( Aux, Pi l ha) ;
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em" ;
cout << " \ n============\ n\ n" ;

Desempi l har ( Pi l ha, Aux) ;

eddiesaliba@yahoo.com ICQ-45923544 30

i f ( Aux. Codi go > 0) {
cout << " \ nO i t ema segui r f oi r emovi do da
Pi l ha: \ n\ n" ;
cout << " \ nCdi go: " << Aux. Codi go;
cout << " \ nNome : " << Aux. Nome;
}

f f l ush( st di n) ;
get char ( ) ;
br eak;

case 3: / * Tamanho da Pi l ha */
syst em( " CLS" ) ;
cout << " Pi l ha" ;
cout << " \ n=====\ n\ n" ;
cout << " Quant i dade de i t ens na Pi l ha: " << TamanhoPi l ha
( Pi l ha) ;

f f l ush( st di n) ;
get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

6.3. Fila

As filas, tambm conhecidas como listas FIFO (First In, First Out, do ingls:
Primeiro que Entra, Primeiro que Sai) simulam as filas do mundo real. Como
exemplo podemos citar uma fila de banco. Onde a primeira pessoa que chegar, ser
a primeira pessoa a ser atendida; a segunda pessoa que chegar ser a segunda a
ser atendida e assim por diante.
Quando manipulamos dados atravs de arranjos, os itens inseridos so
armazenados em posies contguas de memria. E esta estrutura deve ser utilizada
quando desejamos processar dados de acordo com a ordem de chegada.
Segundo Ziviani (1996:55), um possvel conjunto de operaes definido para
este tipo :

- FazFilaVazia (Fila) Faz uma fila ficar vazia.
- FilaVazia (Fila) Retorna VERDADEIRO se fila estiver vazia e FALSO caso
contrrio.
- InserirNaFila (X, Fila) Insere o item X no final da fila.
- RetirarDaFila (Fila, X) Retorna o item X que est no incio da fila, retirando-o
desta.

Como a fila nada mais do que uma lista com ordem de entrada e sada, se
quisermos, podemos ainda implementar uma outra operao: Imprimir fila. Esta
operao vai nos mostrar os itens que esto na fila.


eddiesaliba@yahoo.com ICQ-45923544 31
- ImprimeFila (Fila) Imprime os itens da fila na ordem de ocorrncia.

Conforme veremos a seguir, uma fila na informtica, ao contrrio da realidade,
no representado por um conjunto de itens ordenados um aps o outro em uma
linha reta. Na informtica, as filas so representadas por um conjunto de itens
ordenados uma aps o outro, porm em forma circular. Isto quando estamos
tratando de implementao de Filas em arranjos, pois, desta forma no precisaremos
remanejar os itens dentro do vetor medida que entram e saem da fila. Para
sabermos quem o primeiro e o ltimo item da fila, criaremos dois apontadores que
faro este controle. Como podemos observar na figura 03, abaixo:


Fig. 03 Implementao Circular para Filas
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007

Por ser implementada em forma circular, de acordo com Ziviani (1996:56),
existe um pequeno problema: no h uma forma de distinguir uma fila cheia de uma
vazia, pois nos dois casos os apontadores Frente e Trs apontam para a mesma
posio do crculo. Uma possvel soluo para este problema, utilizada por Aho,
Hopcroft e Ullman apud Ziviani (1996:56), no utilizar todo o espao da fila (vetor
ou array), deixando uma posio vazia. Assim sendo, a fila estar cheia quando o
apontador Trs +1 for igual ao apontador Frente. Isto significa que existir uma
clula vazia entre o fim e o incio da fila.
Apesar de existir a perda de uma posio de memria, esse controle faz-se
necessrio para sabermos quando uma fila estar cheia ou no.

A seguir um exemplo de software que simula uma fila para atendimento de
pessoas. Este software foi construdo utilizando a estrutura de fila circular
apresentada.

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>
#i ncl ude <coni o. h>

#def i ne MaxTam5

usi ng namespace st d;

t ypedef i nt Apont ador ;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 10] ;

eddiesaliba@yahoo.com ICQ-45923544 32
};

t ypedef st r uct Ti poFi l a {
Ti poI t emI t em[ MaxTam] ;
Apont ador Fr ent e;
Apont ador Tr as;
};

voi d FazFi l aVazi a ( Ti poFi l a &Fi l a) {
Fi l a. Tr as = Fi l a. Fr ent e = 1;
}

i nt Fi l aVazi a ( Ti poFi l a &Fi l a) {
r et ur n ( Fi l a. Fr ent e == Fi l a. Tr as) ;
}

voi d I nser i r NaFi l a ( Ti poI t emX, Ti poFi l a &Fi l a) {
Fi l a. I t em[ Fi l a. Tr as - 1] = X;
Fi l a. Tr as = ( Fi l a. Tr as %MaxTam+ 1) ;
}

voi d Ret i r aDaFi l a ( Ti poFi l a &Fi l a, Ti poI t em&I t em) {
i f ( Fi l aVazi a ( Fi l a) ) {
cout << " \ n\ nFi l a vazi a! " ;
get char ( ) ;
}
el se {
I t em= Fi l a. I t em[ Fi l a. Fr ent e - 1] ;
Fi l a. Fr ent e = ( Fi l a. Fr ent e %MaxTam+ 1) ;
}
}

i nt Menu ( ) {
i nt Opcao = 5;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - I nser i r " ;
cout << " \ n 2 - Excl ui r " ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 2) ) ;

r et ur n ( Opcao) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
Ti poFi l a Fi l a; / * Cr i a uma Fi l a. */
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
i nt Opcao;

f or ( i nt I = 0; I < MaxTam; I ++) {
Fi l a. I t em[ I ] . Codi go = 0;
st r cpy ( Fi l a. I t em[ I ] . Nome, " " ) ;
}


eddiesaliba@yahoo.com ICQ-45923544 33
/ * Faz a Fi l a f i car vazi a. */
FazFi l aVazi a ( Fi l a) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
swi t ch ( Opcao) {
case 1: / * I nser i r */
syst em( " CLS" ) ;

i f ( ( Fi l a. Tr as %MaxTam+ 1) == Fi l a. Fr ent e) {
cout << " \ n\ nFi l a chei a! " ;
f f l ush( st di n) ;
get char ( ) ;
}
el se {
cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
cout << " \ nDi gi t e umNome: " ;
ci n >> Aux. Nome;

I nser i r NaFi l a ( Aux, Fi l a) ;
}
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em" ;
cout << " \ n============\ n\ n" ;

Ret i r aDaFi l a ( Fi l a, Aux) ;

i f ( Aux. Codi go ! = - 1) {
cout << " \ nO i t ema segui r f oi r emovi do da
Fi l a: \ n\ n" ;
cout << " \ nCdi go: " << Aux. Codi go;
cout << " \ nNome : " << Aux. Nome;
}
Aux. Codi go = - 1;

f f l ush( st di n) ;
get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

6.4. Exerccios

1) Implemente um software em que o usurio digite valores aleatrios numa lista de
tamanho igual a 50. D a opo do usurio imprimir somente os nmeros
mpares, somente os nmeros pares ou a lista por completo.


eddiesaliba@yahoo.com ICQ-45923544 34
2) Construa um programa onde o usurio entre com 20 valores que devero ser
armazenados numa pilha. Feito isto, o software dever apresentar os seguintes
resultados: Somatrio de todos os valores mpares, somatrio de todos os
valores pares, somatrio de todos os valores que esto nas posies mpares da
pilha, somatrio de todos os valores que esto nas posies pares.

Observao: Seu software s poder percorrer os valores contidos na pilha
atravs das operaes de Empilhar e Desempilhar.

3) Escreva um software cuja finalidade administrar uma agenda de atendimento
bancrio, onde todas as pessoas tm que marcar hora nesta agenda para que
possam ser atendidas. O banco quer que seja implementado tambm, um
mecanismo de procura para que uma mesma pessoa no possa fazer dois
agendamentos. Para que possa evitar tal problema, antes de ser colocado na
agenda, o software dever pesquisar a fila existente para averiguar se j h ou
no algum agendamento para a pessoa que est sendo cadastrada. Alm de
usar o TAD fila, use tambm estrutura de dados para criar um tipo agenda que
contenha os dados da pessoa, do horrio reservado e o sexo. Sua agenda
dever suportar no mnimo 50 pessoas.

4) Implemente um procedimento para inverter a ordem dos elementos de uma lista,
usando uma pilha. Onde o usurio dever digitar 20 valores quaisquer em uma
lista, e o software dever dar a opo de inverso e impresso dos valores na
lista.

5) Em um nico vetor de 20 posies, crie duas pilhas que crescem do centro para
as pontas do vetor. Estas pilhas devero ser utilizadas num software que
solicitar do usurio que entre com 20 nmeros quaisquer, limitados a 10
nmeros impares e 10 nmeros pares. Os nmeros podero ser digitados
aleatoriamente. O software dever armazenar os nmeros pares do centro para a
esquerda, e os nmeros mpares do centro para a direita. Use constantes para
limitar os tamanhos das pilhas e do vetor, pois essas podero ser alteradas a
cada compilao. Implemente tambm um mecanismo de impresso dos valores
digitados: Todos, s os mpares ou s os pares.

6) Implemente um software onde o usurio entre com diversos nmeros em uma
fila, limitado a 50 posies. Implemente uma funo para separar em duas outras
filas, os nmeros pares dos nmeros mpares. Construa tambm uma funo
para imprimir qualquer uma das duas novas filas criadas utilizando as operaes,
fila, aplicadas.

7) Dadas as seguintes estruturas de dados:

t ypedef st r uct Ti poPessoa {
i nt Codi go;
char Nome[ 50] ;
char Logr adour o[ 40] ;
i nt Numer o;
char Bai r r o[ 30] ;
char Ci dade[ 50] ;
char Est ado[ 19] ;

eddiesaliba@yahoo.com ICQ-45923544 35
char CEP[ 8] ;
char Tel ef one[ 20] ;
};

t ypedef st r uct Ti poVei cul o {
char Pl aca[ 7] ;
char Mar ca[ 50] ;
char Model o[ 30] ;
i nt Ano_Fabr i c;
i nt Ano_Model o;
};

t ypedef st r uct Ti poPr opr i et ar i o {
Ti poPessoa Pessoa;
Ti poVei cul o Vei cul o;
};


a) Escreva um software utilizando a estrutura de Lista implementada em Arranjo,
onde seja possvel cadastrar 50 pessoas. Implemente alm das principais
operaes que so aplicadas sobre as listas, uma outra operao de Procura.
Utilize-a para que em seu software no seja permitido o cadastro de duas
pessoas com cdigos e nomes idnticos.

b) Uma concessionria vende veculos novos e usados. Diariamente chegam
veculos novos e usados para repor o estoque. Sabe-se que o ptio desta
concessionria suporta no mximo 20 veculos novos e 20 veculos usados.
Construa um software utilizando um nico vetor de 40 posies onde, as
primeiras 20 posies sero preenchidas com veculos novos, e as demais
com veculos usados. Implemente alm das operaes bsicas do TAD lista,
uma operao para imprimir uma lista de veculos Novos ou Usados,
escolha do usurio.

c) Uma empresa governamental possui os direitos de operar uma balsa que faz
a travessia, no canal de Bertioga, de carros que esto em Bertioga para
Guaruj, no estado de So Paulo. A balsa utilizada pela empresa estreita,
sendo que os carros entram e saem dela por uma nica passagem, ou seja, o
primeiro carro que entrar na balsa ser o ltimo a sair. A empresa necessita
manter um cadastro de todos os veculos e seus respectivos proprietrios que
entraram na balsa, pois a checagem de veculo e dono ser feita no momento
de desembarque. Esta medida visa implementar maior segurana aos
proprietrios de veculos nas viagens da balsa. Implemente um software que
possibilite tal operao.

d) Construa um software que possua uma matriz de 10 linhas e 26 colunas.
Onde cada coluna da matriz dever funcionar como uma pilha. O software
dever solicitar o cadastro de pessoas e armazena-los de acordo com a letra
inicial de cada nome, por exemplo, Andr, Alexandre e Antnio devero ficar
todos na coluna 0 (zero) da matriz, que est destinada a letra A. Bruno,
Bernardo e Baltazar devero ser empilhados na coluna 1 (um) da matriz, pois
esta a segunda coluna e est destinada letra B, e assim por diante. O
software dever aceitar no mximo 10 pessoas com uma determinada letra
inicial. O software dever dar condies do usurio imprimir as colunas de

eddiesaliba@yahoo.com ICQ-45923544 36
acordo com suas necessidades, ou seja, todas de uma nica vez ou letra por
letra. Para a manipulao dos dados na matriz, devero ser utilizadas,
unicamente, as operaes aplicadas ao TAD pilha.



eddiesaliba@yahoo.com ICQ-45923544 37

7. Lista, Pilha e Fila atravs de Ponteiros

Como j foi dito no item 6 deste trabalho, as listas, filas e pilhas, so tipos
abstratos de dados os quais nos criamos, em grande parte dos casos, para
gerenciamento de estruturas de dados (registros).
Cada qual dos tipos acima citados tem sua particularidade, as quais j foram
descritas nos itens 6.1, 6.2 e 6.3 respectivamente. Adiante mostraremos ento a
implementao dos mesmos softwares apresentados nestes itens, porm, ao invs
de utilizarmos arranjos, utilizaremos ponteiros ou apontadores.
Uma particularidade deste tipo de implementao que no h um tamanho
definido para Lista, Pilha ou Fila, ou seja, qualquer uma destas pode crescer
indiscriminadamente. De acordo com Ziviani (1996:38), em aplicaes em que no
existe previso sobre o crescimento da lista conveniente utilizar Listas encadeadas
por apontadores. E a maior desvantagem deste tipo de implementao a utilizao
de memria extra para armazenar os apontadores.

7.1. Lista



Fig. 04 Implementao de Lista Encadeada por Apontadores
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007

Para termos uma idia mais clara do funcionamento da lista encadeada por
ponteiros, vejamos a seguir a figura 05 que mostra como se procede para insero
de um novo elemento na lista. J a figura 06 que mostra a retirada de um elemento
localizado no meio da lista encadeada.



Fig. 05 Insero de um nodo na Lista Encadeada por Apontadores


eddiesaliba@yahoo.com ICQ-45923544 38

Fig. 06 Retirada de um nodo do meio da Lista Encadeada por Apontadores


A seguir o cdigo de um software para criao e manipulao de uma lista
simples encadeada por ponteiros:


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>
#i ncl ude <coni o. h>

usi ng namespace st d;

t ypedef st r uct Ti poCel ul a *Apont ador ;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 10] ;
};

t ypedef st r uct Ti poCel ul a {
Ti poI t emI t em;
Apont ador Pr ox;
} Cel ul a;

t ypedef st r uct Ti poLi st a {
Apont ador Pr i mei r o;
Apont ador Ul t i mo;
};

voi d FazLi st aVazi a ( Ti poLi st a *Li st a) {
Li st a- >Pr i mei r o = ( Apont ador ) mal l oc ( si zeof ( Cel ul a) ) ;
Li st a- >Ul t i mo = Li st a- >Pr i mei r o;
Li st a- >Pr i mei r o- >Pr ox = NULL;
}

i nt Li st aVazi a ( Ti poLi st a Li st a) {
r et ur n ( Li st a. Pr i mei r o == Li st a. Ul t i mo) ;
}

voi d I nser i r NaLi st a ( Ti poI t emX, Ti poLi st a *Li st a) {
Li st a- >Ul t i mo- >Pr ox = ( Apont ador ) mal l oc( si zeof ( Cel ul a) ) ;
Li st a- >Ul t i mo = Li st a- >Ul t i mo- >Pr ox;
Li st a- >Ul t i mo- >I t em= X;
Li st a- >Ul t i mo- >Pr ox = NULL;
}

voi d Ret i r aDaLi st a ( Apont ador P, Ti poLi st a *Li st a, Ti poI t em*I t em) {
/ * O i t ema ser r et i r ado o segui nt e ao apont ado por P. */
Apont ador Q;
i f ( Li st aVazi a ( *Li st a) | | ( P == NULL) | | ( P- >Pr ox == NULL) ) {

eddiesaliba@yahoo.com ICQ-45923544 39
cout << " Er r o: Li st a vazi a ou posi o no exi st e! " ;
}
el se {
Q = P- >Pr ox;
*I t em= Q- >I t em;
P- >Pr ox = Q- >Pr ox;

i f ( P- >Pr ox == NULL)
Li st a- >Ul t i mo = P;

f r ee( Q) ;
}
}

voi d I mpr i meLi st a ( Ti poLi st a Li st a) {
Apont ador Aux;
i nt cont = 0;

Aux = Li st a. Pr i mei r o- >Pr ox;
whi l e ( Aux ! = NULL) {
cout << " \ nPosi o: " << cont ;
cout << " \ nCdi go : " << Aux- >I t em. Codi go;
cout << " \ nNome : " << Aux- >I t em. Nome << " \ n" ;

cont ++;
Aux = Aux- >Pr ox;
}
}

Apont ador Ret or naPont ei r oPar aUmaCel ul aDaLi st a ( Ti poLi st a Li st a, i nt
Posi cao) {
Apont ador Aux;
i nt cont = 0;

Aux = Li st a. Pr i mei r o;
whi l e ( ( Aux ! = NULL) && ( cont ! = Posi cao) ) {
Aux = Aux- >Pr ox;
cont ++;
}

r et ur n ( Aux) ;
}

i nt Menu ( ) {
i nt Opcao = 5;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - I nser i r " ;
cout << " \ n 2 - Excl ui r " ;
cout << " \ n 3 - Al t er ar " ;
cout << " \ n 4 - I mpr i mi r " ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 4) ) ;

r et ur n ( Opcao) ;

eddiesaliba@yahoo.com ICQ-45923544 40
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
Ti poLi st a Li st a;
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
Apont ador P;
i nt Opcao,
Posi cao = 0;

/ * Faz a l i st a f i car vazi a. */
FazLi st aVazi a ( &Li st a) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
swi t ch ( Opcao) {
case 1: / * I nser i r */
syst em( " CLS" ) ;
cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
cout << " \ nDi gi t e umNome: " ;
ci n >> Aux. Nome;

I nser i r NaLi st a ( Aux, &Li st a) ;
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em\ n" ;
cout << " ============\ n\ n" ;

I mpr i meLi st a ( Li st a) ;

cout << " \ nQual r egi st r o voc desej a excl ui r ? Di gi t e a
posi o: " ;
ci n >> Posi cao;

P = Ret or naPont ei r oPar aUmaCel ul aDaLi st a ( Li st a,
Posi cao) ;

Ret i r aDaLi st a ( P, &Li st a, &Aux) ;

cout << " \ n\ nO i t ema segui r f oi r emovi do da
l i st a: \ n\ n" ;
cout << " \ nCdi go: " << Aux. Codi go;
cout << " \ nNome : " << Aux. Nome;
f f l ush( st di n) ;
get char ( ) ;
br eak;

case 3: / * Al t er ar */
syst em( " CLS" ) ;

I mpr i meLi st a ( Li st a) ;

cout << " \ n\ nAl t er ar I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e a posi o a ser al t er ada: " ;

eddiesaliba@yahoo.com ICQ-45923544 41
ci n >> Posi cao;

P = Ret or naPont ei r oPar aUmaCel ul aDaLi st a ( Li st a,
Posi cao) ;

cout << " \ n\ n" ;
cout << " Val or es at uai s" ;
cout << " \ n==============\ n\ n" ;
cout << " Cdi go: " << P- >Pr ox- >I t em. Codi go;
cout << " \ nNome : " << P- >Pr ox- >I t em. Nome << " \ n" ;

cout << " \ nDi gi t e o novo Cdi go: " ;
ci n >> P- >Pr ox- >I t em. Codi go;
cout << " \ nDi gi t e o novo Nome : " ;
ci n >> P- >Pr ox- >I t em. Nome;
br eak;

case 4: / * I mpr i mi r */
syst em( " CLS" ) ;
cout << " I t ens da Li st a" ;
cout << " \ n==============\ n\ n" ;

I mpr i meLi st a ( Li st a) ;

f f l ush( st di n) ;
get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

7.1.1. Lista Duplamente Encadeada

Quando falamos de listas encadeadas por ponteiros, podemos nos deparar
como um pequeno problema ao implementarmos uma lista simples como mostrado
na figura 04. O problema que, de acordo com Ziviani (1996:59), na manipulao de
listas lineares simples, no h como voltar atrs na lista, ou seja, percorre-la no
sentido inverso ao dos apontadores. A soluo para esta situao a incorporao
clula de um apontador para o seu antecessor. Listas deste tipo so chamadas de
listas duplamente encadeadas.

Vejamos a seguir a figura 07 que mostra a representao de uma lista
duplamente encadeada.

Fig. 07 Lista Duplamente Encadeada por Apontadores

eddiesaliba@yahoo.com ICQ-45923544 42
7.2. Pilha



Fig. 08 Implementao de Pilha Encadeada por Apontadores
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007

Vejamos agora um exemplo de software para gerenciamento de uma pilha
utilizando ponteiros ou apontadores:

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>
#i ncl ude <coni o. h>

usi ng namespace st d;

t ypedef st r uct Ti poCel ul a *Apont ador ;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 10] ;
};

t ypedef st r uct Ti poCel ul a {
Ti poI t emI t em;
Apont ador Pr ox;
} Cel ul a;

t ypedef st r uct Ti poPi l ha {
Apont ador Topo;
Apont ador Fundo;
i nt Tamanho;
};

voi d FazPi l haVazi a ( Ti poPi l ha *Pi l ha) {
Pi l ha- >Topo = ( Apont ador ) mal l oc( si zeof ( Cel ul a) ) ;
Pi l ha- >Fundo = Pi l ha- >Topo;
Pi l ha- >Topo- >Pr ox = NULL;
Pi l ha- >Tamanho = 0;
}

eddiesaliba@yahoo.com ICQ-45923544 43

i nt Pi l haVazi a ( Ti poPi l ha Pi l ha) {
r et ur n ( Pi l ha. Topo == Pi l ha. Fundo) ;
}

voi d Empi l har ( Ti poI t emX, Ti poPi l ha *Pi l ha) {
Apont ador Aux;

Aux = ( Apont ador ) mal l oc( si zeof ( Cel ul a) ) ;
Pi l ha- >Topo- >I t em= X;
Aux- >Pr ox = Pi l ha- >Topo;
Pi l ha- >Topo = Aux;
Pi l ha- >Tamanho++;
}

voi d Desempi l har ( Ti poPi l ha *Pi l ha, Ti poI t em*I t em) {
Apont ador Q;

i f ( Pi l haVazi a ( *Pi l ha) ) {
cout << " Er r o: Pi l ha est vazi a! " ;
I t em- >Codi go = - 1;
}
el se {
Q = Pi l ha- >Topo;
Pi l ha- >Topo = Q- >Pr ox;
*I t em= Q- >Pr ox- >I t em;
f r ee ( Q) ;
Pi l ha- >Tamanho- - ;
}
}

i nt TamanhoPi l ha ( Ti poPi l ha Pi l ha) {
r et ur n ( Pi l ha. Tamanho) ;
}

i nt Menu ( ) {
i nt Opcao = 5;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - Empi l har " ;
cout << " \ n 2 - Desempi l har " ;
cout << " \ n 3 - Ver i f i car Tamanho da Pi l ha" ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 3) ) ;

r et ur n ( Opcao) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
Ti poPi l ha Pi l ha; / * Cr i a uma Pi l ha. */
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
i nt Opcao;

/ * Faz a Pi l ha f i car vazi a. */

eddiesaliba@yahoo.com ICQ-45923544 44
FazPi l haVazi a ( &Pi l ha) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
swi t ch ( Opcao) {
case 1: / * I nser i r */
syst em( " CLS" ) ;
cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;
cout << " \ nDi gi t e umNome: " ;
get s ( Aux. Nome) ;

Empi l har ( Aux, &Pi l ha) ;
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em" ;
cout << " \ n============\ n\ n" ;

Desempi l har ( &Pi l ha, &Aux) ;

i f ( Aux. Codi go ! = - 1) {
cout << " \ nO i t ema segui r f oi r emovi do da
Pi l ha: \ n\ n" ;
cout << " \ nCdi go: " << Aux. Codi go;
cout << " \ nNome : " << Aux. Nome;
}

f f l ush( st di n) ;
get char ( ) ;
br eak;

case 3: / * Tamanho da Pi l ha */
syst em( " CLS" ) ;
cout << " Pi l ha" ;
cout << " \ n=====\ n\ n" ;
cout << " Quant i dade de i t ens na Pi l ha: " << TamanhoPi l ha
( Pi l ha) ;

f f l ush( st di n) ;
get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


eddiesaliba@yahoo.com ICQ-45923544 45

7.3. Fila




Fig. 09 Implementao de Fila Encadeada por Apontadores
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007


Abaixo o software para manipulao do conceito de fila atravs da utilizao
de apontadores.

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>
#i ncl ude <coni o. h>

usi ng namespace st d;

t ypedef st r uct Cel ul a *Apont ador ;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 10] ;
};

t ypedef st r uct Cel ul a {
Ti poI t emI t em;
Apont ador Pr ox;
};

t ypedef st r uct Ti poFi l a {
Apont ador Fr ent e;
Apont ador Tr as;
};

voi d FazFi l aVazi a ( Ti poFi l a *Fi l a) {
Fi l a- >Fr ent e = ( Apont ador ) mal l oc( si zeof ( Cel ul a) ) ;
Fi l a- >Tr as = Fi l a- >Fr ent e;
Fi l a- >Fr ent e- >Pr ox = NULL;
}

i nt Fi l aVazi a ( Ti poFi l a Fi l a) {
r et ur n ( Fi l a. Fr ent e == Fi l a. Tr as) ;
}

voi d I nser i r NaFi l a ( Ti poI t emX, Ti poFi l a *Fi l a) {
Fi l a- >Tr as- >Pr ox = ( Apont ador ) mal l oc( si zeof ( Cel ul a) ) ;
Fi l a- >Tr as = Fi l a- >Tr as- >Pr ox;
Fi l a- >Tr as- >I t em= X;

eddiesaliba@yahoo.com ICQ-45923544 46
Fi l a- >Tr as- >Pr ox = NULL;
}

voi d Ret i r aDaFi l a ( Ti poFi l a *Fi l a, Ti poI t em*I t em) {
Apont ador Q;

i f ( Fi l aVazi a ( *Fi l a) ) {
cout << " \ n\ nFi l a vazi a! " ;
I t em- >Codi go = - 1;
get char ( ) ;
}
el se {
Q = Fi l a- >Fr ent e;
Fi l a- >Fr ent e = Fi l a- >Fr ent e- >Pr ox;
*I t em= Fi l a- >Fr ent e- >I t em;
f r ee( Q) ;
}
}

i nt Menu ( ) {
i nt Opcao = 5;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - Enf i l ei r ar " ;
cout << " \ n 2 - Desenf i l ei r ar " ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 2) ) ;

r et ur n ( Opcao) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
Ti poFi l a Fi l a; / * Cr i a uma Fi l a. */
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
i nt Opcao;

/ * Faz a Fi l a f i car vazi a. */
FazFi l aVazi a ( &Fi l a) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
swi t ch ( Opcao) {
case 1: / * I nser i r */
syst em( " CLS" ) ;

cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;
cout << " \ nDi gi t e umNome: " ;
get s ( Aux. Nome) ;

I nser i r NaFi l a ( Aux, &Fi l a) ;

eddiesaliba@yahoo.com ICQ-45923544 47
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em" ;
cout << " \ n============\ n\ n" ;

Ret i r aDaFi l a ( &Fi l a, &Aux) ;

i f ( Aux. Codi go ! = - 1) {
cout << " \ nO i t ema segui r f oi r emovi do da
Fi l a: \ n\ n" ;
cout << " \ nCdi go: " << Aux. Codi go;
cout << " \ nNome : " << Aux. Nome;
}
Aux. Codi go = - 1;

f f l ush( st di n) ;
get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


7.4. Exerccio

1) Refaa os exerccios do item 6.4 utilizando Listas, Pilhas e Filas implementadas
com apontadores.


eddiesaliba@yahoo.com ICQ-45923544 48
8. rvores de Pesquisa

De acordo com Ziviani (1996:111), rvores de pesquisa so estruturas de
dados eficientes para armazenar informao. Uma rvore de pesquisa
particularmente adequada quando existe necessidade de considerar todos ou
alguma combinao de requisitos, tais como: (i) acesso direto e seqencial
eficientes; (ii) facilidade de insero e retirada de registros; (iii) boa taxa de utilizao
de memria; (iv) utilizao de memria primria e secundria.


8.1. rvores Binrias de Pesquisa Sem Balanceamento


Fig. 10 rvore Binria de Pesquisa
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007


Segundo Knuth apud Ziviani (1996:112), uma rvore binria formada a
partir de um conjunto finito de nodos, consistindo de um nodo chamado raiz mais 0
ou 2 subrvores binrias distintas. Resumindo, uma rvore binria aquela onde
cada nodo tem exatamente 0 ou 2 filhos. Quando um nodo tem dois filhos, eles so
chamados filhos esquerda e direita do nodo.
Cada nodo contm apontadores para subrvores esquerda e direita. O
nmero de subrvores de um nodo chamado grau daquele nodo. Um nodo de grau
zero chamado de nodo externo ou folha. Os demais so chamados nodos internos.
Uma rvore binria de pesquisa uma rvore binria em que todo nodo
interno contm um registro, e, para cada nodo, a seguinte propriedade verdadeira:
todos os registros com chaves maiores esto na subrvore direita.
O nvel do nodo raiz 0 (zero). Se um nodo est no nvel i, ento a raiz de
suas subrvores esto no nvel i + 1.
A altura de um nodo o comprimento do caminho mais longo deste nodo at
um nodo folha. A altura de uma rvore a altura do nodo raiz.

eddiesaliba@yahoo.com ICQ-45923544 49
A estrutura de dados rvore binria de pesquisa ser utilizada para
implementar o tipo abstrato de dados Dicionrio.
O TAD Dicionrio possui as seguintes operaes:
- Inicializa
- Pesquisa
- Insere
- Retira
Um procedimento Pesquisa para uma rvore binria de pesquisa bastante
simples. Para encontrar um registro de valor X, primeiro compare-o com o valor
que est na raiz. Se for menor, v para a subrvore esquerda, caso contrrio v para
subrvore direita. Este procedimento repetir-se- recursivamente at que o valor
desejado seja encontrado ou ento um nodo folha seja atingido. Se obtivermos
sucesso na pesquisa, ento o contedo do registro retornar o valor desejado. Se
atingirmos um apontador nulo em um processo de pesquisa, significa que no
encontramos o valor desejado, ou seja, este registro no est na rvore. Caso queira
inseri-lo na rvore, o apontador nulo atingido justamente o ponto de insero.

Vejamos agora um exemplo de retirada de registro de uma rvore:



Fig. 11 Exemplo de retirada de registro da rvore Binria
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007


eddiesaliba@yahoo.com ICQ-45923544 50
A seguir, o software implementando o conceito de rvore binria de pesquisa
sem balanceamento:

#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

t ypedef st r uct Nodo *Apont ador ;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 50] ;
};

t ypedef st r uct Nodo {
Ti poI t emI t em;
Apont ador Esq;
Apont ador Di r ;
};

t ypedef Apont ador Ti poDi ci onar i o;

voi d Pesqui sa ( Ti poI t em*X, Nodo **P, i nt &Encont r ou) {
Encont r ou = 0;
i f ( *P == NULL) {
r et ur n; / * r vor e vazi a. */
}
el se {
i f ( X- >Codi go < ( *P) - >I t em. Codi go) {
Pesqui sa( X, &( *P) - >Esq, Encont r ou) ;
r et ur n;
}
el se {
i f ( X- >Codi go > ( *P) - >I t em. Codi go) {
Pesqui sa( X, &( *P) - >Di r , Encont r ou) ;
}
el se {
/ * Ret or na 1 caso o r egi st r o est ej a na r vor e. */
Encont r ou = 1;
r et ur n;
}
}
}
}

voi d I nser e ( Ti poI t emX, Apont ador *P) {
i f ( *P == NULL) {
*P = ( Apont ador ) mal l oc ( si zeof ( Nodo) ) ;
( *P) - >I t em= X;
( *P) - >Esq = NULL;
( *P) - >Di r = NULL;
}
i f ( X. Codi go < ( *P) - >I t em. Codi go) {
I nser e ( X, &( *P) - >Esq) ;
}
i f ( X. Codi go > ( *P) - >I t em. Codi go)
I nser e ( X, &( *P) - >Di r ) ;
el se
cout << " Er r o: Regi st r o j exi st e na r vor e! " ;

eddiesaliba@yahoo.com ICQ-45923544 51
}

voi d I ni ci al i za ( Ti poDi ci onar i o *Di c) {
*Di c = NULL;
}

voi d Ant ecessor ( Apont ador Q, Apont ador *R) {
i f ( ( *R) - >Di r ! = NULL) {
Ant ecessor ( Q, &( *R) - >Di r ) ;
}
Q- >I t em= ( *R) - >I t em;
Q = *R;
*R = ( *R) - >Esq;
f r ee( Q) ;
}

voi d Ret i r a ( Ti poI t em&X, Apont ador *P) {
Apont ador Aux;

i f ( *P == NULL) {
cout << " Er r o: Regi st r o no est na r vor e! " ;
get char ( ) ;
}
el se {
i f ( X. Codi go < ( *P) - >I t em. Codi go) {
Ret i r a ( X, &( *P) - >Esq) ;
}
el se {
i f ( X. Codi go > ( *P) - >I t em. Codi go) {
Ret i r a ( X, &( *P) - >Di r ) ;
}
el se {
i f ( ( *P) - >Di r == NULL) {
Aux = *P;
X = ( *P) - >I t em;
*P = ( *P) - >Esq;
f r ee( Aux) ;
}
el se {
i f ( ( *P) - >Esq ! = NULL) {
Ant ecessor ( *P, &( *P) - >Esq) ;
}
el se {
Aux = *P;
X = ( *P) - >I t em;
*P = ( *P) - >Di r ;
f r ee( Aux) ;
}
}
}
}
}
}

voi d Cami nhament oCent r al ( Apont ador P) {
i f ( P ! = NULL) {
Cami nhament oCent r al ( P- >Esq) ;
cout << " \ nCdi go: " << P- >I t em. Codi go;
cout << " \ nNome : " << P- >I t em. Nome << " \ n" ;
Cami nhament oCent r al ( P- >Di r ) ;

eddiesaliba@yahoo.com ICQ-45923544 52
}
}

i nt Menu ( ) {
i nt Opcao;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - I nser i r " ;
cout << " \ n 2 - Excl ui r " ;
cout << " \ n 3 - Pesqui sar " ;
cout << " \ n 4 - I mpr i mi r " ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 4) ) ;
f f l ush( st di n) ;
r et ur n ( Opcao) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
Ti poDi ci onar i o Di c; / * Cr i a uma r vor e. */
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
i nt Opcao, RegEncont r ado;

/ * Faz a Fi l a f i car vazi a. */
I ni ci al i za( &Di c) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
/ * Li mpa Aux. */
Aux. Codi go = 0;
Aux. Nome[ 0] = ' \ 0' ;

swi t ch ( Opcao) {
case 1: / * I nser i r */
syst em( " CLS" ) ;
cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;
cout << " \ nDi gi t e umNome: " ;
get s( Aux. Nome) ;

I nser e ( Aux, &Di c) ;
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em" ;
cout << " \ n============\ n\ n" ;

cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;


eddiesaliba@yahoo.com ICQ-45923544 53
Ret i r a ( Aux, &Di c) ;

br eak;

case 3: / * Pesqui sa */
syst em( " CLS" ) ;
cout << " Pesqui sar I t em" ;
cout << " \ n==============\ n\ n" ;

cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;

Pesqui sa ( &Aux, &Di c, RegEncont r ado) ;

i f ( RegEncont r ado)
cout << " \ nRegi st r o encont r ado. \ n\ n" ;
el se
cout << " \ nRegi st r o no encont r ado. " ;

get char ( ) ;
br eak;

case 4: / * I mpr i mi r */
syst em( " CLS" ) ;
cout << " I mpr i mi r I t ens" ;
cout << " \ n===============\ n\ n" ;

Cami nhament oCent r al ( Di c) ;

get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}

8.2. rvores Binrias de Pesquisa Com Balanceamento


Fig. 12 rvore Binria de Pesquisa Completamente Balanceada
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007

eddiesaliba@yahoo.com ICQ-45923544 54

Para uma distribuio uniforme das chaves, segundo Ziviani (1996:117), onde
cada chave igualmente provvel de ser usada em uma pesquisa, a rvore
completamente balanceada
1
minimiza o tempo mdio de pesquisa. Entretanto, o
custo para manter a rvore completamente balanceada aps cada insero muito
alto. Por exemplo, para inserir a chave 1 na rvore esquerda na Fig. 12 e obter a
rvore direita na mesma figura, necessrio movimentar todos os nodos da rvore
original.
Uma das formas de contornar este problema procurar uma soluo
intermediria que possa manter a rvore quase balanceada, ao invs de
completamente balanceada. O objetivo procurar obter bons tempos de pesquisa,
prximos do tempo timo da rvore completamente balanceada, mas sem pagar
muito para inserir ou retirar da rvore.
Existem inmeras heursticas fundamentadas nos princpios acima. Gonnet e
Baeza-Yates apud Ziviani (1996:118) apresentam algoritmos que utilizam vrios
critrios de balanceamento para rvores de pesquisa, tais como restries impostas
na diferena das alturas de subrvores de cada nodo da rvore, na reduo do
comprimento do caminho interno
2
da rvore ou que todos os nodos externos
apaream no mesmo nvel.

8.3. rvores SBB (Symmetric Binary B-trees)

De acordo com Ziviani (1996:118), as rvores B foram apresentadas por
Bayer e McCreight, como uma estrutura para memria secundria.
Um caso especial da rvore B apropriado para memria primria a rvore 2-
3, onde cada nodo tem duas ou trs subrvores.
Bayer apud Ziviani (1996:118) mostrou que as rvores 2-3 podem ser
representadas por rvores binrias, conforme mostrado na figura 13, a seguir:


Fig. 13 Uma rvore 2-3 e a rvore Binria correspondente
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007


1
Em uma rvore completamente balanceada os nodos externos aparecem em no mximo dois nveis adjacentes.
2
O comprimento do caminho interno corresponde soma dos comprimentos dos caminhos entre a raiz e cada um
dos nodos internos da rvore. Por exemplo, o comprimento do caminho interno da rvore esquerda na Fig. 08
igual a 8 =(0 +1 +1 +2 +2 +2).

eddiesaliba@yahoo.com ICQ-45923544 55
A rvores SBB uma rvores binria com dois tipos de apontadores,
chamados de verticais e horizontais, onde:

- Todos os caminhos da raiz at cada nodo externo possuem o mesmo nmero
de apontadores verticais, e
- No podem existir dois apontadores horizontais sucessivos.

Vejamos na figura 14, a seguir, um exemplo de rvore SBB:


Fig. 14 rvore SBB
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007

eddiesaliba@yahoo.com ICQ-45923544 56

8.3.1. Manuteno da rvore SBB

Segundo Ziviani (1996:119), o algoritmo para rvores SBB usa
transformaes locais no caminho de insero ou retirada para preservar o
balanceamento. A insero ou retirada de uma chave sempre feita aps o
apontador vertical mais baixo na rvore. Dependendo da situao anterior insero
ou retirada, podem aparecer dois apontadores horizontais sucessivos e, neste caso,
faz-se necessrio realizar uma transformao. Se uma transformao realizada, a
altura da subrvore transformada um mais do que a altura da subrvore original, o
que pode provocar outras transformaes ao longo do caminho de pesquisa, at a
raiz da rvore.

A figura 15, a seguir, mostra as transformaes propostas por Bayer apud
Ziviani (1996:120), onde transformaes simtricas podem ocorrer.


Fig. 15 Transformaes propostas por Bayer
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007


eddiesaliba@yahoo.com ICQ-45923544 57

Vejamos agora, um exemplo de crescimento de uma rvore SBB (figura 16),
atravs da insero de diversas chaves em uma rvore inicialmente vazia. Onde:

- rvore esquerda obtida aps a insero das chaves 7, 10, 5.
- rvore do meio obtida aps a insero das chaves 2, 4 na rvore anterior.
- rvore direita obtida aps a insero das chaves 9, 3, 6 na rvore anterior.


Fig. 16 Crescimento de uma rvore SBB
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007

A seguir, a figura 17 mostra a decomposio da rvore SBB mostrada na
figura 16 (rvore mais a direita). Onde:

- A rvore esquerda obtida aps a retirada da chave 7 da rvore direita
acima.
- A rvore do meio obtida aps a retirada da chave 5 da rvore anterior.
- A rvore direita obtida aps a retirada da chave 9 da rvore anterior.


Fig. 17 Decomposio de uma rvore SBB
Fonte: <http://www.dcc.ufmg.br/algoritmos/transparencias.php>Acesso em: 19 nov.
2007

Para as rvores SBB, faz-se necessrio distinguir dois tipos de alturas. Uma
delas a altura vertical h, necessria para manter a altura uniforme e obtida atravs
da contagem do nmero de apontadores verticais em qualquer caminho entre a raiz
e um nodo externo. A outra a altura k, que representa o nmero mximo de
comparaes de chaves obtido atravs da contagem do nmero total de
apontadores no maior caminho entre a raiz e um nodo externo. A altura k maior
que a altura h sempre que existirem apontadores horizontais na rvore. (Ziviani,
1996, p. 126-127)



eddiesaliba@yahoo.com ICQ-45923544 58
A seguir, o software implementando o conceito de rvore SBB:


#i ncl ude <cst dl i b>
#i ncl ude <i ost r eam>

usi ng namespace st d;

t ypedef enum{ Ver t i cal , Hor i zont al } I ncl i nacao;

t ypedef st r uct Ti poI t em{
i nt Codi go;
char Nome[ 50] ;
};

t ypedef st r uct Nodo_Est {
Ti poI t emI t em;
Nodo_Est *Esq;
Nodo_Est *Di r ;
I ncl i nacao Bi t E, Bi t D;
} Nodo;

voi d EE ( Nodo **Ap) {
Nodo *Ap1;
Ap1 = ( *Ap) - >Esq;
( *Ap) - >Esq = Ap1- >Di r ;
Ap1- >Di r = *Ap;
Ap1- >Bi t E = Ver t i cal ;
( *Ap) - >Bi t E = Ver t i cal ;
*Ap = Ap1;
}

voi d ED ( Nodo **Ap) {
Nodo *Ap1, *Ap2;

Ap1 = ( *Ap) - >Esq;
Ap2 = Ap1- >Di r ;
Ap1- >Bi t D = Ver t i cal ;
( *Ap) - >Bi t E = Ver t i cal ;
Ap1- >Di r = Ap2- >Esq;
Ap2- >Esq = Ap1;
( *Ap) - >Esq = Ap2- >Di r ;
Ap2- >Di r = *Ap;
*Ap = Ap2;
}

voi d DD ( Nodo **Ap) {
Nodo *Ap1;

Ap1 = ( *Ap) - >Di r ;
( *Ap) - >Di r = Ap1- >Esq;
Ap1- >Esq = *Ap;
Ap1- >Bi t D = Ver t i cal ;
( *Ap) - >Bi t D = Ver t i cal ;
*Ap = Ap1;
}

voi d DE ( Nodo **Ap) {
Nodo *Ap1, *Ap2;


eddiesaliba@yahoo.com ICQ-45923544 59
Ap1 = ( *Ap) - >Di r ;
Ap2 = Ap1- >Esq;
Ap1- >Bi t E = Ver t i cal ;
( *Ap) - >Bi t D = Ver t i cal ;
Ap1- >Esq = Ap2- >Di r ;
Ap2- >Di r = Ap1;
( *Ap) - >Di r = Ap2- >Esq;
Ap2- >Esq = *Ap;
*Ap = Ap2;
}

voi d I I nser e ( Ti poI t emX, Nodo **Ap, I ncl i nacao *I Ap, i nt *Fi m) {
i f ( *Ap == NULL) {
*Ap = ( Nodo *) mal l oc ( si zeof ( Nodo) ) ;
*I Ap = Hor i zont al ;
( *Ap) - >I t em= X;
( *Ap) - >Bi t E = Ver t i cal ;
( *Ap) - >Bi t D = Ver t i cal ;
( *Ap) - >Esq = NULL;
( *Ap) - >Di r = NULL;
*Fi m= 0;
}
el se {
i f ( X. Codi go < ( *Ap) - >I t em. Codi go) {
I I nser e ( X, &( *Ap) - >Esq, &( *Ap) - >Bi t E, Fi m) ;
i f ( ! *Fi m) {
i f ( ( *Ap) - >Bi t E ! = Hor i zont al ) {
*Fi m= 1;
}
el se {
i f ( ( *Ap) - >Esq- >Bi t E == Hor i zont al ) {
EE( Ap) ;
*I Ap = Hor i zont al ;
}
el se {
i f ( ( *Ap) - >Esq- >Bi t D == Hor i zont al ) {
ED( Ap) ;
*I Ap = Hor i zont al ;
}
}
}
}
}
i f ( X. Codi go <= ( *Ap) - >I t em. Codi go) {
cout << " Er r o : Chave j est na r vor e! \ n" ;
*Fi m= 1;
}
el se {
I I nser e ( X, &( *Ap) - >Di r , &( *Ap) - >Bi t D, Fi m) ;
i f ( ! *Fi m) {
i f ( ( *Ap) - >Bi t D ! = Hor i zont al ) {
*Fi m= 1;
}
el se {
i f ( ( *Ap) - >Di r - >Bi t D == Hor i zont al ) {
DD( Ap) ;
*I Ap = Hor i zont al ;
}
el se {
i f ( ( *Ap) - >Di r - >Bi t E == Hor i zont al ) {

eddiesaliba@yahoo.com ICQ-45923544 60
DE( Ap) ;
*I Ap = Hor i zont al ;
}
}
}
}
}
}
}

voi d I nser e ( Ti poI t emX, Nodo **Ap) {
i nt Fi m;
I ncl i nacao I Ap;

I I nser e ( X, Ap, &I Ap, &Fi m) ;
}

voi d I ni ci al i za ( Nodo **Di c) {
*Di c = NULL;
}

voi d EsqCur t o ( Nodo **Ap, i nt *Fi m) {
/ * Fol ha esquer da r et i r ada => r vor e cur t a na al t ur a esquer da. */
Nodo *Ap1;

i f ( ( *Ap) - >Bi t E == Hor i zont al ) {
( *Ap) - >Bi t E = Ver t i cal ;
*Fi m= 1;
}
el se {
i f ( ( *Ap) - >Bi t D == Hor i zont al ) {
Ap1 = ( *Ap) - >Di r ;
( *Ap) - >Di r = Ap1- >Esq;
Ap1- >Esq = *Ap;
*Ap = Ap1;
i f ( ( *Ap) - >Esq- >Di r - >Bi t E == Hor i zont al ) {
DE( &( *Ap) - >Esq) ;
( *Ap) - >Bi t E = Ver t i cal ;
}
el se {
i f ( ( *Ap) - >Esq- >Di r - >Bi t D == Hor i zont al ) {
DD( &( *Ap) - >Esq) ;
( *Ap) - >Bi t E = Ver t i cal ;
}
*Fi m= 1;
}
}
el se {
( *Ap) - >Bi t D = Hor i zont al ;
i f ( ( *Ap) - >Di r - >Bi t E == Hor i zont al ) {
DE( Ap) ;
*Fi m= 1;
}
el se {
i f ( ( *Ap) - >Di r - >Bi t D == Hor i zont al ) {
DD( Ap) ;
*Fi m= 1;
}
}
}

eddiesaliba@yahoo.com ICQ-45923544 61
}
}

voi d Di r Cur t o( Nodo **Ap, i nt *Fi m) {
/ * Fol ha di r ei t a r et i r ada => r vor e cur t a na al t ur a di r ei t a. */
Nodo *Ap1;

i f ( ( *Ap) - >Bi t D == Hor i zont al ) {
( *Ap) - >Bi t D = Ver t i cal ;
*Fi m= 1;
}
el se {
i f ( ( *Ap) - >Bi t E == Hor i zont al ) {
Ap1 = ( *Ap) - >Esq;
( *Ap) - >Esq = Ap1- >Di r ;
Ap1- >Di r = *Ap;
*Ap = Ap1;
i f ( ( *Ap) - >Di r - >Esq- >Bi t D == Hor i zont al ) {
ED( &( *Ap) - >Di r ) ;
( *Ap) - >Bi t D = Ver t i cal ;
}
el se {
i f ( ( *Ap) - >Di r - >Esq- >Bi t E == Hor i zont al ) {
EE( &( *Ap) - >Di r ) ;
( *Ap) - >Bi t D = Ver t i cal ;
}
}
*Fi m= 1;
}
el se {
( *Ap) - >Bi t E = Hor i zont al ;
i f ( ( *Ap) - >Esq- >Bi t D == Hor i zont al ) {
ED( Ap) ;
*Fi m= 1;
}
el se {
i f ( ( *Ap) - >Esq- >Bi t E == Hor i zont al ) {
EE( Ap) ;
*Fi m= 1;
}
}
}
}
}

voi d Ant ecessor ( Nodo *Q, Nodo **R, i nt *Fi m) {
i f ( ( *R) - >Di r ! = NULL) {
Ant ecessor ( Q, &( *R) - >Di r , Fi m) ;
i f ( ! *Fi m)
Di r Cur t o( R, Fi m) ;
}
el se {
Q- >I t em= ( *R) - >I t em;
Q = *R;
*R = ( *R) - >Esq;
f r ee( Q) ;

i f ( *R ! = NULL)
*Fi m= 1;
}

eddiesaliba@yahoo.com ICQ-45923544 62
}

voi d I Ret i r a ( Ti poI t emX, Nodo **Ap, i nt *Fi m) {
Nodo *Aux;

i f ( *Ap == NULL) {
cout << " Chave no est na r vor e! \ n" ;
*Fi m= 1;
}
el se {
i f ( X. Codi go < ( *Ap) - >I t em. Codi go) {
I Ret i r a( X, &( *Ap) - >Esq, Fi m) ;
i f ( ! *Fi m)
EsqCur t o( Ap, Fi m) ;
}
el se {
i f ( X. Codi go > ( *Ap) - >I t em. Codi go) {
I Ret i r a( X, &( *Ap) - >Di r , Fi m) ;
i f ( ! *Fi m)
Di r Cur t o( Ap, Fi m) ;
}
el se {
*Fi m= 0;
Aux = *Ap;
i f ( Aux- >Di r == NULL) {
*Ap = Aux- >Esq;
i f ( *Ap ! = NULL)
*Fi m= 1;
}
el se {
i f ( Aux- >Esq == NULL) {
*Ap = Aux- >Di r ;
i f ( *Ap ! = NULL)
*Fi m= 1;
}
el se {
Ant ecessor ( Aux, &Aux- >Esq, Fi m) ;
i f ( ! *Fi m)
EsqCur t o( Ap, Fi m) ;
}
}
}
}
}
}

voi d Ret i r a( Ti poI t emX, Nodo **Ap) {
i nt Fi m;

I Ret i r a( X, Ap, &Fi m) ;
}

voi d Cami nhament oCent r al ( Nodo *P) {
i f ( P ! = NULL) {
Cami nhament oCent r al ( P- >Esq) ;
cout << " \ nCdi go: " << P- >I t em. Codi go;
cout << " \ nNome : " << P- >I t em. Nome << " \ n" ;
Cami nhament oCent r al ( P- >Di r ) ;
}
}

eddiesaliba@yahoo.com ICQ-45923544 63

voi d Pesqui sa ( Ti poI t em*X, Nodo **P, i nt &Encont r ou) {
Encont r ou = 0;
i f ( *P == NULL) {
r et ur n; / * r vor e vazi a. */
}
el se {
i f ( X- >Codi go < ( *P) - >I t em. Codi go) {
Pesqui sa( X, &( *P) - >Esq, Encont r ou) ;
r et ur n;
}
el se {
i f ( X- >Codi go > ( *P) - >I t em. Codi go) {
Pesqui sa( X, &( *P) - >Di r , Encont r ou) ;
}
el se {
/ * Ret or na 1 caso o r egi st r o est ej a na r vor e. */
Encont r ou = 1;
r et ur n;
}
}
}
}

i nt Menu ( ) {
i nt Opcao;

do {
syst em( " CLS" ) ;
cout << " Escol ha uma opo\ n" ;
cout << " =================\ n" ;
cout << " \ n 1 - I nser i r " ;
cout << " \ n 2 - Excl ui r " ;
cout << " \ n 3 - Pesqui sar " ;
cout << " \ n 4 - I mpr i mi r " ;
cout << " \ n 0 - Sai r \ n" ;
cout << " \ nOpo: " ;
ci n >> Opcao;
} whi l e ( ( Opcao < 0) | | ( Opcao > 4) ) ;
f f l ush( st di n) ;
r et ur n ( Opcao) ;
}

i nt mai n( i nt ar gc, char *ar gv[ ] )
{
Nodo *Di c; / * Cr i a uma r vor e. */
Ti poI t emAux; / * Auxi l i ar par a ent r ada de dados. */
i nt Opcao,
RegEncont r ado;

/ * Faz a Fi l a f i car vazi a. */
I ni ci al i za( &Di c) ;

Opcao = Menu ( ) ;
whi l e ( Opcao ! = 0) {
/ * Li mpa Aux. */
Aux. Codi go = 0;
Aux. Nome[ 0] = ' \ 0' ;

swi t ch ( Opcao) {

eddiesaliba@yahoo.com ICQ-45923544 64
case 1: / * I nser i r */
syst em( " CLS" ) ;
cout << " I nser i r I t em" ;
cout << " \ n============\ n\ n" ;
cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;
cout << " \ nDi gi t e umNome: " ;
get s( Aux. Nome) ;

I nser e ( Aux, &Di c) ;
br eak;

case 2: / * Excl ui r */
syst em( " CLS" ) ;
cout << " Excl ui r I t em" ;
cout << " \ n============\ n\ n" ;

cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;

Ret i r a ( Aux, &Di c) ;
br eak;

case 3: / * Pesqui sa */
syst em( " CLS" ) ;
cout << " Pesqui sar I t em" ;
cout << " \ n==============\ n\ n" ;

cout << " \ nDi gi t e umCdi go: " ;
ci n >> Aux. Codi go;
f f l ush( st di n) ;

Pesqui sa ( &Aux, &Di c, RegEncont r ado) ;

i f ( RegEncont r ado)
cout << " \ nRegi st r o encont r ado. \ n\ n" ;
el se
cout << " \ nRegi st r o no encont r ado. " ;

get char ( ) ;
br eak;

case 4: / * I mpr i mi r */
syst em( " CLS" ) ;
cout << " I mpr i mi r I t ens" ;
cout << " \ n===============\ n\ n" ;

Cami nhament oCent r al ( Di c) ;

get char ( ) ;
}
Opcao = Menu ( ) ;
}

syst em( " PAUSE" ) ;
r et ur n EXI T_SUCCESS;
}


eddiesaliba@yahoo.com ICQ-45923544 65

8.4. Exerccio

1) Se copiarmos os cdigos apresentados para o compilador, veremos que
funcionam perfeitamente. Contudo, no se pode provar, atravs do simples
funcionamento do software, que uma pesquisa numa rvore SBB pode ser mais
eficiente que em uma rvore Binria sem balanceamento (levando-se em
considerao que ambas tero as mesmas chaves). Assim sendo, pede-se: Crie
um software, onde se faa a entrada de chaves aleatrias idnticas, numa rvore
binria sem balanceamento e, em seguida, esta mesma chave em uma rvore
SBB. Certifique-se de entrar com um nmero considervel de chaves, para que
se possa medir o tempo de pesquisa das chaves. Implemente um mecanismo em
seu software, em que se possa solicitar a pesquisa de existncia de uma
determinada chave; esta pesquisa dever ser feita em ambas as rvores, e o
tempo de resposta dever ser medido e mostrado como resultado para que se
possa comparar a eficincia de uma rvore e de ou outra.

eddiesaliba@yahoo.com ICQ-45923544 66

9. Bibliografia


FUNDAMENTOS DE LINGUAGEM C: Tudo que voc precisa saber sobre C para no
passar vergonha!, Centro Tecnolgico de Mecatrnica. Caxias do Sul, RS, 1997

MIZRAHI, Victorine Viviane. Treinamento em Linguagem C : Curso Completo Mdulo
1, So Paulo:McGraw-Hill, 1990

MIZRAHI, Victorine Viviane. Treinamento em Linguagem C : Curso Completo Mdulo
2, So Paulo:McGraw-Hill, 1990

SANTOS, Wellington Lima dos. Algoritmos e Estruturas de Dados II : Exerccios Listas
Lineares. UFGD/FACET Disponvel em: <
http://www.ufgd.edu.br/~wlsantos/Algo/ListasLineares_Exercicios.pdf>Acesso em: 27 nov.
2007

TENENBAUM, M. Aaron; LANGSAM, Yedidyah; AUGENSTEIN, Moshe J . Estrutura de
Dados Usando C. So Paulo: Pearson, 1995

ZIVIANI, Nivio. Projeto de Algoritmos : com implementaes em Pascal e C. 3 ed., So
Paulo: Pioneira, 1996

Anda mungkin juga menyukai