| @@ -0,0 +1,177 @@ | |||||
| // | |||||
| // Lol Engine | |||||
| // | |||||
| // Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
| // (c) 2013-2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
| // (c) 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | |||||
| // This program is free software; you can redistribute it and/or | |||||
| // modify it under the terms of the Do What The Fuck You Want To | |||||
| // Public License, Version 2, as published by Sam Hocevar. See | |||||
| // http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #pragma once | |||||
| namespace lol | |||||
| { | |||||
| template<typename K, typename V> | |||||
| class avl_tree | |||||
| { | |||||
| avl_tree() : | |||||
| m_root(0) | |||||
| { | |||||
| } | |||||
| bool insert(K const & key, V const & value) | |||||
| { | |||||
| if (!m_root) | |||||
| this->m_root = new tree_node(key, value); | |||||
| else | |||||
| { | |||||
| tree_node * created = this->m_root->insert(key, value); | |||||
| if (created) | |||||
| { | |||||
| this->m_root->path_update_balance(created); | |||||
| tree_node * new_root = this->m_root->path_rebalance(created); | |||||
| if (new_root) | |||||
| this->m_root = new_root; | |||||
| } | |||||
| else | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| private: | |||||
| class tree_node | |||||
| { | |||||
| tree_node(K key, V value) : | |||||
| m_key(key), | |||||
| m_value(value), | |||||
| m_lo(0), | |||||
| m_hi(0) | |||||
| m_stairs_lo(0), | |||||
| m_stairs_hi(0), | |||||
| { | |||||
| } | |||||
| tree_node * insert(K const & key, V const & value) | |||||
| { | |||||
| tree_node * ret = 0; | |||||
| if (key < this->m_key) | |||||
| { | |||||
| if (this->m_lo) | |||||
| ret = this->m_lo->insert(key, value); | |||||
| else | |||||
| ret = this->m_lo = new tree_node(key, value); | |||||
| } | |||||
| else if (this->m_key < key) | |||||
| { | |||||
| if (this->m_hi) | |||||
| ret = this->m_hi->insert(key, value); | |||||
| else | |||||
| ret = this->m_hi = new tree_node(key, value); | |||||
| } | |||||
| else | |||||
| this->m_value = value; | |||||
| return ret; | |||||
| } | |||||
| int path_update_balance(K const & key) | |||||
| { | |||||
| if (key < this->m_key) | |||||
| this->m_stairs_lo = lol::max(this->m_lo->path_update_balance(node), this->m_stairs_lo); | |||||
| else if (this->m_key < key) | |||||
| this->m_stairs_hi = lol::max(this->m_hi->path_update_balance(node), this->m_stairs_hi); | |||||
| return lol::max(this->m_stairs_lo, this->m_stairs_hi) + 1; | |||||
| } | |||||
| tree_node * path_rebalance(K const & key) | |||||
| { | |||||
| if (key < this->m_key) | |||||
| { | |||||
| tree_node * node = this->m_lo->path_rebalance(); | |||||
| if (node) | |||||
| { | |||||
| this->m_lo = node; | |||||
| --this->m_lo; | |||||
| } | |||||
| } | |||||
| else if (this->m_key < key) | |||||
| { | |||||
| tree_node * node = this->m_hi->path_rebalance(); | |||||
| if (node) | |||||
| { | |||||
| this->m_hi = node; | |||||
| --this->m_hi; | |||||
| } | |||||
| } | |||||
| if (this->m_stairs_lo - this->m_stairs_hi == 2) | |||||
| { | |||||
| return this->rotate(); | |||||
| } | |||||
| else if (this->m_stairs_lo - this->m_stairs_hi == -2) | |||||
| { | |||||
| return this->rotate(); | |||||
| } | |||||
| else | |||||
| assert(lol::abs(this->m_stairs_lo - this->m_stairs_hi) < 3); | |||||
| } | |||||
| enum Rotation { CW = 0, CCW = 1 }; | |||||
| tree_node * rotate(Rotation rotation) | |||||
| { | |||||
| if (rotation == CW) | |||||
| { | |||||
| tree_node * lo = this->m_lo; | |||||
| tree_node * lo_hi = this->m_lo->m_hi; | |||||
| this->m_lo->m_hi = this; | |||||
| this->m_lo = lo_hi; | |||||
| // TODO : Rebalance | |||||
| return lo; | |||||
| } | |||||
| else // rotation == CCW | |||||
| { | |||||
| tree_node * lo = this->m_lo; | |||||
| tree_node * lo_hi = this->m_lo->m_hi; | |||||
| this->m_lo->m_hi = this; | |||||
| this->m_lo = lo_hi; | |||||
| // TODO : Rebalance | |||||
| return lo; | |||||
| } | |||||
| } | |||||
| private: | |||||
| K m_key; | |||||
| V m_value; | |||||
| tree_node * m_lo; | |||||
| tree_node * m_hi; | |||||
| int m_stairs_lo; | |||||
| int m_stairs_hi; | |||||
| }; | |||||
| tree_node * m_root; | |||||
| }; | |||||
| } | |||||