From cb896fae1a0dd7e718d0b631e8fb658dbddb3324 Mon Sep 17 00:00:00 2001
From: Guillaume Bittoun <guillaume.bittoun@gmail.com>
Date: Wed, 8 Oct 2014 13:58:44 +0000
Subject: [PATCH] avl_tree: first incomplete draft

---
 src/lol/base/avl_tree.h | 177 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 177 insertions(+)
 create mode 100644 src/lol/base/avl_tree.h

diff --git a/src/lol/base/avl_tree.h b/src/lol/base/avl_tree.h
new file mode 100644
index 00000000..8157e66d
--- /dev/null
+++ b/src/lol/base/avl_tree.h
@@ -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;
+};
+
+}