Переглянути джерело

avl_tree: first incomplete draft

undefined
Guillaume Bittoun Sam Hocevar <sam@hocevar.net> 10 роки тому
джерело
коміт
cb896fae1a
1 змінених файлів з 177 додано та 0 видалено
  1. +177
    -0
      src/lol/base/avl_tree.h

+ 177
- 0
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;
};

}

Завантаження…
Відмінити
Зберегти