1 / 18

Árvores com valores em todos os nós

Árvores com valores em todos os nós.

avani
Download Presentation

Árvores com valores em todos os nós

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Árvores com valores em todos os nós Existe também a função flatten que retorna a lista de valores que estão nos nós da árvores. A ordem pela qual este valores são compostos é, usualmente chamada, de inorder. Ou seja, o valor do nó de topo é colocado entre as listas correspondentes aos valores dos nós das sub-árvores esquerda e direita, que são ordenadas de forma similar. fun flatten Empty = [ ] | flatten (Tr (t1, a, t2)) = flatten t1 @ [a] @ flatten t2 Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  2. Árvores com valores em todos os nós Se pretendermos uma ordem diferente para os valores da lista podemos definir as funções: fun preorder Empty = [ ] | preorder (Tr (t1, a, t2)) = [a] @ preorder t1 @ preorder t2 fun postorder Empty = [ ] | postorder (Tr (t1, a, t2)) = postorder t1 @ postorder t2 @ [a] Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  3. Árvores com valores em todos os nós Podemos introduzir ainda uma função genérica sobre árvores (análoga a btreeop). Esta função recebe como argumento um valor constante, uma função g e uma árvore. A constante é retornada no caso da árvore ser Empty, caso contrário, a função g é usada para combinar os resultados do processamento recursivo das sub-árvores esquerda e direita: fun treeop c g Empty = c | treeop c g (Tr (t1, a, t2)) = g (treeop c g t1, a, treeop c g t2) Ao contrário da função btreeop, neste caso decidiu-se que a função g não está na forma curried, recebendo assim um triplo de argumentos. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  4. Árvores com valores em todos os nós Usualmente estas árvores são usadas quando se pretende manter uma colecção de items ordenados e o uso de uma lista torna as inserções muito ‘caras’ e consequentemente ineficientes. Podemos comprovar este facto pela análise da implementação de um algoritmo de ordenação de árvores, que é usado para ordenar listas. O algoritmo é semelhante a uma mistura do quicksort com o insert sort, onde é usada uma árvore para organizar o posicionamento dos elementos. À medida que a árvore é percorrida, os elementos são inseridos na posição correcta e assim, quando a árvore é achatada (flatten) a lista resultante está ordenada. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  5. Árvores com valores em todos os nós fun treeinsert Empty m = leaf m | treeinsert (Tr (t1, n, t2)) m = if (lessthan n) m (i.e. m<n) then Tr (treeinsert t1 m, n, t2) else Tr (t1, n, treeinsert t2 m) fun treesort x = flatten (accumulate treeinsert Empty x) A ordenação funciona da seguinte forma: começa por receber uma árvore vazia vai acumulando os elementos na árvore, através da função treeinsert, com cada elemento da lista recebida como argumento, de cada vez. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  6. Árvores com valores em todos os nós As árvores intermédias estão sempre ordenadas porque se começa a partir da lista vazia, usando apenas a função treeinsert que preserva a ordem. A lista final é obtida simplesmente por achatamento da árvore assim obtida. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  7. Notação ZF para listas Introduz-se agora uma notação para listas que não é standard ML. Essa notação é chamada ZF e permite denotar de forma sucinta aquelas listas que resultam da aplicação encadeada das funções map, link e filter, embora tenha correspondência na notação standard. Um caso em que esta notação se torna muito conveniente é o da função permutations que será apresentada como exemplo. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  8. Notação ZF para listas A forma mais simples que a notação ZF pode assumir é: [E | V1  E1] em que E1 é uma expressão do tipo lista onde a variável V1 toma valores. Por sua vez E é uma expressão em que V1 pode ocorrer. Para cada valor possível para V1 tem-se o valor correspondente para E. Ao componente da forma V1  E1 dá-se o nome de gerador uma vez que este é usado para gerar a lista de valores para V1 a partir da lista denotada por E1. A expressão completa é chamada de lista em compreensão, mas a notação é também conhecida por notação ZF, que vem do nome Zermelo-Fraenkel. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  9. Notação ZF para listas Um exemplo da notação ZF será: [2*x | x  1 upto 5] que denota a lista [2*1, 2*2, 2*3, 2*4, 2*5] = [2, 4, 6, 8, 10] Podemos também definir a função sum usando a notação ZF. A função sum recebe uma função g e soma os valores g(y), em que y varia de 0 a x. fun sum g x = sumlist [g y | y  0 upto x] Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  10. Notação ZF para listas A notação ZF pode ser generalizada da seguinte forma: [E | V1  E1; V2  E2; ...; Vn  En] Aqui cada uma das variáveis locais Vi toma valores na lista que lhe corresponde Ei e E pode envolver ocorrências de todos os Vis. Além disso cada Ei pode envolver ocorrências dos Vjs precedentes (1 j < i). Assim, o verdadeiro significado é que Ei pode depender dos valores tomados por V1, V2, ..., Vi-1. Por exemplo [x* y | x  1 upto 20; y  1 upto x] denota a lista [1*1, 2*1, 2*2, ..., 20*1, ..., 20*20] Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  11. Notação ZF para listas Para encontrar a lista denotada por expressões do tipo indicado basta fixar uma a uma as variáveis V1, V2, ... fazendo variar as de índice mais elevado. Eis um exemplo que se torna muito difícil de expressar se não usarmos a notação ZF. A função permutations calcula todas as permutações dos elementos de uma lista, retornando uma lista de listas. Faz-se ainda uso de uma função infixa - - que remove a primeira ocorrência de um dado elemento de uma lista. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  12. Notação ZF para listas fun permutations [] = [[]] | permutations x = [a::y | a  x, y  permutations (x - - a)] infix - - fun [] - - a = [] | (a::x) - - a = x | (b::x) - - a = b::(x - - a) - - : = list X =  = list permutations: = list  (= list) list Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  13. Notação ZF para listas permutations: = list  (= list) list - - : = list X =  = list A lista de permutações de uma lista vazia é [[]], uma vez que [] é uma permutação da lista vazia. Para uma lista não vazia x, as permutações são calculadas como todas as listas da forma a::y onde a é um elemento de x e y é uma permutação de x tendo sido removido o elemento a. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  14. Notação ZF para listas Outra extensão útil da notação ZF é permitir condições para qualificar um gerador para que os elementos da lista gerada que não satisfaçam a condição sejam filtrados. Assim um gerador pode ter a forma Vi  Ei; B onde a condição B será uma expressão booleana, envolvendo algumas variáveis dos geradores precedentes (V1, ..., Vi). Por exemplo fun ordcart x y = [(a,b) | a  x; b  y; a < b] ordcart: int list  int list  (int x int) list define a lista de pares da forma (a, b), tal que a vem de x, b vem de y e a < b. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  15. Notação ZF para listas Para traduzir (expandir) listas na notação ZF para ML, basta compreender o significado da referida notação. Assim, uma possível correspondente em ML da expressão [E | V1  E1] é dada por map (fn V1  E) E1 que não é mais do que a lista de possíveis valores que E toma quando o parâmetro da função anónima, V1, é substituído pelos valores da lista E1 via map. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  16. Notação ZF para listas Generalizando, para encontrar a correspondente em ML da expressão [E | V1  E1; V2  E2; ...; Vn  En] basta notar que esta expressão é quase equivalente a (fixando V1) [[E | V2  E2; ...; Vn  En] | V1  E1] mas como esta expressão forma uma lista de listas, se utilizarmos a função link obtemos uma expressão exactamente equivalente à primeira: link [[E | V2  E2; ...; Vn  En] | V1  E1] Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  17. Notação ZF para listas E, fazendo uso da primeira regra enunciada tem-se link (map (fn V1  [E | V2  E2; ...; Vn  En]) E1) Por último, a tradução de [E | V1  E1; V2  E2; ...; Vn  En; B] é dada, naturalmente por filter B’ [E | V1  E1; V2  E2; ...; Vn  En] em que B’ representa o predicado contido em B. Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

  18. Notação ZF para listas No caso do exemplo apresentado [(a,b) | a  x; b  y; a < b] em que B é a < b,B’ será o predicado par_ordenado definido da seguinte forma fun par_ordenado (x, y) = x < y e teremos a seguinte correspondência filter par_ordenado [(a,b) | a  x; b  y] Programação em Lógica e Funcional (2000/01) (Actualizado em 2004/05)

More Related