# Árvore de Pesquisa Binária (Binary Search Tree)

Na ciência da computação **binary search trees** (BST), algumas vezes
chamadas de árvores binárias ordenadas (_ordered or sorted binary trees_),
é um tipo particular de container: estruturas de dados que armazenam
"itens" (como números, nomes, etc.) na memória. Permite pesquisa rápida,
adição e remoção de itens além de poder ser utilizado para implementar
tanto conjuntos dinâmicos de itens ou, consultar tabelas que permitem
encontrar um item por seu valor chave. E.g. encontrar o número de
telefone de uma pessoa pelo seu nome.

Árvore de Pesquisa Binária mantem seus valores chaves ordenados, para
que uma pesquisa e outras operações possam usar o princípio da pesquisa
binária: quando pesquisando por um valor chave na árvore (ou um lugar
para inserir uma nova chave), eles atravessam a árvore da raiz para a folha,
fazendo comparações com chaves armazenadas nos nós da árvore e decidindo então,
com base nas comparações, continuar pesquisando nas sub-árvores a direita ou
a esquerda. Em média isto significa que cara comparação permite as operações
pular metade da árvore, para que então, cada pesquisa, inserção ou remoção
consuma tempo proporcional ao logaritmo do número de itens armazenados na
árvore. Isto é muito melhor do que um tempo linear necessário para encontrar
itens por seu valor chave em um array (desorndenado - _unsorted_), mas muito
mais lento do que operações similares em tableas de hash (_hash tables_).

Uma pesquisa de árvore binária de tamanho 9 e profundidade 3, com valor 8
na raíz.
As folhas não foram desenhadas.

![Trie](./images/binary-search-tree.jpg)

*Made with [okso.app](https://okso.app)*

## Pseudocódigo para Operações Básicas

### Inserção

```text
insert(value)
  Pre: value has passed custom type checks for type T
  Post: value has been placed in the correct location in the tree
  if root = ø
    root ← node(value)
  else
    insertNode(root, value)
  end if
end insert
```

```text
insertNode(current, value)
  Pre: current is the node to start from
  Post: value has been placed in the correct location in the tree
  if value < current.value
    if current.left = ø
      current.left ← node(value)
    else
      InsertNode(current.left, value)
    end if
  else
    if current.right = ø
      current.right ← node(value)
    else
      InsertNode(current.right, value)
    end if
  end if
end insertNode
```

### Pesquisa

```text
contains(root, value)
  Pre: root is the root node of the tree, value is what we would like to locate
  Post: value is either located or not
  if root = ø
    return false
  end if
  if root.value = value
    return true
  else if value < root.value
    return contains(root.left, value)
  else
    return contains(root.right, value)
  end if
end contains
```


### Remoção

```text
remove(value)
  Pre: value is the value of the node to remove, root is the node of the BST
      count is the number of items in the BST
  Post: node with value is removed if found in which case yields true, otherwise false
  nodeToRemove ← findNode(value)
  if nodeToRemove = ø
    return false
  end if
  parent ← findParent(value)
  if count = 1
    root ← ø
  else if nodeToRemove.left = ø and nodeToRemove.right = ø
    if nodeToRemove.value < parent.value
      parent.left ←  nodeToRemove.right
    else
      parent.right ← nodeToRemove.right
    end if
  else if nodeToRemove.left != ø and nodeToRemove.right != ø
    next ← nodeToRemove.right
    while next.left != ø
      next ← next.left
    end while
    if next != nodeToRemove.right
      remove(next.value)
      nodeToRemove.value ← next.value
    else
      nodeToRemove.value ← next.value
      nodeToRemove.right ← nodeToRemove.right.right
    end if
  else
    if nodeToRemove.left = ø
      next ← nodeToRemove.right
    else
      next ← nodeToRemove.left
    end if
    if root = nodeToRemove
      root = next
    else if parent.left = nodeToRemove
      parent.left = next
    else if parent.right = nodeToRemove
      parent.right = next
    end if
  end if
  count ← count - 1
  return true
end remove
```

### Encontrar o Nó Pai

```text
findParent(value, root)
  Pre: value is the value of the node we want to find the parent of
       root is the root node of the BST and is != ø
  Post: a reference to the prent node of value if found; otherwise ø
  if value = root.value
    return ø
  end if
  if value < root.value
    if root.left = ø
      return ø
    else if root.left.value = value
      return root
    else
      return findParent(value, root.left)
    end if
  else
    if root.right = ø
      return ø
    else if root.right.value = value
      return root
    else
      return findParent(value, root.right)
    end if
  end if
end findParent
```

### Encontrar um Nó

```text
findNode(root, value)
  Pre: value is the value of the node we want to find the parent of
       root is the root node of the BST
  Post: a reference to the node of value if found; otherwise ø
  if root = ø
    return ø
  end if
  if root.value = value
    return root
  else if value < root.value
    return findNode(root.left, value)
  else
    return findNode(root.right, value)
  end if
end findNode
```

### Encontrar Mínimo

```text
findMin(root)
  Pre: root is the root node of the BST
    root = ø
  Post: the smallest value in the BST is located
  if root.left = ø
    return root.value
  end if
  findMin(root.left)
end findMin
```

### Encontrar Máximo

```text
findMax(root)
  Pre: root is the root node of the BST
    root = ø
  Post: the largest value in the BST is located
  if root.right = ø
    return root.value
  end if
  findMax(root.right)
end findMax
```

### Traversal

#### Na Ordem Traversal (InOrder Traversal)

```text
inorder(root)
  Pre: root is the root node of the BST
  Post: the nodes in the BST have been visited in inorder
  if root = ø
    inorder(root.left)
    yield root.value
    inorder(root.right)
  end if
end inorder
```

#### Pré Ordem Traversal (PreOrder Traversal)

```text
preorder(root)
  Pre: root is the root node of the BST
  Post: the nodes in the BST have been visited in preorder
  if root = ø
    yield root.value
    preorder(root.left)
    preorder(root.right)
  end if
end preorder
```

#### Pós Ordem Traversal (PostOrder Traversal)

```text
postorder(root)
  Pre: root is the root node of the BST
  Post: the nodes in the BST have been visited in postorder
  if root = ø
    postorder(root.left)
    postorder(root.right)
    yield root.value
  end if
end postorder
```

## Complexidades

### Complexidade de Tempo

| Access    | Search    | Insertion | Deletion  |
| :-------: | :-------: | :-------: | :-------: |
| O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) |

### Complexidade de Espaço

O(n)

## Referências

- [Wikipedia](https://en.wikipedia.org/wiki/Binary_search_tree)
- [Inserting to BST on YouTube](https://www.youtube.com/watch?v=wcIRPqTR3Kc&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8&index=9&t=0s)
- [BST Interactive Visualisations](https://www.cs.usfca.edu/~galles/visualization/BST.html)
