map类简单实现

迷宫问题提到过键值对查询,最坏情况查询效率是\Theta \left ( \log n \right ),总之比顺序查询快得多。

这次基于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; }
};

存储类的时候记得写无参构造函数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值