Você está na página 1de 13

Conceito de Estrutura de Dados

A estrutura de dados uma disciplina que trabalha com mtodos de


organizao lgica dos dados, dando-lhes atributos mais funcionais do que se
estivessem sem qualquer tipo de estruturao.
Dentre as vrias atividades da estrutura de dados, esto o
desenvolvimento de estruturas clssicas, como pilhas, filas, listas, deques,
rvores! mtodos de pesquisa "pesquisa linear, pesquisa binria#, mtodos de
ordenao, ou classificao, "$ooble %ort, &uic' %ort, (eap %ort, etc#, entre
outras.
Atualmente, uma grande fatia da performance dos grandes programas
dependente da efici)ncia das estruturas de dados utilizadas na sua
implementao.
Tipos Abstratos de Dados
*ipos abstratos de dados so tipos criados arbitrariamente pelo
programador, sem que este+am definidos na linguagem de programao como
tipos de dados primitivos.
,a realidade, os tipos abstratos de dados so uni-es de tipos de dados
primitivos e, at mesmo, outros tipos abstratos de dados, formando uma .nica
estrutura, semelhante a uma ficha com vrios campos, sendo que a ficha
corresponde ao registro "ou struct, como chamada em /# e os campos
correspondem 0s variveis internas da struct.
1s tipos abstratos de dados devem ser previamente declarados antes de
serem utilizados, ou se+a, antes de ser declarada uma varivel com seu tipo. 1
acesso aos dados de uma 2struct3 so realizados atravs de uma varivel de
acesso, declarada com o mesmo tipo do nome atribu4do ao registro.
5eralmente os tipos abstratos de dados so utilizados onde h a
necessidade de armazenar diversos dados semelhantes referentes a um mesmo
tipo de entidade. 6or e7emplo, os dados sobre funcionrios, sobre carros, sobre
pessoas, clientes, etc.
Abai7o, um e7emplo de declarao de uma struct para armazenar dados
sobre um funcionrio8
struct endereco 9
char rua:;<=!
char bairro:><=!
char complemento:?<=!
int numero!
@!
struct funcionario 9
char nomeAcompleto:B<<=!
struct endereco endAfuncionario!
int idade!
float salario!
@!
Cepare que a declarao possui tipos de dados primitivos "int, char, float#
e abstratos "struct endereco#.
A fim de acessar um campo da struct funcionrio, devemos criar uma
varivel do seu tipo8
struct funcionario f!
Assim, a varivel f do tipo funcionrio, possuindo todos os campos
listados na declarao do tipo de dado funcionrio.
6ara acessar um campo desta varivel, procede-se assim8
f.nomeAcompleto, f.idade, f.salario
6ara acessar um campo de um tipo abstrato de dado dentro de outro tipo,
faz-se8
f.endAfuncionario.rua, f.endAfuncionario.bairro
ESTRUTURAS DE DADOS CLSSICAS
PILHA
A pilha uma estrutura de dados que se assemelha a uma pilha do mundo
real "uma pilha de livros, de pratos, de /DDs, etc#.
A pilha baseia-se na idia de que os elementos so empilhados
seqEencialmente, uns sobre os outros, sendo o elemento presente no topo o
.ltimo a ter sido nela colocado.
A retirada de elementos seqEencial e apenas o elemento do topo pode
ser retirado. Fm outras palavras8
O primeiro elemento a ser colocado o ltimo a ser retirado! O
ltimo elemento a ser colocado o primeiro a ser retirado!
*al afirmao, em ingl)s, gerou a sigla LI"O #Last In$ "irst Out% para
designar as pilhas.
As principais opera-es que podem ser realizadas em uma pilha so8
Gnserir elemento no topo
Cetirar elemento do topo
Histar Flementos
/ontar elementos
Gnicializar a pilha
6esquisar por elemento
As pilhas so declaradas como tipos abstratos de dados, sendo o m4nimo
necessrio para seu funcionamento8
um vetor, cu+o tamanho representa o tamanho m7imo a que a pilha pode
chegar
uma varivel inteira, responsvel por controlar o topo da pilha.
Ie+a como seria declarar uma pilha em /8
struct pilha 9
int vet:B<=!
int topo!
@!
Deste modo, declaramos uma pilha que ter no m7imo B< elementos
inteiros empilhados.
A fim de utilizarmos suas fun-es bsicas, devemos inicializ-la, criando
uma varivel do tipo pilha, primeiramente.
struct pilha p!
1 pr7imo passo obrigatrio inicializar o valor do topo. J recomendvel
que tal inicializao se+a feita em uma funo espec4fica para este fim.
void inicializa"void# 9
p.topo K -B!
@
Fmbora o valor do topo possa ser inicializado com zero, muito mais
conveniente e prtico inicializ-lo com -B!
Aps terem sido efetuados todos os procedimentos acima descritos,
podemos comear a escrever as funcionalidades bsicas de pilha8
Gnsero
A insero insere um elemento no topo da pilha.
J conveniente checar, antes de cada insero, se a pilha no ir ser
estourada caso um novo elemento se+a inserido.
int insercao"int elemento# 9
if"p.topoLM# 9
p.vet:NNp.topo= K elemento!
@else9
printf"2FrroO 6ilha Hotada3#!
@
return <!
@
Ie+a que a insero apenas realizada caso o topo se+a inferior 0 .ltima
posio. /aso contrrio, mesmo que ele se+a igual a .ltima posio "que M, pois
vet:B<= varia de vet:<= at vet:M=#, ocorrer um estouro, visto que o topo
incrementado aps o teste ter sido realizado.
,a linha p.vet:NNp.topo= K elemento! fazemos, primeiramente, o
incremento do topo. /aso se+a a primeira insero "p.topo KK -B, conforme
inicializado#, teremos, antes de a insero ser efetuada, p.topo KK <, graas ao
operador de incremento NN antes de p.topo, o que crucial "/aso voc) coloque
o operador NN aps a varivel, ele colocar o primeiro elemento na posio -B,
pois o incremento ser feito aps a insero. Iale ressaltar que este um erro
grave na programao#.
Cemoo
Assim como na insero fazemos um teste para verificar se o vetor
estourar "overfloP#, na remoo devemos verificar se h elementos a
serem retirados antes de efetuarmos a retirada.
Iale destacar que a pilha estar vazia quando o valor do topo for
igual ao valor que atribu4mos a ele na inicializao! no nosso caso, -B.
Hembre-se que a cada elemento retirado, o valor do topo dever ser
decrementado.
Abai7o, uma funo para retirar elementos da pilha8
int remover "void# 9
if"p.topoQ-B# 9
int removido K p.vet:p.topo=!
p.topo--!
printf"2Ioc) removeu o elemento Rd3, removido#!
@else9
printf"2Frro ao remover elemento. 6ilha vazia.3#!
@
return <!
@
Cepare que atribu4mos 0 varivel 2int removido3 o elemento do topo que
ser removido, para que possamos mostr-lo na tela.
As tr)s linhas que utilizamos aps o 2if3 poder4am ser escritas em uma s8
printf"2Flemento removido8 Rd3, p.vet:p.topo--=#!
Cepare que mostramos o elemento do topo antesde acontecer o
decremento. 1 operador 2--3 aps a varivel do topo nos garante isso.
Histar elementos
6ara listar elementos de uma pilha, utilizamos um lao de repetio de
primeira posio at o topo. /omo nosso topo foi inicializado em -B, ele
est sempre apontando para o .ltimo elemento que foi inserido. Fnto
o lao deve iniciar em zero e fazer repeti-es at que encontremos um
valor superior ao do topo.
for"iK<! iLKp.topo! iNN# 9
printf"2RdSn3, p.v:i=#!
@
Ioc) pode tambm mostrar o elemento do topo acima dos demais, basta
inverter a ordem do lao8
for"iKp.topo! iQK<! i--# 9
printf"2RdSn3, p.v:i=#!
@
/ontar Flementos
1 n.mero de elementos da pilha sempre ser igual ao nosso valor do topo
acrescido de B.
6or e7emplo, quando o topo vale <, significa que + colocamos um
elemento, pois ele foi inicializado com -B.
Assim8
,.mero de elementos da pilha K valor do topo N B!
Hogo, quando p.topo KK <8
,.mero de elementos da pilha K < N B
,.mero de elementos da 6ilha K B
Fm linguagem /8
int contaFlementos"void# 9
printf"2A pilha possui Rd elementos. 2, p.topoNB#!
return <!
@
6esquisa
6ara pesquisar um elemento, e7ecutamos um lao semelhante ao que
e7ecutamos para mostrar todos os elementos da pilha. Ambos percorrem a pilha
inteira, entretanto, enquanto um apenas imprime os elementos, o outro, faz
compara-es entre os elementos que esto na pilha e o elemento que o usurio
quer buscar.
int busca "int elementoAprocurado# 9
int i!
int flag K <!
for"iK<! iLKp.topo! iNN# 9
if"elementoAprocurado KK p.vet:i=# 9
flagNN!
@
@
if"flagQ<# 9
printf"21 elemento foi encontrado Rd vezes na pilha3, flag#!
@else9
printf"21 elemento no foi encontrado na pilha.3#!
@
return <!
@
Cepare que a varivel inteira flag inicializada com < e incrementada
caso encontremos na pilha um elemento igual ao procurado.
Aps termos pesquisado por toda a pilha "ou se+a, o lao ter-se e7ecutado
totalmente#, caso a flag tenha valor superior a zero, sinal que encontramos o
elemento pelo qual procurvamos. /aso contrrio, ele no foi encontrado.
"ILA
A fila segue um padro semelhante ao da pilha, alteram-se apenas as
caracter4sticas referentes a insero de elementos. Tma fila se assemelha a uma
fila de pessoas, na qual a primeira pessoa a chegar a primeira a sair. As
.ltimas pessoas que chegam ocupam as .ltimas posi-es da fila e so as .ltimas
a sair dela.
A sigla UGU1 a e7plicao genrica da fila8 Uirst Gn, Uirst 1ut. 1u se+a, o
primeiro a entrar nela , tambm, o primeiro a sair.
Fm uma fila, precisamos controlar a posio do primeiro elemento e do
.ltimo elemento. 6or trabalharmos linearmente, assumimos, por praticidade,
como a posio inicial da fila "aquela que ocupar o elemento que ser o
primeiro a ser removido, quando houver uma remoo# a primeira posio do
vetor, ou se+a, aquela inde7ada por 4ndice <. Deste modo, eliminamos a
necessidade de uma varivel para controlar o seu in4cio, que ser fi7o.
/aso se este+a trabalhando com uma fila circular, esta varivel
obrigatria.
As opera-es que podemos realizar em uma fila so semelhantes 0s
realizadas em uma pilha8
Gnserir elemento no final da fila
Cetirar elemento do in4cio da fila
Histar Flementos
/ontar elementos
Gnicializar a fila
6esquisar por elemento
Ieremos a seguir, como elas funcionam.
Antes de comear a trabalharmos com suas fun-es, devemos declarar o
tipo abstrato de dado fila, a varivel de acesso 0 fila e inicializ-la.
struct fila 9
int vet:B<=!
int fim!
@!
struct fila f!
Ie+a que nossa fila poder ter no m7imo B< elementos.
A fim de inicializ-la, criaremos uma funo espec4fica para isso. 1 valor
inicial da posio fim -B, que indica 2fila vazia3.
void inicializa"void# 9
f.fim K -B!
@
A partir de agora, podemos comear a trabalhar com as opera-es de
nossa fila.
Gnsero
Fm uma fila os elementos so sempre inseridos na .ltima posio, ou se+a,
aquela referenciada pela varivel 2fim3.
A insero de elementos de uma fila bastante semelhante 0 de uma
pilha, fazendo inclusive, o mesmo teste a fim de testar se ela no ser
estourada aps a insero.
int inserir "int elemento# 9
if"f.fimLVAW-B# 9
f.vet:NNf.fim= K elemento!
@else9
printf"2Gmposs4vel inserir elemento. Uila lotada3.#!
@
return <!
@
Cemoo
A remoo de elementos de uma fila bem diferente da de uma
pilha. Fm uma fila, remove-se o primeiro elemento e h a necessidade de fazer
todos os demais elementos da fila avanarem uma posio "e7ceto se voc)
estiver trabalhando com uma fila circular#.
A cada remoo, a varivel responsvel por controlar o fim da fila
deve ser decrementada.
Analogamente 0 pilha, aqui tambm fazemos um teste a fim de
verificar se h elementos a serem removidos, antes de e7ecutarmos a remoo.
int remover "void# 9
if"f.fim Q -B# 9
int i!
int removido K f.vet:<=!
for"iK<! iLf.fim! iNN# 9
f.vet:i= K f.vet:iNB=!
@
f.fim--!
printf"21 elemento Rd foi removido da fila.3, removido#!
@else9
printf"2Frro ao remover elemento. A fila est vazia.3#!
@
return <!
@
,a linha
int removido K f.vet:<=!
guardamos o elemento que foi removido em uma varivel, a fim de mostr-lo ao
usurio aps a remoo ter sido efetuada.
Aps isso, no lao de repetio de zero at a posio final X B "ou
se+a, de iK< at iLf.fim# fazemos todas as posi-es da fila, da segunda at a
.ltima, avanarem uma posio. Assim, sobrepomos o elemento removido "que
estava na primeira posio, 4ndice <# e fazemos a fila 2andar3.
,o se pode esquecer da linha
f.fim--!
que decrementa o ponteiro que aponta para o final da fila, aps
termos e7ecutado o lao.
Vostrar Flementos, /ontar elementos, 6esquisar por Flemento
Fssas tr)s opera-es e7ecutadas em filas so id)nticas como as
e7ecutadas nas pilhas.
Heia como elas so e7plicadas para as pilhas que, certamente,
entender como funcionam para as listas.
A .nica diferena significativa que a varivel de 2topo3 nas pilhas
substitu4da pela varivel de 2fim3, nas filas. *odavia, os procedimentos de
procura, listagem e contagem so e7ecutados da mesma forma.
DE&UE
1 deque consiste em duas pilhas horizontais cu+a base de uma est
em contato direto com a base da outra.
As regras de operao do deque so as seguintes8
1s elementos so inseridos a partir do seu centro. Hogo, cada lado
preenchido do centro 0 lateral.
1s elementos retirados so os das e7tremidades!
Tm lado no pode sobrepor o outro. Assim, deve-se estar atento
para ocorr)ncias de overfloP e underfloP.
As opera-es que podemos e7ecutar em um deque so8
Gnserir elemento 0 esquerda!
Gnserir elemento 0 direita!
Cemover elemento 0 esquerda!
Cemover elemento 0 direita!
Gnicializar deque!
Vostrar deque!
6esquisar no deque "em um dos lados ou nele inteiro#.
/ontar elementos do deque
A seguir, veremos cada uma delas.
G,G/GAHGYAC DF&TF
Tm deque deve ser declarado, no m4nimo, com os seguintes
campos8 um vetor, que ser o prprio deque! um ponteiro que controla o lado
esquerdo! um ponteiro que controla o lado direito.
struct deque 9
int vet:B<=
int ptrdir!
int ptresq!
@!
%eu acesso se d atravs da varivel declarada com seu tipo8
struct deque d!
A inicializao do deque deve estabelecer posi-es iniciais para os
ponteiros. Fm nosso deque, como possui tamanho m7imo de B< elementos,
teremos cinco para cada lado.
Gnicializaremos os ponteiros uma posio alm "NB 0 esquerda e -B 0
direita# da qual ser inserido o primeiro elemento. A razo disso simples8
estaremos decrementando "0 esquerda# e incrementando "0 direita# estes
ponteiros antes da insero do elemento.
Z esquerda, a primeira posio ser > "de < at >, temos ; elementos#.
Assim, o ptresq ser inicializado com valor ;. 1 primeiro elemento 0 direita ser
inclu4do na posio ;. 6ortanto, inicializaremos o ptrdir com o valor >.
void inicializa"void# 9
int d.ptrdir K >!
int d.ptresq K ;!
@
G,%FCGC FHFVF,*1 Z F%&TFCDA
&uando inserimos um elemento 0 esquerda, antes de tudo, devemos
verificar se o lado esquerdo no est lotado. /omo o lado esquerdo vai
at zero e o ponteiro que o controla "ptresq# aponta para o .ltimo
elemento, caso seu valor se+a igual a zero, teremos o lado cheio.
Aps termos feito o teste e verificado que o vetor no est lotado,
decrementamos o ponteiro da esquerda A,*F% de inserir o elemento. "Hembre-
se de que ele foi inicializado na posio posterior 0 primeira posio do lado
esquerdo.
Abai7o, a funo de insero de elemento no lado esquerdo do deque8
int insereFsquerda"int elemento# 9
if"d.ptresqQ<# 9
d.vet:--d.ptresq= K elemento!
@else9
printf"2FrroO 1 deque est lotado 0 esquerda.3#!
@
return <!
@
,ote que, como os elementos so inseridos a partir do centro, devemos
DF/CFVF,*AC o ptresq a cada insero.
G,%FCGC FHFVF,*1 Z DGCFG*A
A insero 0 direita semelhante 0 da esquerda, entretanto, aqui devemos
G,/CFVF,*AC o ponteiro a cada elemento inserido.
1 controle de overfloP aqui feito pela comparao do ponteiro da direita
com o .ltimo elemento do vetor, ou se+a, o valor m7imo X B. ,o nosso e7emplo,
como o vetor de B< elementos, o referencial ser o n.mero M.
J altamente recomendvel utilizar um 2[define VAW B<3 no in4cio do
cdigo a fim de facilitar seu entendimento. /aso isso fosse feito, comparar4amos
ptrdir a VAW X B8 caso fosse menor, poder4amos realizar a insero, caso
contrrio, ou se+a, igual, significa que a .ltima posio + foi ocupada e uma nova
insero provocar um overfloP.
Abai7o, a funo de insero 0 direita8
int insereDireita"int elemento# 9
if"d.ptrdirLVAW-B# 9
d.vet:NNd.ptrdir= K elemento!
@else9
printf"2FrroO 1 deque est lotado 0 direita.3#!
@
return <!
@
CFV1IFC FHFVF,*1 Z F%&TFCDA
Antes de removermos um elemento da esquerda do deque, devemos
nos assegurar de que h elementos a serem removidos.
1 teste feito com a comparao entre o valor do ponteiro da
esquerda "ptresq# e o valor com o qual ele foi inicializado no in4cio do programa
"neste e7emplo, ;#.
/aso ele se+a igual a ;, nosso deque est vazio 0 esquerda e no
poderemos realizar a remoo de elemento. /aso contrrio, procederemos a
remoo de um elemento apenas realizando a 16FCA\]1 /1,*C^CGA 0
realizada na insero.
,a insero 0 esquerda, DF/CFVF,*AV1% ptresq para acomodar um novo
elemento. ,a remoo, G,/CFVF,*AV1% ptresq para que ele faa a e7cluso do
elemento que est 0 e7tremidade esquerda do deque.
Ie+a um e7emplo em funo8
int removeFsquerda"void# 9
if"d.ptresqL;# 9
d.ptresqNN!
@else9
printf"2Gmposs4vel retirar elemento. Deque vazio 0
esquerda.3#!
@
return <!
@
/aso voc) quisesse mostrar o elemento removido, bastaria acrescentar a
linha8
printf"2Rd3, d.vet:ptresq=#!
antes de realizar o incremento.
CFV1IFC FHFVF,*1 Z DGCFG*A
Assim como fizemos na remoo 0 esquerda, na remoo 0 direita tambm
faremos a operao inversa que fizemos na insero neste mesmo lado.
,a insero 0 direita, incrementamos ptrdir. ,a remoo, o
decrementamos.
Da mesma forma, antes de efetuar qualquer alterao no deque,
checamos a consist)ncia de operao de remoo, ou se+a, deve e7istir algum
elemento a ser removido.
/aso o ponteiro da direita "ptrdir# tenha o mesmo valor de sua inicializao
"no nosso e7emplo, >#, isso significa que o lado direito do que est vazio.
Ie+a uma funo de remoo 0 direita8
int removeDireita"void# 9
if"d.ptrdirQ># 9
printf"2Ioc) removeu o elemento8 Rd3, d.vet:d.ptrdir--=#!
@else9
printf"2FrroO Gmposs4vel retirar elemento. Deque vazio 0
direita.3#!
@
return <!
@
Cepare que usamos o operador de decremento aps a varivel d.ptrdir .
Assim, primeiro imprimimos na tela seu conte.do e depois a decrementamos.
6F%&TG%AC FV TV HAD1 D1 DF&TF
A pesquisa em um lado do deque deve percorrer desde a posio em que
ouve a sua inicializao "entretanto, no devemos consider-la, pois ela
faz parte do outro ladoO Apenas G,G/GAHGYAV1% a partir dela, mas as
inser-es so feitas 0 frente "no caso do lado direito# ou atrs "no caso do
lado esquerdo# dela# at a posio do ponteiro que controla o lado.
6or e7emplo, para mostrarmos todos os elementos que esto ao lado
esquerdo do deque8
int mostraFsq"void# 9
int i!
for"iKd.ptresq! iL;! iNN# 9
printf"2Rd3, d.vet:i=#!
@
return <!
@
%e quisermos fazer uma busca nesse lado, bastaria acrescentamos
algumas linhas8
int procuraFsq"int elementoAprocurado# 9
int i!
int flag K <!
for"iKd.ptresq! iL;! iNN# 9
if"d.vet:i= KK elementoAprocurado# 9
flagNN!
@
@
"flag# _ printf"21 elemento foi encontrado Rd vezes3, flag# 8
printf"21 elemento no foi encontrado3#!
return <!
@
1 procedimento 0 direita anlogo. $astaria percorrer o deque a
partir da posio posterior ao qual ele foi inicializado e e7ecutar o lao de
repetio at "inclusive# a posio em que est o ponteiro.
Ie+a a procura 0 direita8
int procuraDir"int elementoAprocurado# 9
int i!
int flag K <!
for"iK;! iLKd.ptrdir! iNN# 9
if"d.vet:i= KK elementoAprocurado# 9
flagNN!
@
@
if"flag# printf"21 elemento foi encontrado Rd vezes3, flag#!
else printf"21 elemento no foi encontrado3#!
return <!
@
6F%&TG%AC ` V1%*CAC *1D1 1 DF&TF
1 procedimento para mostrar ou pesquisar um elemento em todo o deque
trata de percorrer as posi-es e7istentes entre o ponteiro da direita "ptrdir# e o
ponteiro da esquerda "ptresq#.
6ara mostrar todo o deque usar4amos8
int mostraDeque"void# 9
int i!
for"iKd.ptresq! iLKd.ptrdir! iNN# 9
printf"2Rd3,d.vet:i=#!
@
return <!
@
6ara pesquisar um elemento em todo o deque8
int pesquisaDeque"int elementoAprocurado# 9
int i!
int flag K <!
for"iKd.ptresq! iLKd.ptrdir! iNN# 9
if"d.vet:i= KK elementoAprocurado# 9
flagNN!
@
@
if"flag# 9
printf"21 elemento foi encontrado Rd vezes no deque3, flag#!
@else9
printf"21 elemento no foi encontrado no deque.3#!
@
return <!
@
/1,*A,D1 FHFVF,*1% ,1 DF&TF
A contagem de elementos no deque simplesmente realizada em
funo dos ponteiros que apontam para o .ltimo elemento inserido em cada
lado.
Assim, como ptrdir geralmente maior do que ptresq, utilizamos a
operao8
&uantidade de elementos K "ptrdir -ptresq# NB!
Ie+a como inicializamos nossos ponteiros8
void inicializa"void# 9
int d.ptrdir K >!
int d.ptresq K ;!
@
Ie+a que8
&uantidade de elementos K "ptrdir X ptresq# N B KKQ
Assim8
&uantidade de elementos K "> X ;# N B K <
%e inserirmos dois elementos 0 direita, ocorrero dois incrementos
em ptrdir, que passar a valer a.
&uantidade de elementos8 "a-;#N B K b
/aso coloquemos tr)s elementos 0 esquerda do deque, ptresq
sofrer tr)s decrementos, passando a valer b.
&uantidade de elementos8 "a-b# NB K ;
Assim, colocamos dois elementos 0 direita e mais tr)s 0 esquerda,
totalizando cinco elementos no deque.