-
Disciplina: Estrutura de dados - CC - UFC - Quixadá
-
Turma: Ciência da Computação - 2º semestre
-
Equipe:
Henricky de Lima Monteiro (475075)
Elibe Soares Sousa (470820)
-
Professor: Atílio Gomes
-
Agradecimentos: Pedro Henrique Spinnosa
-
Linguagem: C++
-
Data: Outubro 2019
-
Contatos:
[email protected] (Email)
@HenrickyL (Redes Sociais)
O problema consiste em realizar a ordenação de um ou mais vetores utilizando a Estrutura de dados da Árvore Binária, onde, dados, um vetor V de n elementos arbitrários devem ser obtidos de um arquivo (.txt).
Em resumo, o vetor deve ser utilizado criar um arvore binária cheia, ou seja, todas as suas folhas estão na mesma altura, onde todos os valores de suas folhas devem ser preenchidos com os elementos do vetor. Vale lembrar, que uma arvore cheia tem
No processo de reolução do problema foram divididas tarefas para cada integrante de modo que os dois pudessem praticar os conceitos de arvore, percurso e o método de ordenação proposto. Desta forma, foram porposta motodologias de resolução e aplicá-las na resolução do problema. E através destas soluções definir o grau de complexidade pela análise assintotica da mesma.
A divisão de tarefas na resolução e implementação do trabalho foram, relativamente, balanceadas, onde, os alunos se reuníam e discutiam o melhor método de resolução do problema. Quanto a implementação, foram feitas, na sua maioria, em conjunto, onde quem deu a ideia a implementava no papel ou computador, testava e faziam-se os devidos ajustes nos prototipos.
O problema de ordenação de um vetor utilizando uma arvore é um grande problema que pode ser quebrado em problemas menores e através da solução destes resolver o todo. Foi proposto a divisão do problema em três partes, criar as folhas utilizando os elementos do vetor, popular a arvore de baixo para cima através da comparação dos valores das mesmas, e fazer o Percurso e armazenagem dos valores da arvore de modo que retorne o vetor ordenado. E através destes métodos foram implementadas as função auxiliares CreateLeaf, OrdenaCria, e OrdenaVec.
Este trabalho foi escrito em cima dos códigos de Árvore Binária estudados em sala, onde a implementação da árvore consiste em uma estrutura, noArv, que carrega um inteiro int value,e dois ponteiro de nó da mesma estrutura para o filho esquerdo, noArv esq,e direito, noArv dir*. Além disto, uma variável global, int Eglobal, foi criada para salvar o valor do coringa(E) e algumas funções bás icas para trabalhar com estes nós de arvore, como criar um nó vazio, criar um nó com valor e filhos como parâmetro, liberar a memória alocada para os nós da arvore, dentre outras.
Uma função que recebe um vetor v e o seu tamanho n e tem como retorno uma fila(Queue) de ponteiros e nós. Foi pensada para receber o vetor e seu tamanho e retornar uma fila de ponteiros de nós, equivalente as folhas da arvore que vai ser criada, já organizada para ser do tamanho
Esta função utiliza uma função auxiliar, maiorElem(v,n), para obter o maior elemento de um vetor, uma constante k com valor 2 que irá incrementar por 2 em uma repetição com a condição do tamanho maior que k, ou seja, k recebe o valor
Por fim, cria uma fila e adiciona os elementos do vetor a fila até chegar no tamanho do mesmo, depois aficiona o valor do coringa a todos os nós acima de n e menores que k, e retorna a fila.
Uma função iterativa que tem como entrada uma fila de ponteiros de nós e como saída um ponteiro de nó. Ela tem por objetivo criar a arvore de modo que os pais das folhas tenham o valor igual ao menor valor entre seus filhos e isso vale para todos os nós até a raiz.
Esta função utiliza de quatro ponteiros de nósm sendo eles, dois ponteiros que apontam para cada par de folhas(aux1,aux2), um que aponta para o menor deste par (menor) e um ponteiro de nó que vai ser retornado com a raiz da árvore (raiz).
Utiliza-se uma repetição com a condição da fila ter um tamanho diferente de um, ou seja ter somente um elemento. Nesta repetição os ponteiros aux1 e aux2 recebem os dois primeiros elementos da fila de nós e compara eles para saber qual dos dois tem menor valor, depois cria um nó com a função arv_Cria, que recebe o menor valor e os dois nós que comporem o par, onde o ponteiro raiz o recebe, e por fim adiciona este ponteiro ao fim da fila. Esta repetição ocorre até sobrar somente o ponteiro raiz da arvore com os valores adicionados sobre a condição imposta.
Uma função interativa que tem como entrada um ponteiro de nó para a raíz da árvore já criada e como retorno uma fila de números inteiros. Esta função tem como objetivo utilizar da arvore criada pela função arv_OrdenaCria para retornar uma fila com os elementos do vetor original ordenado, através do método pedido, ou seja, enfileirar e substituindo o menor elemento, o valor da raiz, das folhas pelo coringa e retrabalhar a arvore de modo que, comoo menor saíu, o segundo menor tome seu lugar no valor da raiz.
A função utiliza de duas repetições, do tipo while, aninhadas de modo que a primeira tem como condição o valor da raíz ser diferente do coringa, enquanto que a segunda tem como condição os nós esquedo ou direitos serem nulos, ou seja chegar nas folhas. A segunda repetição tem como objetivo fazer um ponteiro auxiliar (aux) percorrer o caminho do valor da raiz (menor elemento) até a folha com o mesmo valor. Após percorrer o caminho até a folha altera-se o seu valor para o coringa e chama uam função auxiliar, propaga(raiz), que recebe a raíz e retorna a raíz da arvore apósatualiza o menor valor das folhas para a raíz de forma recursiva. Deste modo, sobe a condição da primeira repetição o menor valor vai ser sempre adicionado a fila de inteiros e a arvore é atualizada até a raíz ter o valor do coringa, ou seja, todos os elementos menor que ele foram adicionados a fila.
Esta é a função que utiliza todas as funções auxiliares, de modo, a seguir o passo a passo de resolução do problema. Tem como entrada o vetor
std::queue<int> arv_Ordena(int *v,int n){
std::queue<NoArv*> qLeafs = createLeaf(v,n);
NoArv* raiz = arv_OrdenaCria(qLeafs);
std::queue<int> ordenado = arv_OrdenaVec(raiz);
// desalocações
arv_libera(raiz);
return ordenado;
}
Entrando na área de análise assintótica, pode-se analisar a complexidade de um algoritmo em termos do seu número de operações, notação O(f(n)). Deste, modo podemos concluir que o algoritmo criado tem ordem aproximada de
O inicio é de seguido três instruções de atribuição, uma delas tem uma chamada de metódo o mesmo tendo complexidade
Pior caso é a fila passada não é vazia, pois vai entrar em um laço que será executado
O pior caso e o melhor nesse metodo se assemelham, pois ele irá percorrer necessariamente todos os
#ifndef QXTREE_H
#define QXTREE_H
#include <queue>
struct NoArv;
/* //nos de arvore
int chave;
noArv* esq;
noArv* dir;
*/
NoArv* arv_CriaVazia(); //cria arvore vazia
NoArv* arv_Cria(int key, NoArv* esq, NoArv* dir); //cria um nó de valor key de filhos esq e dir;
void arv_imprime(NoArv* no); // imprime os elementos da arvore
bool arv_vazia(NoArv* no); // retora se a arvore está vazia
NoArv* arv_libera(NoArv* no);//Libera todos os nós alocados na arvore
bool arv_pertence(NoArv* no,int chave); // verifica se uma chave está na arvore
int arv_num_nos(NoArv* no); // retorna o número de nó da arvore
/* ::TRABALHO:: */
//funções relativas ao trabalho
int maiorElem(int *V,int n, int aux); //auxiliar: retorna o maior elemento de um vetor
std::queue<NoArv*> createLeaf(int *v, int n);// auxiliar: cria uma fila de ponteiros de noArv para as folhas da arvore (cheeia com coringa)
NoArv* arv_OrdenaCria(std::queue<NoArv*> leafs);//auxiiar: cria uma arvore apartir de uma fila de nós (folhas)
std::queue<int> arv_OrdenaVec(NoArv* raiz); //auxiliar: retorna uma fila com os elementos do vetor ordenado
NoArv* propaga(NoArv* no); // auxiliar: retorna a raiz após a operação de rePopular arvore com a alteração do menor elemento (raiz->value)
std::queue<int> arv_Ordena(int *v,int n); // função que utiliza das auxiliares para agrupar o passo a passo.
// :: Desenho da arvore :: ignorar
// função obtida na internet para auxiliar na visualização da arvore criada.
void draw_arvore_hor(NoArv *arvore); // desenha, de forma horizontal, a arvore;
void desenha_arvore_horiz(NoArv *arvore, int depth, char *path, int direita); // auxiliar
//referência: https://pt.stackoverflow.com/questions/207358/como-imprimir-%C3%A1rvores-bin%C3%A1rias-gen%C3%A9ricas-usando-c
#endif