Beruflich Dokumente
Kultur Dokumente
Pilhas
Uma pilha uma das vrias estruturas de dados que admitem remoo de elementos e insero de novos elementos. Mais especificamente, uma pilha (= stack ) uma estrutura sujeita seguinte regra de operao: sempre que houver uma remoo, o elemento removido o que est na estrutura h menos tempo. Em outras palavras, o primeiro objeto a ser inserido na pilha o ltimo a ser removido. Essa poltica conhecida pela sigla LIFO (= Last-In-First-Out ). Veja o verbete Stack (data structure) na Wikipedia.
Implementao em um vetor
Suponha que nossa pilha est armazenada em um vetor p i l h a [ 0 . . n 1 ] . Suponha ainda que os elementos de p i l h aso nmeros inteiros. (Isto s um exemplo; os elementos de p i l h a poderiam ser objetos de qualquer outro tipo.) A parte do vetor ocupada pela pilha ser p i l h a [ 0 . . t 1 ].
0 t N 1
O ndice tindica o topo (= top) da pilha. Esta a primeira posio vaga da pilha. A pilha est vazia se tvale 0e cheia se tvale n . Para remover um elemento da pilha esta operao conhecida como desempilhar (= to pop) faa
x=p i l h a [ t ] ;
Isso equivale ao par de instrues "t=1 ;x=p i l h a [ t ] ; " nesta ordem. claro que voc s deve desempilhar se tiver certeza de que a pilha no est vazia. Para consultar a pilha sem desempilhar faa x = p i l h a [ t 1 ] . Para inserir ou seja, para empilhar (= to push) um objeto yna pilha faa
p i l h a [ t + + ]=y ;
Isso equivale ao par de instrues "p i l h a [ t ]=y ;t+ =1 ; " nesta ordem. Antes de empilhar, verifique se a pilha j est cheia para evitar que ela transborde (ou seja, para evitar um overflow). Em geral, a tentativa de inserir em uma pilha cheia uma situao excepcional,
Exerccios
1. Suponha que, diferentemente da conveno adotada no texto, a parte do vetor ocupada pela pilha p i l h a [ 0 . . t ] . Escreva a instruo que remove um elemento da pilha. Escreva a instruo que insere um objeto yna pilha. 2. Escreva funes e m p i l h ae d e s e m p i l h apara manipular uma pilha. Lembre-se de que uma pilha um pacote com dois objetos: um vetor e um ndice. No use variveis globais. Quais os parmetros de suas funes?
Suponha que a sequncia de parnteses e colchetes est armazenada em uma cadeia de caracteres (= string) s . Como hbito em C, o ltimo caractere da cadeia o caractere nulo, ' \ 0 ' .
/ /Af u n od e v o l v e1s eac a d e i asc o n t mu m as e q u n c i a / /b e m f o r m a d ad ep a r n t e s e sec o l c h e t e sed e v o l v e0s e / /as e q u n c i ae s t m a l f o r m a d a . i n tb e m F o r m a d a (c h a rs [ ] ) { c h a r* p i l h a ;i n tt ; i n tn ,i ; n=s t r l e n (s ) ; p i l h a=m a l l o c c (n*s i z e o f( c h a r ) ) ; t=0 ; f o r( i=0 ;s [ i ]! =' \ 0 ' ;+ + i ){ / /ap i l h ae s t a r m a z e n a d an ov e t o rp i l h a [ 0 . . t 1 ] s w i t c h( s [ i ] ){ c a s e' ) ' :i f( t! =0& &p i l h a [ t 1 ]= =' ( ' ) t ; e l s er e t u r n0 ; b r e a k ; c a s e' ] ' :i f( t! =0& &p i l h a [ t 1 ]= =' [ ' ) t ; e l s er e t u r n0 ;
b r e a k ; d e f a u l t : p i l h a [ t + + ]=s [ i ] ; } } r e t u r nt= =0 ; }
(Eu deveria ter invocado f r e e (p i l h a ) antes de cada r e t u r n . S no fiz isso para no obscurecer a lgica da funo.) Note que a pilha no transborda porque nunca ter mais elementos que o nmero de caracteres de s .
Exerccios
Eis algumas questes sobre a funo b e m F o r m a d a : 3. A funo funciona corretamente se stem apenas dois elementos? apenas um? nenhum? 4. Mostre que no incio de cada iterao sest bem-formada se e somente se a sequncia p i l h a [ 0 . . t 1 ]s [ i . . . ] estiver bem-formada. 5. Escreva uma verso melhorada da funo b e m F o r m a d aque desaloque o vetor p i l h aantes de terminar a execuo da funo. [Soluo]
infixa
( A + B * C ) ( A * ( B + C ) / D E )
posfixa
A B C * + A B C + * D / E -
( A + B * ( C D * ( E F ) G * H ) I * 3 )A B C D E F * G H * * + I 3 * ( A + B * C / D * E F ) ( A + ( B ( C + ( D ( E + F ) ) ) ) ) A B C * D / E * + F A B C D E F + + +
( A * ( B + ( C * ( D + ( E * ( F + G ) ) ) ) ) )A B C D E F G + * + * + *
A notao posfixa dispensa parnteses. A ordem dos operandos a mesma nas expresses infixa e posfixa. Nosso problema:
Traduzir para notao posfixa a expresso infixa armazenada em uma cadeia de caracteres i n f . Para simplificar nossa vida, vamos supor que a expresso infixa est correta e consiste apenas de letras, abre-parntese, fecha-parntese e smbolos para as quatro operaes aritmticas. Vamos supor tambm que cada nome de varivel tem uma letra apenas. Finalmente, vamos supor que a expresso toda est embrulhada em um par de parnteses, isto , i n f [ 0 ]vale ' ( 'e os dois ltimos elementos de i n fso ' ) 'e ' \ 0 ' . Usaremos uma pilha para resolver o problema. Como a expresso infixa est embrulhada em um par de parnteses, no precisamos nos preocupar com pilha vazia!
/ /Af u n oa b a i x or e c e b eu m ae x p r e s s oi n f i x ai n fe / /d e v o l v eac o r r e s p o n d e n t ee x p r e s s op o s f i x a . c h a r* i n f i x a P a r a P o s f i x a (c h a ri n f [ ] ){ c h a r* p o s f ; c h a r* p i ;i n tt ;/ /p i l h a i n tn ,i ,j ; n=s t r l e n (i n f ) ; p o s f=m a l l o c c (n*s i z e o f( c h a r ) ) ; p i=m a l l o c c (n*s i z e o f( c h a r ) ) ; t=0 ; p i [ t + + ]=i n f [ 0 ] ; / /e m p i l h a' ( ' f o r( j=0 ,i=1 ;/ * X * /i n f [ i ]! =' \ 0 ' ;+ + i ){ / /ap i l h ae s t e mp i [ 0 . . t 1 ] s w i t c h( i n f [ i ] ){ c h a rx ; c a s e' ( ' :p i [ t + + ]=i n f [ i ] ; / /e m p i l h a b r e a k ; c a s e' ) ' :w h i l e( 1 ){ / /d e s e m p i l h a x=p i [ t ] ; i f( x= =' ( ' )b r e a k ; p o s f [ j + + ]=x ; } b r e a k ; c a s e' + ' : c a s e' ' :w h i l e( 1 ){ x=p i [ t 1 ] ; i f( x= =' ( ' )b r e a k ; t ; / /d e s e m p i l h a p o s f [ j + + ]=x ; } p i [ t + + ]=i n f [ i ] ; / /e m p i l h a b r e a k ; c a s e' * ' : c a s e' / ' :w h i l e( 1 ){ x=p i [ t 1 ] ; i f( x= =' ( '| |x= =' + '| |x= =' ' ) b r e a k ; t ; p o s f [ j + + ]=x ; } p i [ t + + ]=i n f [ i ] ; b r e a k ; d e f a u l t : p o s f [ j + + ]=i n f [ i ] ; }
} f r e e (p i ) ; p o s f [ j ]=' \ 0 ' ; r e t u r np o s f ; }
[Veja outra maneira de escrever a funo tirando proveito dos recursos sintticos da linguagem C.] Constantes e variveis vo diretamente de i n fpara p o s f . Abre-parntese vai para a pilha. Ao encontrar um fecha-parntese, a funo remove tudo da pilha at o abreparntese inclusive. Ao encontrar um +ou -a funo desempilha tudo at um abre-parntese exclusive. Ao encontrar um *ou /desempilha tudo at um abre-parntese ou um +ou um . Eis o resultado da aplicao da funo expresso infixa ( A * ( B * C + D ) ). A tabela abaixo registra os valores das variveis a cada passagem pelo ponto X :
i n f [ 0 . . i 1 ] ( ( A ( A * ( A * ( ( A * ( B ( A * ( B * ( A * ( B * C ( A * ( B * C + ( A * ( B * C + D ( A * ( B * C + D ) ( A * ( B * C + D ) ) p i [ 0 . . t 1 ] p o s f [ 0 . . j 1 ] ( ( A ( * A ( * ( A ( * ( A B ( * ( * A B ( * ( * A B C ( * ( + A B C * ( * ( + A B C * D ( * A B C * D + A B C * D + *
Exerccios
6. Aplique o algoritmo de converso para a notao posfixa expresso aritmtica
( A+B )*D+E/( F+A*D )+C
7. Considere a funo i n f i x a P a r a P o s f i x a . Suponha que a expresso infixa i n ftem ncaracteres (sem contar o ' \ 0 'final). Que tamanho a pilha p ipode atingir, no pior caso? Em outras palavras, qual o valor mximo da varivel tno pior caso? Que acontece se o nmero de abre-parnteses na expresso for limitado (menor que 6, por exemplo)? 8. No cdigo da funo i n f i x a P a r a P o s f i x a , alguns casos tm um w h i l e( 1 ) . Escreva uma nova verso sem esses w h i l e . (Dica: troque o f o rexterno por um w h i l eapropriado.) 9. Reescreva a funo i n f i x a P a r a P o s f i x asem supor que a expresso infixa est embrulhada em um par de parnteses. 10. Reescreva a funo i n f i x a P a r a P o s f i x asupondo que a expresso pode ter parnteses e colchetes.
Exerccios
12. VALOR DE EXPRESSO POLONESA. Suponha que p o s f uma string que guarda uma expresso aritmtica em notao posfixa. Suponha que p o s fno vazio e contm somente os operadores + , , * e / (todos exigem dois operandos). Suponha tambm que a expresso no tem constantes e que todos os nomes de variveis na expresso consistem de uma nica letra maiscula (A ,...,Z ). Suponha ainda que temos um vetor t a b e l aque d os valores das variveis (todas as variveis tm valores inteiros):
t a b e l a [ 0 ] o
valor da varivel A , t a b e l a [ 1 ] o valor da varivel Betc. Escreva uma funo que calcule o valor da expresso p o s f . Cuidado com divises por zero! 13. Escreva um algoritmo que use uma pilha para inverter a ordem das letras de cada palavra de uma string, preservando a ordem das palavras. Por exemplo, dado o texto E S T EE X E R C I C I OEM U I T OF A C I L a sada deve ser E T S EO I C I C R E X EE O T I U ML I C A F . (Lembre-se: strings em C terminam com ' \ 0 ' .) 14. Digamos que nosso alfabeto formado pelas letras a , be c . Considere o seguinte conjunto de cadeias de caracteres sobre nosso alfabeto:
c , a c a , b c b , a b c b a , b a c a b , a a c a a , b b c b b ,
...
Qualquer cadeia deste conjunto tem a forma Wc M, onde W uma sequncia de letras que s contm ae be M o inverso de W, ou seja, M W lido de trs para frente. Escreva um programa que determina se uma cadeia X pertence ou no ao nosso conjunto, ou seja, determina se X da forma Wc M. 15. PERMUT AES PRODUZIDAS PELO DESEMPILHAR. Suponha que os inteiros 1,2,3,4 so colocados, nesta ordem, numa pilha inicialmente vazia. Depois de empilhar cada inteiro, voc pode retirar zero ou mais elementos da pilha. Cada elemento desempilhado impresso numa folha de papel. Por exemplo, a sequncia de operaes empilha 1, empilha 2, desempilha, empilha 3, desempilha, desempilha, empilha 4, desempilha, produz a impresso da sequncia 2,3,1,4. Quais das 24 permutaes de 1,2,3,4 podem ser obtidas desta maneira?
tipo c e l u l a :
t y p e d e fs t r u c tc e l{ i n t c o n t e u d o ; s t r u c tc e l* p r o x ; }c e l u l a ;
Decises de projeto: Vamos supor que nossa lista tem uma clula-cabea (ou seja, vamos supor que a primeira clula da lista no faz parte da pilha). Vamos supor que o topo da pilha est na segunda clula e no na ltima (por qu?). A pilha pode ser criada e inicializada assim:
c e l u l ac a b e c a ; c e l u l a* t p ; t p=& c a b e a ; t p > p r o x=N U L L ;
Para ter acesso pilha, s preciso do ponteiro t p . De acordo com nossa deciso de projeto, teremos sempre t p== & c a b e c a . A pilha est vazia se t p > p r o x== N U L L .
/ /I n s e r eu me l e m e n t oyn ap i l h at p . v o i de m p i l h a (i n ty ,c e l u l a* t p ){ c e l u l a* n o v a ; n o v a=m a l l o c c (s i z e o f( c e l u l a ) ) ; n o v a > c o n t e u d o=y ; n o v a > p r o x =t p > p r o x ; t p > p r o x=n o v a ; } / /R e m o v eu me l e m e n t od ap i l h at p . / /S u p eq u eap i l h an oe s t v a z i a . / /D e v o l v eoe l e m e n t or e m o v i d o . i n td e s e m p i l h a (c e l u l a* t p ){ i n tx ; c e l u l a* p ; p=t p > p r o x ; x=p > c o n t e u d o ; t p > p r o x=p > p r o x ; f r e e (p ) ; r e t u r nx ; }
Exerccios
16. Implemente um pilha em uma lista encadeada sem clula-cabea (s pra ver ver que dor de cabea isso d!). A pilha ser dada pelo endereo da primeira clula da lista (que tambm o topo da pilha). 17. Reescreva as funes b e m F o r m a d ae i n f i x a P a r a P o s f i x aarmazenando a pilha em uma lista encadeada. 18. Resolva o problem da intercalao de duas listas ordenadas.
19. Suponha dada uma lista encadeada que armazena nmeros inteiros. Cada clula da lista tema estrutura abaixo.
s t r u c tc e l{ i n t c o n t e u d o ; s t r u c tc e l* p r o x ; } ;
Escreva uma funo que transforme a lista em duas: a primeira contendo as clulas cujo contedo par e a segunda aquelas cujo contedo mpar.
A execuo do programa prossegue da seguinte maneira: Um espao de trabalho criado para a funo m a i ne colocado na pilha de execuo. O espao contm as variveis locais i ,j , ke y . A execuo de m a i ncomea.
No ponto 1 , a execuo de m a i n temporariamente interrompida e um espao de trabalho para a funo F colocado na pilha. Esse espao contm os parmetros i ,j , kda funo (com valores 1 1 1 ,2 2 2e 4 4 4respectivamente) e a varivel local x . Comea ento a execuo de F . No ponto 2 , a execuo de F interrompida e um espao de trabalho para a funo G colocado na pilha. Esse espao contm os parmetros ae bda funo (com valores 1 1 1e 2 2 2respectivamente) e a varivel local x . Em seguida, comea a execuo de G . Quando a execuo de Gtermina, a funo devolve 3 3 3 . O espao de trabalho de G removido da pilha e descartado. O espao de trabalho de F(que agora est no topo da pilha de execuo) reativado e a execuo retomada no ponto 3 . A primeira instruo executada "x=3 3 3 ; ". Quando a execuo de Ftermina, a funo devolve 7 7 7 . O espao de trabalho de F removido da pilha e descartado. O espao de trabalho de m a i n(que agora est no topo da pilha) reativado e a execuo retomada no ponto 4 . A primeira instruo executada "y=7 7 7 ; ". No nosso exemplo, Fe Gso funes distintas. Mas tudo funcionaria da mesma maneira se Fe Gfossem idnticas, ou seja, se Ffosse uma funo recursiva.
Exerccios
20. Considere a funo recursiva abaixo. Escreva uma verso iterativa da funo que simule o comportamento da verso recursiva. Use uma pilha.
i n tT T T (i n tx [ ] ,i n tn ){ i f( n= =0 )r e t u r n0 ; i f( x [ n ]>0 )r e t u r nx [ n ]+T T T (x ,n 1 ) ; e l s er e t u r nT T T (x ,n 1 ) ; }
URL of this site: www.ime.usp.br/~pf/algoritmos/ Last modified: Tue Apr 23 08:06:54 BRT 2013 Paulo Feofiloff IME-USP