




























Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
material para estudo
Tipologia: Notas de estudo
1 / 36
Esta página não é visível na pré-visualização
Não perca as partes importantes!





























struct { char primeiro[10]; char inicialmeio; char ultimo[20]; } nome; typedef struct { char primeiro[10]; char inicialmeio; char ultimo[20]; } TIPONOME; TIPONOME nome, snome, fulano;
#include
Primeira etapa: se n = 1 mova o disco de A para C (sem auxiliar) (origem para destino) senão transfira n-1 discos de A (origem) para B (destino), usando C (auxiliar) mova disco n de A para C (origem para destino) transfira n-1 discos de B (origem) para C (destino), usando A (auxiliar) Segunda etapa: Como a passagem dos parâmetros é sempre: torre A, torre B (auxiliar) e torre C, pois esta é a seqüência das 3 torres, os parâmetros devem ser manipulados na chamada recursiva da rotina Hanoi, respeitando a lógica dos algoritmos:
início limpa tela hanoi(3,'A','B','C') fim
Hanoi (int n, char origem, auxiliar, destino); início se (n=1) então Escrever (“1. Mova disco 1 da torre”, origem, “ para ” , destino) senão Escrever (“2.”) Hanoi( n-1 , origem , destino , auxiliar) Escrever (“3. Mova disco” ,n, “da torre”, origem, “ para ” ,destino) Hanoi( n-1 , auxiliar , origem , destino) fim_se fim
Série de Fibonacci A série de Fibonacci é a seguinte: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... Para fins de implementação, a série inicia com fib(0) e cada termo n é referenciado por fib(n-1), ou seja o 1o^ termo é fib(0), o 2o^ termo é fib(1) e assim sucessivamente. Com exceção dos dois primeiros, cujos valores são pré- determinados (0 e 1), cada elemento da seqüência sempre será a soma dos dois elementos anteriores. Ex: fib(2) = 0+1 = 2, fib(3) = 1+1 = 2, fib(4) = 2+1 = 3, fib(5) = 2+3 = 5, ... Podemos então definir a série de Fibonacci através da seguinte definição recursiva: Fib(n) = n se n== 0 ou n== Fib(n) = Fib(n-2) + fib(n-1) se n >= Dessa forma, Fib(4) seria então: Fib(4) = Fib(2) + Fib(3) = Fib(0) + Fib(1) + Fib(3) = 0 + 1 + Fib(3) = 1 + Fib(1) + Fib(2) = 1 + 1 + Fib(0) + Fib(1) = 2 + 0 + 1 = 3 A C A B C A C A B C A B C
Para implementarmos uma pilha seqüencial precisamos de uma variável (Topo) indicando o endereço da mais recente informação colocada na pilha. Por convenção, se a pilha está vazia, o Topo = -1. O tamanho da Pilha é limitado pelo tamanho do vetor.
3.1.1. Inserção
3.1.2 Retirada Na retirada deve-se:
using namespace std;
Como poderia ser feita a inserção e retirada no caso de se utilizar mais do que uma pilha?
Implemente em laboratório:
Queremos garantir que os parênteses estejam corretamente agrupados, ou seja, desejamos verificar se: a) Existe um número igual de parênteses esquerdos e direitos. Expressões como “A((A + B)” ou “A + B(” violam este critério. b) Todo parêntese da direita está precedido por um parêntese da esquerda correspondente. Expressões como “)A+B(-C” ou “(A+B))-(C+D” violam este critério.
UM EXEMPLO: INFIXO, POSFIXO E PREFIXO Esta seção examinará uma importante aplicação que ilustra os diferentes tipos de pilhas e as diversas operações e funções definidas a partir delas. O exemplo é, em si mesmo, um relevante tópico de ciência da computação. Considere a soma de A mais B. Imaginamos a aplicação do operador "+" sobre os operandos A e B, e escrevemos a soma como A + B. Essa representação particular é chamada infixa. Existem três notações alternativas para expressar a soma de A e B usando os símbolos A, B e +. São elas:
Quando operadores sem parênteses e da mesma ordem de precedência são avaliados, pressupõe-se a ordem da esquerda para a direita, exceto no caso da exponenciação, em que a ordem é supostamente da direita para a esquerda. Sendo assim, A + B + C significa (A + B) + C, enquanto A ^ B ^ C significa A ^ (B ^ C). Usando parênteses, podemos ignorar a precedência padrão. Uma questão imediatamente óbvia sobre a forma posfixa de uma expressão é a ausência de parênteses. Examine as duas expressões, A + (B * C) e (A + B) * C. Embora os parênteses em uma das expressões sejam supérfluos [por convenção, A + B * C = A + (B * C)], os parênteses na segunda expressão são necessários para evitar confusão com a primeira. As formas posfixas dessas expressões são: Forma Infixa Forma Posfixa
Considerando a expressão: a/b^c + de - ac Os operandos são: Os operadores são: O primeiro passo a saber é qual a ordem de prioridade dos operadores:
Após, basta utilizarmos uma pilha para transformarmos a expressão Ex: A+BC em ABC+
No final, basta juntarmos a saída ao que restou da pilha (desempilhando um a um) à saída: ABC * + Note que em (1) o operador * foi colocado na pilha sobre o operador +. Isso se deve ao fato de que a prioridade do * é maior do que a do +. Sempre que a prioridade de um elemento a empilhar for maior do que a prioridade do último elemento da pilha, esse elemento deverá ser empilhado. Quando a prioridade do elemento a empilhar for menor ou igual ao último elemento que está na pilha, deve-se então adotar o seguinte procedimento: desempilhar elementos até que fique como último elemento da pilha, algum elemento com prioridade menor do que o elemento que se está empilhando. Caso não houver na pilha nenhum elemento com prioridade menor do que o elemento que se está empilhando, fica somente o elemento que se está empilhando. Os demais saem para a saída.
Entra: + Entra: - Entra: * Saem: *- Sai: * Saem: ^ /
Início da solução Alguns passos devem ser considerados aqui para a resolução do problema: ● Leia o Problema cuidadosamente: leia cada linha do problema cuidadosamente. Após desenvolver a solução, leia atentamente a descrição do erro. Confira atentamente as entradas e saídas do problema. ● Não pressuponha entradas: sempre há um conjunto de entradas para exemplo de um problema. Para testar, deve-se utilizar mais casos para entrada, números negativos, números longos, números fracionários, strings longas. Toda entrada que não for explicitamente proibida é permitida. Deve se cuidar a ordem de entrada também, pois quando pede-se por exemplo para verificar um intervalo entre 2 números, estes 2 números podem estar em ordem crescente ou decrescente e assim por diante. ● Não se apressar: nem sempre a eficiência é fundamental, portanto não deve-se preocupar com isso a menos que isso seja um predicado do problema. Deve-se ler a especificação para aprender o máximo possível sobre o tamanho da entrada e decidir qual algoritmo pode resolver o problema para aquela determinada entrada de dados. Neste caso específico a eficiência não precisa ser uma grande preocupação. Sugestão para implementação Existem muitas maneiras diferentes para verificar a prioridade de um elemento no trabalho de implementação. Uma sugestão seria criar uma estrutura com 2 vetores ELEM[10] e PRI[10]. Procura-se inicialmente o operador no vetor ELEM. Ao encontrá-lo, pega-se a prioridade na mesma posição do vetor PRI. Exemplos:
3.2. FILA (QUEUE) Filas mantém a ordem (first in, first out). Um baralho com cartas pode ser modelado como uma fila, se retirarmos as cartas em cima e colocarmos as carta de volta por baixo. Outro exemplo seria a fila de um banco. As operações de inserção são efetuadas no final e as operações de retirada são efetuadas no início. A inserção de um elemento torna-o último da lista (fila). As operações abstratas em uma fila incluem:
Uma fila com 5 elementos, sem nenhum deles ter sido retirado é apresentada abaixo: fila.dados: A F C G B queue.first queue.last pseudo-algoritmo de inserção de uma fila:
pseudo-algoritmo de retirada de uma fila:
/* Queue.cpp. Baseado no algoritmo queue.c do livro do Steven Skiena (2002) e atualizado por Neilor Tonin em 03/01/2008. Implementation of a FIFO queue abstract data type. */
Quando a carta virada dos dois jogadores tem o mesmo valor acontece então a guerra. Estas cartas ficam na mesa e cada jogador joga mais duas cartas. A primeira com a face para baixo, e a segunda com a face para cima. A carta virada com a face para cima que for maior vence, e o jogador que a jogou leva as 6 cartas que estão na mesa. Se as cartas com a face para cima de ambos os jogadores tiverem o mesmo valor, a guerra continua e cada jogador volta a jogar uma carta com a face para baixo e outra com a face para cima. Se algum dos jogadores fica sem cartas no meio da guerra, o outro jogador automaticamente vence. As cartas são adicionadas de volta para os jogadores na ordem exata que elas foram distribuídas, ou seja a primeira carta própria (jogada pelo próprio jogador), a primeira carta do oponente, a segunda carta própria, a segunda carta jogada pelo oponente e assim por diante... Como qualquer criança de 5 anos, sabe-se que o jogo de guerra pode levar um longo tempo para terminar. Mas quanto longo é este tempo? O trabalho aqui é escrever um programa para simular o jogo e reportar o numero de movimentos. Construção do monte de cartas Qual a melhor estrutura de dados para representar um monte de cartas? A resposta depende do que se quer fazer com elas. Está se tentando embaralhá-las? Comparar seus valores? Pesquisar por um padrão na pilha. As intenções é que vão definir as operações na estrutura de dados. A primeira ação que necessitamos fazer é dar as cartas do topo e adicionar outras na parte de baixo do monte. Portanto, é natural que cada jogador utilize uma fila (estrutura FIFO) definida anteriormente. Mas aqui têm-se um problema fundamental. Como representar cada carta? Têm-se as naipes (Paus, Copas, Espada e Ouro) e valores na ordem crescente (2-10, valete, rainha, rei e Ás). Têm-se diversas escolhas possíveis. Pode-se representar cada carta por um par de caracteres ou números especificando a naipe e valor. No problema da GUERRA, pode-se ignorar as naipes – mas tal pensamento pode trazer um problema. Como saber que a implementação da Fila está funcionando perfeitamente? A primeira operação na GUERRA é comparar o valor da face das cartas. Isso é complicado de fazer com o primeiro caracter da representação, porque deve-se comparar de acordo com o ordenamento histórico dos valores da face. Uma lógica Had Hoc parece necessária para se lidar com este problema. Cada carta deverá ter um valor de 0 a 13. Ordena-se os valores das cartas do menor ao maior, e nota-se que há 4 cartas distintas de cada valor. Multiplicação e divisão são a chave para mapeamento de 0 até 51. #include
void embaralha ( int perm[NCARDS+ 1 ]){ randomize(); int a,b,i,aux; for (i = 0 ; i <= 20 ; i++){ a= rand()% 52 ; b= rand()% 52 ; aux = perm[a]; perm[a]=perm[b]; perm[b]=aux; } } void random_init_decks(queue *a, queue *b){ int i; // counter int perm[NCARDS+ 1 ]; for (i= 0 ; i<NCARDS; i=i+ 1 ) { perm[i] = i; } embaralha(perm); init_queue(a); init_queue(b); for (i= 0 ; i<NCARDS/ 2 ; i=i+ 1 ) { enqueue(a,perm[ 2 *i]); enqueue(b,perm[ 2 *i+ 1 ]); } //cout << endl << "CARTAS: " << endl; //print_card_queue(a); //cout << endl << "CARTAS: " << endl; //print_card_queue(b); } void war(queue *a, queue b) { int steps= 0 ; / step counter / int x,y; / top cards / queue c; / cards involved in the war / bool inwar; / are we involved in a war? */ inwar = FALSE; init_queue(&c); while ((!empty(a)) && (!empty(b) && (steps < MAXSTEPS))) { print_card_queue(a); cout << endl; print_card_queue(b); cout << endl << endl; steps = steps + 1 ; x = dequeue(a); y = dequeue(b); // x e y possuem valores de 0 até 51 cout << x <<":"<< value(x) <<suits[x%NSUITS] <<" "<<y<<":"<<value(y)<< suits[y%NSUITS] << endl; enqueue(&c,x); enqueue(&c,y); if (inwar) { inwar = FALSE; } else { if (value(x) > value(y)) clear_queue(&c,a); else if (value(x) < value(y)) clear_queue(&c,b); else if (value(y) == value(x)) inwar = TRUE; } } cout << "Cartas nas pilhas A: " << a->count << " B: " << b->count << endl; if (!empty(a) && empty(b)) cout << "a venceu em " << steps << " jogadas " << endl; else if (empty(a) && !empty(b)) cout << "b venceu em " << steps << " jogadas " << endl; else if (!empty(a) && !empty(b)) cout << "jogo empatado apos " << steps << " jogadas" << endl; else cout << "jogo empatado apos " << steps << " jogadas" << endl; } int main(){ queue a,b; int i; random_init_decks(&a,&b); war(&a,&b); return ( 0 ); } Problemas (exercícios) complementares 10038, 10315, 10050, 843, 10205, 10044, 10258 (páginas 42 até 54) - livro Steven Skiena e Miguel Revilla (http://icpcres.ecs.baylor.edu/onlinejudge/)
4.2 Seleção Direta Consiste em encontrar a menor chave por pesquisa sequencial. Encontrando a menor chave, essa é permutada com a que ocupa a posição inicial do vetor, que fica então reduzido a um elemento. O processo é repetido para o restante do vetor, sucessivamente, até que todas as chaves tenham sido selecionadas e colocadas em suas posições definitivas. Uma outra variação deste método consiste em posicionar-se no primeiro elemento e aí ir testando-o com todos os outros (segundo)... (último), trocando cada vez que for encontrado um elemento menor do que o que está na primeira posição. Em seguida passa-se para a segunda posição do vetor repetindo novamente todo o processo. Ex: ... Exercício: considerando o vetor: 9 25 10 18 5 7 15 3 Ordene-o pelo método de seleção direta: 4.3 Inserção Direta O método de ordenação por Inserção Direta é o mais rápido entre os outros métodos considerados básicos – Bubblesort e Seleção Direta. A principal característica deste método consiste em ordenarmos o arranjo utilizando um sub-arranjo ordenado localizado em seu inicio, e a cada novo passo, acrescentamos a este sub-arranjo mais um elemento, até que atingimos o último elemento do arranjo fazendo assim com que ele se torne ordenado. Realmente este é um método difícil de se descrever, então vamos passar logo ao exemplo. Consideremos inicialmente um arranjo qualquer desordenado: Inicialmente consideramos o primeiro elemento do arranjo como se ele estivesse ordenado, ele será considerado o o sub-arranjo ordenado inicial :
Agora o elemento imediatamente superior ao o sub-arranjo ordenado, no o exemplo o número 3, deve se copiado para uma variável auxiliar qualquer. Após copiá-lo, devemos percorrer o sub-arranjo a partir do último elemento para o primeiro. Assim poderemos encontrar a posição correta da nossa variável auxiliar dentro do sub-arranjo : No caso verificamos que a variável auxiliar é menor que o último elemento do o sub-arranjo ordenado ( o o sub- arranjo só possui por enquanto um elemento, o número 5 ). O número 5 deve então ser copiado uma posição para a direita para que a variável auxiliar com o número 3, seja colocada em sua posição correta : Verifique que o sub-arranjo ordenado possui agora dois elementos. Vamos repetir o processo anterior para que se continue a ordenação. Copiamos então mais uma vez o elemento imediatamente superior ao o sub-arranjo ordenado para uma variável auxiliar. Logo em seguida vamos comparando nossa variável auxiliar com os elementos do sub- arranjo, sempre a partir do último elemento para o primeiro : Neste caso verificamos que a nossa variável auxiliar é menor que o último elemento do sub-arranjo. Assim, copiamos este elemento para a direita e continuamos com nossas comparações : Aqui, mais uma vez a nossa variável auxiliar é menor que o elemento do sub-arranjo que estamos comparando. Por isso ele deve ser copiado para a direita, abrindo espaço para que a variável auxiliar seja colocada em sua posição correta : Verifique que agora o sub-arranjo ordenado possui 3 elementos. Continua-se o processo de ordenação copiando mais uma vez o elemento imediatamente superior ao o sub-arranjo para a variável auxiliar. Logo em seguida vamos comparar essa variável auxiliar com os elementos do o sub-arranjo a partir do último elemento : Veja que nossa variável auxiliar é menor que o elemento que está sendo comparado no o sub-arranjo. Então ele deve ser copiado para a direita para que continuemos com nossas comparações :