我有两个AVL树,每个树按不同的参数排序相同的数据(比如,其中一个树实际存储数据,另一个树只指向它)。在示例中,左侧的树按左侧数字排序,右侧的树按右侧数字排序:
58 64
/ \ / \
22 73 22 58
/ \ / \ / \ / \
19 36 64 81 81 73 36 19
假设我想删除一个项目(来自两个树,因为它是相同的数据),但我只给出了左边的数字。例如,在调用removeLeft(6)
之后,我的树看起来像:
58 36
/ \ / \
22 73 22 58
/ \ \ / \ \
19 36 81 81 73 19
我可以在log(n)
时间内找到左侧树中的节点,如果我在要删除的节点上,我可以从每棵树的另一个log(n)
中的每个树中删除它。
但是,我需要从左侧树中的节点到右侧节点的链接:
58 ------>64
/ \ | / \
22 73 | 22 58
/ \ / \ | / \ / \
19 36 64 81 | 81 73 36 19
|______|
否则我需要在n
时间内找到右侧树中的节点,因为它没有按左数字排序。
我的Tree
类不允许直接访问节点,只允许直接访问数据(我希望保持这种方式)。
我别无选择,只能将我的数据结构实现为friend
类的Tree
类吗?那甚至会起作用吗?或者有一些优雅的方式来做这样的事情吗?
答案 0 :(得分:1)
这是我打算做的事,如果有人应该遇到这个问题......
如果我对为什么这是一个坏主意有任何有说服力的评论,我会删除答案/编辑它。
基本上,我将创建一个Forrest
类,它本质上是一个带有数据本身的List
,以及一个专门的AVL树的内部列表(Sapling
s ),我将Forrest
friend
Sapling
_______________ ... _______
Data: |19 |22 |...|81 |
|PTR->M7|PTR->M2|...|PTR->M1|
|PTR->N1|PTR->N2|...|PTR->N7|
_____
Saplings: |T1|T2|
T1:
N4:PTR->58
/ \
N2:PTR->22 N6:PTR->73
/ \ / \
N1:PTR->19 N3:PTR->36 N5:PTR->64 N7:PTR->81
T2:
M4:PTR->64
/ \
M2:PTR->22 M6:PTR->58
/ \ / \
M1:PTR->81 M3:PTR->73 M5:PTR->36 M7:PTR->19
。{/ p>
Compare
此外,我还会创建一个Tree
类,因此相同Forrest
类型的不同实例可能会有不同的排序,并允许Sapling
定义// Base AVL type, incomplete but for the purpose of this question it'll do
template<typename T>
class AVL {
public:
// Compare type, so different trees can sort differently
class Compare {
public:
virtual bool less(const& T, const& T) = 0;
virtual bool equal(const& T, const& T) = 0;
};
protected:
// Default compare type, to utilize type T's default comparison operators
class DefaultCompare : public AVL<T>::Compare {
public:
bool less(const& T a, const& T b) { return a<b; }
bool equal(const& T a, const& T b) { return a==b; }
};
// AVL tree node. Will be extended in the Sapling
class Node {
public:
Node *_parent, *_left, *_right;
T _data;
};
public:
AVL(const& AVL<T>::Compare = DefaultCompare());
};
排序指向数据的指针的方法。
基本AVL树:
Forrest
扩展它,以便与template<typename T>
class Sapling: public AVL<T> {
public:
friend class Forrest;
};
:
List
这是我将使用的template<typename T>
class List {
protected:
// A list node: prev, next and data
class Node {
public:
Node *_next, *_prev;
T _data;
};
// The list itself
Node* _head;
public:
... // Setters, getters, iterator... etc.
};
课程:
Forrest
定义template<typename T>
class Forrest: public List<T> {
private:
// Extend the list node to include all the Sapling nodes pointing to this data
class Node: public List<T>::Node {
List<AVL::Node*> _sapling_nodes;
};
// The Saplings themselves store pointers to list nodes, so the data itself
// is stored in the main list (the _head field, inherited from List<T>)
List<AVL<Forrest::Node*> > _saplings;
// Create a Compare object so pointers to the data can be compared in the saplings:
class ComparePtrs: public AVL<Forrest::Node*>::Compare {
public:
bool less(const& Node* a, const& Node* b) { return a->_data < b->_data; }
bool equal(const& Node*, const& Node*) { return a->_data == b->_data; }
};
};
类(事实上,Forrest 是列表):
{{1}}
嗯...
希望这有效。