迷宫问题提到过键值对查询,最坏情况查询效率是,总之比顺序查询快得多。
这次基于AVL树(3+4重构)实现map,以及其中序遍历的迭代器。
除了增删节点外,迭代器也是一大难点...之前没啥思路来着。大佬提示用栈作迭代器,其实对于动态存储的容器,随着容器元素的修改要维护额外的数据结构也不容易,最后还是中序遍历。
中序遍历好在按照键值升序排序的,重载迭代器自减运算之后也支持降序,一个迭代器可以对应好几棵树,说明迭代器不仅仅保存结点指针。换句话说迭代器end里除了空指针,还存储了树的指针。有树的指针就可以找到根节点,保证了自减后可以迭代到begin。
template<typename Type_key, typename Type_value>
struct _map {
struct _pair {
friend struct _map;
const Type_key first;
Type_value second;
protected:
int height;
_pair *lchild, *rchild, *parent;
_pair(const Type_key key, Type_value value, _pair *parent) :first(key), second(value), height(1), lchild(0), rchild(0), parent(parent) {}
~_pair() {
if (lchild) delete lchild;
if (rchild) delete rchild;
}
};
private:
int SIZE;
_pair *root;
/*获得孩子的高度*/
void getheightbelow(_pair *p, int &l, int &r) {
l = p->lchild ? p->lchild->height : 0;
r = p->rchild ? p->rchild->height : 0;
}
/*通过孩子更新高度*/
void updateheight(_pair *p) {
int l, r;
getheightbelow(p, l, r);
p->height = 1 + (l > r ? l : r);
}
/*更新自己及祖先的高度*/
void updateheightabove(_pair *p) {
int l, r;
while (p) {
getheightbelow(p, l, r);
p->height = 1 + (l > r ? l : r);
p = p->parent;
}
}
void balance(_pair *g) {
_pair *p, *v, *gp;
int l, r;
while (g) {
getheightbelow(g, l, r);
if ((l - r) == 2 || (r - l) == 2) {
/*g失衡,找到g的父亲*/
gp = g->parent;
if (l > r) {
p = g->lchild;
getheightbelow(p, l, r);
if (l>r) {
v = p->lchild;
g = connect34(v, p, g, v->lchild, v->rchild, p->rchild, g->rchild);
}
else {
v = p->rchild;
g = connect34(p, v, g, p->lchild, v->lchild, v->rchild, g->rchild);
}
}
else {
p = g->rchild;
getheightbelow(p, l, r);
if (r>l) {
v = p->rchild;
g = connect34(g, p, v, g->lchild, p->lchild, v->lchild, v->rchild);
}
else {
v = p->lchild;
g = connect34(g, v, p, g->lchild, v->lchild, v->rchild, p->rchild);
}
}
g->parent = gp;
/*若旧g的父亲存在,新g成为旧g父亲的孩子*/
if (gp) {
if (g->first < gp->first) gp->lchild = g;
else gp->rchild = g;
}
else root = g;
updateheightabove(g);
}
g = g->parent;
}
}
/*3+4重构返回新g结点*/
_pair *connect34(_pair *a, _pair *b, _pair *c, _pair *T0, _pair *T1, _pair *T2, _pair *T3) {
a->lchild = T0; if (T0) T0->parent = a;
a->rchild = T1; if (T1) T1->parent = a;
updateheight(a);
c->lchild = T2; if (T2) T2->parent = c;
c->rchild = T3; if (T3) T3->parent = c;
updateheight(c);
b->lchild = a; a->parent = b;
b->rchild = c; c->parent = b;
return b;
}
/*判断np应该是祖先的左还是右孩子,并连接np和祖先,np不一定存在*/
void lor(_pair *parent, _pair *np,const Type_key key) {
if (parent) {
if (key < parent->first) parent->lchild = np;
else parent->rchild = np;
}
else root = np;
if (np) np->parent = parent;
}
/*删除p结点*/
void remove(_pair *p) {
_pair *parent = p->parent, *np = 0;
/*当p有左右孩子*/
if (p->lchild&&p->rchild) {
_pair *npp = 0;
np = p->lchild;
/*找到左边最右的孩子作为被替换结点np*/
while (np->rchild) np = np->rchild;
/*找到被替换节点的父亲npp*/
npp = np->parent;
/*若被替换节点的父亲是要被删除的结点,直接拿np替换p*/
if (npp == p) {
lor(parent, np, p->first);
p->rchild->parent = np;
np->rchild = p->rchild;
updateheightabove(np);
balance(np);
}
else {
/*若被替换的结点np有左孩子,把np的左孩子作为npp的右孩子*/
if (np->lchild) {
npp->rchild = np->lchild;
np->lchild->parent = npp;
}
p->lchild->parent = np;
p->rchild->parent = np;
np->lchild = p->lchild;
np->rchild = p->rchild;
npp->rchild = 0;
lor(parent, np, p->first);
updateheightabove(npp);
balance(npp);
}
}
else {
/*当p只有一个孩子,直接用它的孩子替换,若没有孩子,np为空*/
if (p->lchild) np = p->lchild;
else if (p->rchild) np = p->rchild;
lor(parent, np, p->first);
updateheightabove(parent);
balance(parent);
}
p->lchild = 0, p->rchild = 0;
delete p;
SIZE--;
return;
}
public:
_map() :root(0), SIZE(0) {}
~_map() { if (root) delete root; }
void clear() { if (root) delete root; SIZE = 0; root = 0; }
int size() { return SIZE; }
struct _iterator {
_map *m;
_pair *p;
_iterator(_map *m = 0, _pair *p = 0) :m(m), p(p) {}
_pair *operator->() { return p; }
_iterator operator++(int) {
_pair *pre = p;
if (p == 0) throw "invalid index\n";
/*当p有右孩子,找到最左的右孩子*/
if (p->rchild) {
p = p->rchild;
while (p->lchild) p = p->lchild;
}
/*当p没有右孩子,p的祖先是下个结点的左孩子*/
else {
while (p->parent) {
if (p->parent->lchild == p) break;
p = p->parent;
}
p = p->parent;
}
return _iterator(m, pre);
}
_iterator &operator--() {
/*从根节点找到最右的孩子*/
if (p == 0) {
p = m->root;
if (p) while (p->rchild) p = p->rchild;
}
else {
if (p->lchild) {
p = p->lchild;
while (p->rchild) p = p->rchild;
}
else {
while (p->parent) {
if (p->parent->rchild == p) break;
p = p->parent;
}
p = p->parent;
}
}
return *this;
}
bool operator!=(_iterator o) { return p != o.p; }
bool operator==(_iterator o) { return p == o.p; }
};
/*最左的孩子*/
_iterator begin() {
_pair *p = root;
if (p) while (p->lchild) p = p->lchild;
return _iterator(this, p);
}
_iterator end() { return _iterator(this, 0); }
_pair &insert(const Type_key key, Type_value value, bool rep = 1) {
if (root == 0) {
root = new _pair(key, value, 0);
SIZE++;
return *root;
}
_pair *p = root;
_pair *parent = 0;
while (p) {
parent = p;
if (key < p->first) {
p = p->lchild;
}
else if (key > p->first) {
p = p->rchild;
}
else {
if (rep) p->second = value;
return *p;
}
}
_pair *node = new _pair(key, value, parent);
if (key < parent->first) parent->lchild = node;
else parent->rchild = node;
updateheightabove(parent);
balance(parent->parent);
SIZE++;
return *node;
}
void erase(const Type_key key) {
_pair *p = root;
while (p) {
if (key < p->first) p = p->lchild;
else if (key > p->first) p = p->rchild;
else {
remove(p);
return;
}
}
}
_pair &search(const Type_key key) {
_pair *p = root;
while (p) {
if (key < p->first) p = p->lchild;
else if (key > p->first) p = p->rchild;
else return *p;
}
Type_value value = Type_value();
return insert(key, value);
}
Type_value &operator[](Type_key key) { return search(key).second; }
};
存储类的时候记得写无参构造函数。