Árvore binária de busca do tipo splay
Publicado por Perfil removido (última atualização em 12/03/2010)
[ Hits: 9.187 ]
Olá pessoal, postei há pouco tem um gerador de referência cruzada que usa essa estrutura de árvores ( http://www.vivaolinux.com.br/script/Gerador-de-referencia-cruzada-de-texto ).
Resolvi postar aqui separadamente a estrutura da SplayTree em Python caso alguém necessite para outra aplicação.
Obs.: Desenvolvido em Python 3.1.
# -*- coding: utf-8 -*-
"""
Authors: Ewerton Lima, Fernando Rocha
Date: 07/12/2009
Version: 1.0
"""
from splay_tree_node import Node
class SplayTree(object):
"""Implementa uma árvore binária de busca do tipo SplayTree."""
slots = ("__raiz", "__qtde")
def __init__(self):
self.__raiz = None
self.__qtde = 0
def __len__(self):
return self.__qtde
@property
def raiz(self):
'''
Retorna valor do nó que está na raiz da árvore.
'''
return self.__raiz.dado
@property
def altura(self, pont=None):
'''
Retorna a altura da árvore.
'''
if not pont:
pont = self.__raiz
def altura_aux(pont):
'''
Método auxiliar do 'altura'.
'''
if not pont:
return 0
else:
altura_dir = altura_aux(pont.dir) + 1
altura_esq = altura_aux(pont.esq) + 1
return altura_dir if altura_dir > altura_esq else altura_esq
return altura_aux(pont)
def remover_tudo(self):
'''
Apaga a árvore inteira, setando o ponteiro da raíz para valor nulo.
'''
self._raiz = None
def esta_vazia(self):
'''
Verifica se a árvore está vazia ou se contém elementos.
Retorna True quando vazia e False para qualquer outro caso.
'''
return self.__raiz == None
def rotacionar_esquerda(self, pont=None, pont_ante=None):
'''
Rotaciona para a esquerda um nó representado por ponteiro
com o parâmetro 'pont' e o seu nó pai representado por ponteiro
usando o parâmetro 'pont_ante'.
'''
if pont_ante == self.__raiz:
pont_temp = pont.esq
pont.esq = pont_ante
pont.pai = pont_ante.pai
pont_ante.pai = pont
pont_ante.dir = pont_temp
if pont_temp:
pont_temp.pai = pont_ante
self.__raiz = pont
else:
pont_temp = pont.esq
pont.esq = pont_ante
pont.pai = pont_ante.pai
pont_ante.pai = pont
pont_ante.dir = pont_temp
if pont_temp:
pont_temp.pai = pont_ante
if pont.pai.dado > pont.dado:
pont.pai.esq = pont
self.rotacionar_direita(pont, pont.pai)
else:
pont.pai.dir = pont
self.rotacionar_esquerda(pont, pont.pai)
def rotacionar_direita(self, pont=None, pont_ante=None):
'''
Rotaciona para a direita um nó representado por ponteiro
com o parâmetro 'pont' e o seu nó pai representado por ponteiro
usando o parâmetro 'pont_ante'.
'''
if pont_ante == self.__raiz:
pont_temp = pont.dir
pont.dir = pont_ante
pont.pai = pont_ante.pai
pont_ante.pai = pont
pont_ante.esq = pont_temp
if pont_temp:
pont_temp.pai = pont_ante
self.__raiz = pont
else:
pont_temp = pont.dir
pont.dir = pont_ante
pont.pai = pont_ante.pai
pont_ante.pai = pont
pont_ante.esq = pont_temp
if pont_temp:
pont_temp.pai = pont_ante
if pont.pai.dado > pont.dado:
pont.pai.esq = pont
self.rotacionar_direita(pont, pont.pai)
else:
pont.pai.dir = pont
self.rotacionar_esquerda(pont, pont.pai)
def splay(self, pont):
'''
Faz o procedimento de Splay, baseando-se no ponteiro do elemento
sobre o qual objetiva-se fazer o splay. Verifica qual é a
necessidade de rotação do nó (para esquerda ou para direita)
e faz a rotação.
'''
pont_ante = pont.pai
if not (pont and pont_ante):
return
if pont == pont_ante.dir:
self.rotacionar_esquerda(pont, pont_ante)
else:
self.rotacionar_direita(pont, pont_ante)
def inserir(self, dado):
'''
Insere o elemento na árvore obedecendo às propriedades de
uma árvore binária de busca, fazendo ainda o splay no final.
Mantém assim as propriedades de uma SplayTree.
'''
nodo = Node(dado)
if not self.__raiz:
self.__raiz = nodo
else:
pont = self.__raiz
pont_ante = self.__raiz
while pont:
pont_ante = pont
if pont.dado > dado:
pont = pont.esq
else:
pont = pont.dir
if pont_ante.dado > dado:
pont_ante.esq = nodo
else:
pont_ante.dir = nodo
nodo.pai = pont_ante
self.__qtde += 1
self.splay(nodo)
def antecessor(self, pont):
'''Baseando-se no ponteiro representado pelo parâmetro 'pont',
retorna o ponteiro para maior elemento da subárvore da esquerda,
caso exista e também o ponteiro de seu nó pai.
'''
antecessor = pont.esq
pont_ante = pont
while antecessor.dir:
pont_ante = antecessor
antecessor = antecessor.dir
return antecessor, pont_ante
def remover(self, objetivo, pont=None, pont_ante=None):
'''
Utiliza os ponteiros 'pont' e 'pont_ante' para efetuar a remoção de
determinado elemento. Caso não tenha os ponteiros, pode ser
passado o valor do elemento no parâmetro 'objetivo'. Neste caso,
será feita a busca pelos ponteiros na árvore, obedecendo às
propriedades de uma árvore binária de busca, fazendo ainda o
splay no final. Mantém assim as propriedades de uma SplayTree.
'''
if not pont:
pont = self.buscar_sem_splay(objetivo)
pont_ante = pont.pai
if pont:
#Caso em que é folha
if not (pont.esq or pont.dir):
if pont_ante.dir == pont:
pont_ante.dir = None
else:
pont_ante.esq = None
self.splay(pont)
#Caso em que não existe o filho da direita
elif not pont.dir:
pont.dado = pont.esq.dado
self.remover(objetivo, pont.esq, pont)
#Caso em que não existe o filho da esquerda
elif not pont.esq:
pont.dado = pont.dir.dado
self.remover(objetivo, pont.dir, pont)
#Caso em que existem ambos os filhos
else:
antecessor, pont_ante = self.antecessor(pont)
pont.dado = antecessor.dado
self.remover(objetivo, antecessor, pont_ante)
self.__qtde -= 1
def buscar(self, objetivo):
'''
Faz a busca do valor representado pelo parâmetro 'objetivo',
baseando-se nas propriedades de uma árvore binária de busca,
fazendo ainda o splay do nó no final, se este for encontrado.
Mantém assim as propriedades de uma SplayTree.
Retorna o ponteiro do nó (que será a raiz após o splay).
Se não for encontrado o elemento retornará None.
'''
pont = self.__raiz
if pont:
while pont and pont.dado != objetivo:
if pont.dado > objetivo:
pont = pont.esq
else:
pont = pont.dir
if pont:
self.splay(pont)
return pont
else:
return None
def buscar_sem_splay(self, objetivo):
'''
Faz a busca do valor representado pelo parâmetro 'objetivo',
baseando-se nas propriedades de uma árvore binária de busca,
NÃO faz o splay do nó no final. Mais utilizado dentro da classe.
Retorna o ponteiro do nó buscado ou None se não for encontrado.
'''
pont = self.__raiz
if pont:
while pont and pont.dado != objetivo:
if pont.dado > objetivo:
pont = pont.esq
else:
pont = pont.dir
if pont:
return pont
else:
return None
def caminhar(self, tipo=1, funcao=None):
'''
Faz o caminhamento em todos os itens da árvore e executa a função
especificada no parâmetro funcao. Para o parâmetro "tipo" são
válidas três opções:
1. Em ordem
2. Pré-ordem
3. Pós-ordem
'''
if not funcao:
funcao = self.print_dado
def caminhar_aux(pont, tipo, func):
'''
Método auxiliar do 'caminhar'.
'''
if pont:
if tipo == 2:
func(pont)
caminhar_aux(pont.esq, 1, func)
if tipo == 1:
func(pont)
caminhar_aux(pont.dir, 1, func)
if tipo == 3:
func(pont)
caminhar_aux(self.__raiz, tipo, funcao)
def print_dado(self, pont):
'''
Imprime o dado do ponteiro representado pelo parâmetro 'pont'.
'''
print(pont.dado)
QFacil 0.2 - Qemu simplificado.
Nenhum comentário foi encontrado.
IA Turbina o Desktop Linux enquanto distros renovam forças
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
Atualizando o Fedora 42 para 43
Como saber se o seu e-mail já teve a senha vazada?
Como descobrir se a sua senha já foi vazada na internet?
E aí? O Warsaw já está funcionando no Debian 13? [RESOLVIDO] (15)
Secure boot, artigo interessante, nada técnico. (4)
copiar library para diretorio /usr/share/..... su com Falha na a... (1)









