{"id":103,"date":"2015-04-23T12:57:58","date_gmt":"2015-04-23T15:57:58","guid":{"rendered":"http:\/\/just.pro.br\/blog\/?p=103"},"modified":"2015-04-23T12:57:58","modified_gmt":"2015-04-23T15:57:58","slug":"arvore-avl-com-impressao","status":"publish","type":"post","link":"https:\/\/just.pro.br\/blog\/2015\/04\/23\/arvore-avl-com-impressao\/","title":{"rendered":"\u00c1rvore AVL com impress\u00e3o"},"content":{"rendered":"<p>Ol\u00e1, pessoal.<\/p>\n<p>Abaixo, o c\u00f3digo da \u00c1rvore AVL da aula de ontem (a que voc\u00eas fizeram), com a fun\u00e7\u00e3o para imprimir a \u00e1rvore graficamente. Comentei tudo pra facilitar o entendimento e aproveitei pra melhorar algumas coisas no menu de op\u00e7\u00f5es. Para inserir os elementos da \u00e1rvore, n\u00e3o precisa mais ir de um por um, pode digitar todos os elementos separados por espa\u00e7os (na ordem em que deseja inserir), teclar ENTER e depois, CTRL+D.<\/p>\n<p>A constante TELA pode ser alterada para aumentar ou diminuir o tamanho da tela do seu terminal (em colunas).<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;math.h&gt;\r\n#include &lt;list&gt;\r\n\r\n\/\/ Tamanho da tela em colunas (para impress\u00e3o da \u00e1rvore)\r\n#define TELA 64\r\n\r\nusing namespace std;\r\n\r\n\/* Estrutura de um n\u00f3 *\/\r\nstruct no\r\n{\r\n    int chave;\r\n    int nivel;      \/\/ Para impress\u00e3o em gr\u00e1fico\r\n    int pos;        \/\/ Para impress\u00e3o em gr\u00e1fico\r\n    struct no *p;\r\n    struct no *e;\r\n    struct no *d;\r\n};\r\n\r\n\/\/ Imprime a \u00e1rvore graficamente\r\n\/\/ A posi\u00e7\u00e3o de cada elemento ser\u00e1 relativa ao seu n\u00edvel na \u00e1rvore\r\n\/\/ Por isso usa a equa\u00e7\u00e3o (TELA \/ 2^(nivel + 2)) para determinar o quanto\r\n\/\/ o elemento deve variar para cada lado\r\nvoid imprime_graf(struct no *raiz)\r\n{\r\n    list&lt;struct no *&gt; fila; \/\/ Fila para manuten\u00e7\u00e3o da impress\u00e3o\r\n    int nivel_ant = 0;      \/\/ Indica o n\u00edvel do n\u00f3 impresso anteriormente\r\n    int pos_filho;          \/\/ Usado para calcular a posi\u00e7\u00e3o do filho do n\u00f3 atual\r\n    int linha_pos = 0;      \/\/ Calcula quantas casas j\u00e1 foram movimentadas em uma linha\r\n\r\n    \/\/ Inicializa o n\u00edvel e a posi\u00e7\u00e3o da ra\u00edz e insere na fila\r\n    raiz-&gt;nivel = 0;\r\n    raiz-&gt;pos = TELA \/ 2;\r\n    fila.push_back(raiz);\r\n\r\n    \/\/ Enquanto houver elementos na fila, imprime!\r\n    while (!fila.empty())\r\n    {\r\n        \/\/ Pega o primeiro elemento da fila\r\n        struct no *temp = fila.front();\r\n        fila.pop_front();\r\n\r\n        \/\/ Se o n\u00edvel deste novo elemento for maior que o do anterior, significa\r\n        \/\/ que ele deve ficar na linha abaixo. Atualiza o n\u00edvel e a posi\u00e7\u00e3o\r\n        \/\/ atual da linha\r\n        if (temp-&gt;nivel &gt; nivel_ant)\r\n        {\r\n            printf(&quot;\\n&quot;);\r\n            nivel_ant = temp-&gt;nivel;\r\n            linha_pos = 0;\r\n        }\r\n\r\n        \/\/ Insere espa\u00e7os at\u00e9 a posi\u00e7\u00e3o de um prov\u00e1vel filho que esse n\u00f3 possa\r\n        \/\/ ter \u00e0 esquerda\r\n        pos_filho = temp-&gt;pos - (TELA \/ pow(2, temp-&gt;nivel + 2));\r\n        for (int i = linha_pos; i &lt; pos_filho; i++)\r\n            linha_pos += printf(&quot; &quot;);\r\n\r\n        \/\/ Verifica se o elemento tem filho \u00e0 esquerda. Se tiver, insere tra\u00e7os.\r\n        \/\/ Caso contr\u00e1rio, insere espa\u00e7os\r\n        if (temp-&gt;e != NULL) linha_pos += printf(&quot;|&quot;);\r\n        for (int i = linha_pos; i &lt; temp-&gt;pos; i++)\r\n            temp-&gt;e != NULL ? linha_pos += printf(&quot;-&quot;) : linha_pos += printf(&quot; &quot;);\r\n\r\n        \/\/ Imprime o elemento atual e atualiza a posi\u00e7\u00e3o na linha.\r\n        linha_pos += printf(&quot;%d&quot;, temp-&gt;chave);\r\n\r\n        \/\/ Verifica se o elemento tem filho \u00e0 direita. Se tiver, posiciona no\r\n        \/\/ local onde o filho ser\u00e1 impresso abaixo e insere tra\u00e7os.\r\n        if (temp-&gt;d != NULL)\r\n        {\r\n            pos_filho = temp-&gt;pos + (TELA \/ pow(2, temp-&gt;nivel + 2));\r\n            for (int i = linha_pos; i &lt; pos_filho; i++)\r\n                linha_pos += printf(&quot;-&quot;);\r\n            linha_pos += printf(&quot;|&quot;);\r\n        }\r\n\r\n        \/\/ Insere os filhos deste elemento na fila, armazenando suas posi\u00e7\u00f5es.\r\n        if (temp-&gt;e != NULL)\r\n        {\r\n            temp-&gt;e-&gt;nivel = temp-&gt;nivel + 1;\r\n            temp-&gt;e-&gt;pos = temp-&gt;pos - (TELA \/ pow(2, temp-&gt;e-&gt;nivel + 1));\r\n            fila.push_back(temp-&gt;e);\r\n        }\r\n\r\n        if (temp-&gt;d != NULL)\r\n        {\r\n            temp-&gt;d-&gt;nivel = temp-&gt;nivel + 1;\r\n            temp-&gt;d-&gt;pos = temp-&gt;pos + (TELA \/ pow(2, temp-&gt;d-&gt;nivel + 1));\r\n            fila.push_back(temp-&gt;d);\r\n        }\r\n    }\r\n\r\n    printf(&quot;\\n\\n&quot;);\r\n}\r\n\r\n\/* Cria um n\u00f3 *\/\r\nstruct no *criar(int chave)\r\n{\r\n    struct no *novo = (struct no *)malloc(sizeof(struct no));\r\n    novo-&gt;chave = chave;\r\n    novo-&gt;p = novo-&gt;e = novo-&gt;d = NULL;\r\n}\r\n\r\n\/* Rotaciona n\u00f3 para direita *\/\r\nvoid girar_direita(struct no **raiz)\r\n{\r\n    struct no *temp             = *raiz;\r\n    struct no *temp_esquerda    = (*raiz)-&gt;e;\r\n    temp-&gt;e                     = temp_esquerda-&gt;d;\r\n    temp_esquerda-&gt;d            = temp;\r\n    temp_esquerda-&gt;p            = temp-&gt;p;\r\n    temp-&gt;p                     = temp_esquerda;\r\n    *raiz                       = temp_esquerda;\r\n}\r\n\r\n\/* Rotaciona n\u00f3 para esquerda *\/\r\nvoid girar_esquerda(struct no **raiz)\r\n{\r\n    struct no *temp            = *raiz;\r\n    struct no *temp_direita    = (*raiz)-&gt;d;\r\n    temp-&gt;d                    = temp_direita-&gt;e;\r\n    temp_direita-&gt;e            = temp;\r\n    temp_direita-&gt;p            = temp-&gt;p;\r\n    temp-&gt;p                    = temp_direita;\r\n    *raiz                      = temp_direita;\r\n}\r\n\r\n\/* Calcula a altura de uma \u00e1rvore *\/\r\nint altura(struct no *raiz)\r\n{\r\n    if(raiz == NULL)\r\n        return 0;\r\n\r\n    int e = altura(raiz-&gt;e);\r\n    int d = altura(raiz-&gt;d);\r\n    int m;\r\n\r\n    if (e &gt; d)\r\n        m = e;\r\n    else\r\n        m = d;\r\n\r\n    return m + 1;\r\n}\r\n\r\n\r\n\/* Calcula o fator de balanceamento de um n\u00f3 *\/\r\nint balanceamento(struct no *raiz)\r\n{\r\n    return altura(raiz-&gt;d) - altura(raiz-&gt;e);\r\n}\r\n\r\n\/*Percorre a \u00e1rvore pelo m\u00e9todo da p\u00f3s-ordem em busca de n\u00f3s desbalanceados *\/\r\nvoid verificar_balanceamento(struct no **raiz)\r\n{\r\n    if ((*raiz) == NULL)\r\n        return;\r\n\r\n    verificar_balanceamento(&amp;(*raiz)-&gt;e);\r\n    verificar_balanceamento(&amp;(*raiz)-&gt;d);\r\n\r\n    if(balanceamento((*raiz)) == 2)\r\n    {\r\n        \/\/Rota\u00e7\u00e3o a esquerda\r\n        if(balanceamento((*raiz)-&gt;d) == -1)\r\n            girar_direita(&amp;(*raiz)-&gt;d);\r\n        girar_esquerda(&amp;(*raiz));\r\n    }\r\n    else if(balanceamento((*raiz)) == -2)\r\n    {\r\n        \/\/Rota\u00e7\u00e3o a direita\r\n        if(balanceamento((*raiz)-&gt;e) == 1)\r\n            girar_esquerda(&amp;(*raiz)-&gt;e);\r\n        girar_direita(&amp;(*raiz));\r\n    }\r\n}\r\n\r\n\/* Adiciona elemento na \u00e1rvore *\/\r\nstruct no *adicionar(struct no *raiz, int chave)\r\n{\r\n    struct no *novo = (struct no *)malloc(sizeof(struct no));\r\n    if (raiz == NULL)\r\n    {\r\n        novo = criar(chave);\r\n        return novo;\r\n    }\r\n\r\n    if (chave &lt; raiz-&gt;chave)\r\n    {\r\n        novo = adicionar(raiz-&gt;e, chave);\r\n        raiz-&gt;e = novo;\r\n        novo-&gt;p = raiz;\r\n    }\r\n    else\r\n    {\r\n        novo = adicionar(raiz-&gt;d, chave);\r\n        raiz-&gt;d = novo;\r\n        novo-&gt;p = raiz;\r\n    }\r\n\r\n    verificar_balanceamento(&amp;raiz);\r\n\r\n    return raiz;\r\n}\r\n\r\n\/* Busca um n\u00f3 na \u00e1rvore *\/\r\nstruct no *buscar(struct no *raiz, int chave)\r\n{\r\n    if(raiz == NULL)\r\n        return NULL;\r\n    if(raiz-&gt;chave == chave)\r\n        return raiz;\r\n\r\n    if(chave &gt; raiz-&gt;chave)\r\n        return buscar(raiz-&gt;d,chave);\r\n    else\r\n        return buscar(raiz-&gt;e,chave);\r\n}\r\n\r\n\/* Imprime a \u00e1rvore em ordem *\/\r\nvoid emordem(struct no *raiz)\r\n{\r\n    if (raiz == NULL)\r\n        return;\r\n\r\n    emordem(raiz-&gt;e);\r\n    printf(&quot;%d &quot;,raiz-&gt;chave);\r\n    emordem(raiz-&gt;d);\r\n}\r\n\r\n\/* Imprime a \u00e1rvore em pr\u00e9-ordem *\/\r\nvoid preordem(struct no *raiz)\r\n{\r\n    if (raiz == NULL)\r\n        return;\r\n\r\n    printf(&quot;%d &quot;,raiz-&gt;chave);\r\n    preordem(raiz-&gt;e);\r\n    preordem(raiz-&gt;d);\r\n}\r\n\r\n\/* Imprime a \u00e1rvore em p\u00f3s-ordem *\/\r\nvoid posordem(struct no *raiz)\r\n{\r\n    if (raiz == NULL)\r\n        return;\r\n\r\n    posordem(raiz-&gt;e);\r\n    posordem(raiz-&gt;d);\r\n    printf(&quot;%d &quot;,raiz-&gt;chave);\r\n}\r\n\r\n\/* Retorna o m\u00ednimo de uma \u00e1rvore *\/\r\nstruct no *minimo(struct no *raiz)\r\n{\r\n    if (raiz == NULL)\r\n        return NULL;\r\n\r\n    if (raiz-&gt;e == NULL)\r\n        return raiz;\r\n\r\n    return minimo(raiz-&gt;e);\r\n}\r\n\r\n\/* Retorna o m\u00e1ximo de uma \u00e1rvore *\/\r\nstruct no *maximo(struct no *raiz)\r\n{\r\n    if (raiz == NULL)\r\n        return NULL;\r\n\r\n    if (raiz-&gt;d == NULL)\r\n        return raiz;\r\n\r\n    return maximo(raiz-&gt;d);\r\n}\r\n\r\n\/* Retorna o antecessor de um n\u00f3 *\/\r\nstruct no *antecessor(struct no *raiz)\r\n{\r\n    if(raiz-&gt;e == NULL)\r\n    {\r\n        while(raiz-&gt;p != NULL &amp;&amp; raiz-&gt;p-&gt;chave &gt; raiz-&gt;chave  )\r\n            raiz = raiz-&gt;p;\r\n\r\n        return raiz-&gt;p;\r\n    }\r\n    return maximo(raiz-&gt;e);\r\n}\r\n\r\n\/* Retorna o sucessor de um n\u00f3 *\/\r\nstruct no *sucessor(struct no *raiz)\r\n{\r\n    if(raiz-&gt;d == NULL)\r\n    {\r\n        while(raiz-&gt;p != NULL &amp;&amp; raiz-&gt;p-&gt;chave &lt; raiz-&gt;chave  )\r\n            raiz = raiz-&gt;p;\r\n        return raiz-&gt;p;\r\n    }\r\n\r\n    return minimo(raiz-&gt;d);\r\n\r\n}\r\n\r\n\/* Remove um n\u00f3 da \u00e1rvore e retorna a nova \u00e1rvore *\/\r\nstruct no* remover(struct no *arvore, int chave)\r\n{\r\n    if(arvore == NULL)\r\n        return NULL;\r\n\r\n    struct no *raiz = buscar(arvore, chave);\r\n\r\n    if (raiz == NULL)\r\n        return arvore;\r\n\r\n    \/\/ Remover NO sem Filhos\r\n    if (raiz-&gt;e == NULL &amp;&amp; raiz-&gt;d == NULL)\r\n    {\r\n        if(raiz-&gt;p != NULL)\r\n        {\r\n            if(raiz-&gt;p-&gt;chave &gt;= raiz-&gt;chave)\r\n                raiz-&gt;p-&gt;e = NULL;\r\n            else\r\n                raiz-&gt;p-&gt;d = NULL;\r\n            free(raiz);\r\n        }\r\n        else\r\n        {\r\n            free(raiz);\r\n            return NULL;\r\n        }\r\n        if (raiz == arvore)\r\n            return NULL;\r\n    }\r\n    else\r\n    {\r\n        \/\/ Remover NO com 2 Filhos\r\n        if (raiz-&gt;e &amp;&amp; raiz-&gt;d != NULL)\r\n        {\r\n            struct no *ant = antecessor(raiz);\r\n            raiz-&gt;chave = ant-&gt;chave;\r\n            ant = remover(ant, ant-&gt;chave);\r\n        }\r\n        \/\/ Remover NO com 1 Filho\r\n        else\r\n        {\r\n            \/\/ Reconectar Filho a Esquerda\r\n            if(raiz-&gt;e != NULL)\r\n            {\r\n                if (raiz-&gt;p != NULL)\r\n                {\r\n                    if(raiz-&gt;p-&gt;chave &gt; raiz-&gt;chave)    \/\/ Caso o pai seja maior\r\n                        raiz-&gt;p-&gt;e = raiz-&gt;e;\r\n                    else                                \/\/ Caso o pai seja menor\r\n                        raiz-&gt;p-&gt;d = raiz-&gt;e;\r\n                }\r\n                raiz-&gt;e-&gt;p = raiz-&gt;p;\r\n            }\r\n            \/\/ Reconectar Filho a Direita\r\n            else\r\n            {\r\n                if (raiz-&gt;p != NULL)\r\n                {\r\n                    if(raiz-&gt;p-&gt;chave &lt; raiz-&gt;chave)    \/\/ Caso o pai seja menor\r\n                        raiz-&gt;p-&gt;d = raiz-&gt;d;\r\n                    else                                \/\/ Caso o pai seja maior\r\n                        raiz-&gt;p-&gt;e = raiz-&gt;d;\r\n                }\r\n                raiz-&gt;d-&gt;p = raiz-&gt;p;\r\n\r\n                free(raiz);\r\n            }\r\n        }\r\n    }\r\n\r\n    return arvore;\r\n}\r\n\r\n\/* Fun\u00e7\u00e3o principal *\/\r\nint main(void)\r\n{\r\n    struct no *arvore = NULL;\r\n    int opt, chave;\r\n\r\n    do\r\n    {\r\n        printf(&quot;==============================\\n&quot;);\r\n        printf(&quot;OPCOES:\\n\\n&quot;);\r\n        printf(&quot;\\t&#x5B;1] Adicionar\\n&quot;);\r\n        printf(&quot;\\t&#x5B;2] Listar\\n&quot;);\r\n        printf(&quot;\\t&#x5B;3] Remover\\n&quot;);\r\n        printf(&quot;\\t&#x5B;0] Sair\\n\\n&quot;);\r\n        printf(&quot;Escolha: &quot;);\r\n        scanf(&quot;%d&quot;, &amp;opt);\r\n\r\n        switch(opt)\r\n        {\r\n        case 1:\r\n            printf(&quot;\\n\\nDigite as chaves separadas por espacos, na ordem que deseja inserir, e pressione CTRL+D para finalizar: &quot;);\r\n            while (scanf(&quot;%d&quot;, &amp;chave) != EOF)\r\n                arvore = adicionar(arvore, chave);\r\n            break;\r\n\r\n        case 2:\r\n            printf(&quot;==============================\\n&quot;);\r\n            printf(&quot;IMPRESSAO DA ARVORE:\\n\\n&quot;);\r\n            printf(&quot;Em ordem:\\n&quot;);\r\n            emordem(arvore);\r\n            printf(&quot;\\n\\n&quot;);\r\n            printf(&quot;Pre ordem:\\n&quot;);\r\n            preordem(arvore);\r\n            printf(&quot;\\n\\n&quot;);\r\n            printf(&quot;Pos ordem:\\n&quot;);\r\n            posordem(arvore);\r\n            printf(&quot;\\n\\n&quot;);\r\n            printf(&quot;Grafico:\\n&quot;);\r\n            imprime_graf(arvore);\r\n            break;\r\n\r\n        case 3:\r\n            printf(&quot;==============================\\n&quot;);\r\n            printf(&quot;Digite a chave a ser removida: &quot;);\r\n            scanf(&quot;%d&quot;, &amp;chave);\r\n            arvore = remover(arvore, chave);\r\n            break;\r\n\r\n        case 0:\r\n            return 0;\r\n\r\n        default:\r\n            printf(&quot;Opcao invalida!\\n\\n&quot;);\r\n        }\r\n    } while(1);\r\n\r\n    return 0;\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Ol\u00e1, pessoal. Abaixo, o c\u00f3digo da \u00c1rvore AVL da aula de ontem (a que voc\u00eas fizeram), com a fun\u00e7\u00e3o para imprimir a \u00e1rvore graficamente. Comentei tudo pra facilitar o entendimento e aproveitei pra melhorar algumas coisas no menu de op\u00e7\u00f5es. &hellip;<\/p>\n<p class=\"read-more\"> <a class=\"more-link\" href=\"https:\/\/just.pro.br\/blog\/2015\/04\/23\/arvore-avl-com-impressao\/\"> <span class=\"screen-reader-text\">\u00c1rvore AVL com impress\u00e3o<\/span> Read More &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,2],"tags":[],"class_list":["post-103","post","type-post","status-publish","format-standard","hentry","category-estrutura-de-dados-2","category-unifacs"],"_links":{"self":[{"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/posts\/103","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/comments?post=103"}],"version-history":[{"count":2,"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/posts\/103\/revisions"}],"predecessor-version":[{"id":105,"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/posts\/103\/revisions\/105"}],"wp:attachment":[{"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/media?parent=103"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/categories?post=103"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/just.pro.br\/blog\/wp-json\/wp\/v2\/tags?post=103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}