无法从指针(Node *)类型转换为const指针(const Node *&)

无法用指针(Node *)类型转换为const指针(const Node *&)。在以下代码中:
struct Node
{
	int val;
	int index;
	Node(){}
	Node(int v, int i) :val(v), index(i){}
};

struct CompareNode
{
	bool operator()(const Node *&lhs,const Node *&rhs)const
	{
		return lhs->val > rhs->val;
	}
};

void f()
{
	priority_queue<Node*, vector<Node *>, CompareNode> q;
	for (int i = 0; i < 10; ++i)
	{
		q.push(&Node(i, i + 1));
	}
}

编译代码时,会出现错误:无法将参数 1 从“Node *”转换为“const Node *&”,因为Node* p,表示指针p可变,指针p所指的对象也可变,而const Node *&q,表示指针q可变,但是指针q所指向的对象不可变。我们无法从“Node *p”转换为"const Node *&q",(1)假设p可以转换q,q是p的引用,即q是p的一个别名,p指向的对象是个非const对象,但是q指向的对象是个const对象,一个对象不可能同时是const对象和非const对象。所以编译器不允许从“Node *p”转换为"const Node *&q。传递给bool operator()(const Node *&lhs,const Node*&rhs)const,我们的目的是保证指针不可变,而不是保证指针所指向的对象不可变,所以函数bool operator()(const Node *&lhs,const Node *&rhs)const应该改写为bool operator()(Node *const &lhs,Node *const &rhs)const。也可改写成bool operator()(const Node *const &lhs,const Node *const &rhs)const。代码如下:
struct Node
{
	int val;
	int index;
	Node(){}
	Node(int v, int i) :val(v), index(i){}
};

struct CompareNode
{
	bool operator()(const Node *const &lhs,const Node *const &rhs)const 
	{
		return lhs->val > rhs->val;
	}
};

void f()
{
	priority_queue<Node*, vector<Node *>, CompareNode> q;
	for (int i = 0; i < 10; ++i)
	{
		q.push(&Node(i, i + 1));
	}
}



                
/** * implement a container like std::map */ #ifndef SJTU_MAP_HPP #define SJTU_MAP_HPP #include &lt;cstdio&gt; // only for std::less&lt;T&gt; #include &lt;functional&gt; #include &lt;cstddef&gt; #include &quot;utility.hpp&quot; #include &quot;exceptions.hpp&quot; namespace sjtu { template&lt; class Key, class T, class Compare = std::less &lt;Key&gt; &gt; class AAtree{ public: typedef pair&lt;const Key, T&gt; value_type; struct Node { Node *lson, *rson, *parent; int level; value_type data; Node(const value_type &amp;d, int lv = 1, Node *p = nullptr, Node *l = nullptr, Node *r = nullptr) : data(d), level(lv), parent(p), lson(l), rson(r) {} ~Node() { data.~value_type(); } }; Node *root; size_t tree_size; Compare comp; AAtree(): root(nullptr), tree_size(0) {} AAtree(const AAtree &amp;other) { root = copyTree(other.root, nullptr); tree_size = other.tree_size; } AAtree &amp;operator=(const AAtree &amp;other) { if (this != &amp;other) { clear(root); root = copyTree(other.root, nullptr); tree_size = other.tree_size; } return *this; } ~AAtree() { clear(root); tree_size = 0; } Node *skew(Node *node) { if (!node || !node-&gt;lson) return node; if (node-&gt;lson-&gt;level == node-&gt;level) { Node *L = node-&gt;lson; node-&gt;lson = L-&gt;rson; if (L-&gt;rson) L-&gt;rson-&gt;parent = node; L-&gt;rson = node; L-&gt;parent = node-&gt;parent; node-&gt;parent = L; return L; } return node; } Node *split(Node *node) { if (!node || !node-&gt;rson || !node-&gt;rson-&gt;rson) return node; if (node-&gt;level == node-&gt;rson-&gt;rson-&gt;level) { Node *R = node-&gt;rson; node-&gt;rson = R-&gt;lson; if (R-&gt;lson) R-&gt;lson-&gt;parent = node; R-&gt;lson = node; R-&gt;parent = node-&gt;parent; node-&gt;parent = R; ++R-&gt;level; return R; } return node; } Node *insert(Node *node, const value_type &amp;value, Node *parent = nullptr) { if (!node) { ++tree_size; return new Node(value, 1, parent); } if (comp(value.first, node-&gt;data.first)) { node-&gt;lson = insert(node-&gt;lson, value, node); node-&gt;lson-&gt;parent = node; } else if (comp(node-&gt;data.first, value.first)) { node-&gt;rson = insert(node-&gt;rson, value, node); node-&gt;rson-&gt;parent = node; } else return node; node = skew(node); node = split(node); return node; } // 删除节点正确处理父子关系 // void erase(Node*&amp; node, const Key&amp; key) { // if (!node) return; // if (comp(key, node-&gt;data.first)) { // erase(node-&gt;lson, key); // } else if (comp(node-&gt;data.first, key)) { // erase(node-&gt;rson, key); // } else { // if (node-&gt;lson &amp;&amp; node-&gt;rson) { // // 处理有两个子节点的情况 // Node* successor = findMin(node-&gt;rson); // Node *newNode = new Node(successor-&gt;data, node-&gt;level, node-&gt;parent, node-&gt;lson, node-&gt;rson); // if (newNode-&gt;lson) newNode-&gt;lson-&gt;parent = newNode; // if (newNode-&gt;rson) newNode-&gt;rson-&gt;parent = newNode; // if (newNode-&gt;parent) { // if (newNode-&gt;parent-&gt;lson == node) { // newNode-&gt;parent-&gt;lson = newNode; // } else { // newNode-&gt;parent-&gt;rson = newNode; // } // } // erase(newNode-&gt;rson, successor-&gt;data.first); // 递归删除后继节点 // delete node; // node = newNode; // } else { // Node* temp = node; // node = (node-&gt;lson) ? node-&gt;lson : node-&gt;rson; // delete temp; // 释放内存后,node指针已被上层更新 // } // } // // 删除后重新平衡 // if (node) { // node = skew(node); // node = split(node); // } // } Node *erase(Node *node, const Key &amp;key) { if (!node) return nullptr; if (comp(key, node-&gt;data.first)) { node-&gt;lson = erase(node-&gt;lson, key); if (node-&gt;lson) node-&gt;lson-&gt;parent = node; } else if (comp(node-&gt;data.first, key)) { node-&gt;rson = erase(node-&gt;rson, key); if (node-&gt;rson) node-&gt;rson-&gt;parent = node; } else { if (!node-&gt;lson &amp;&amp; !node-&gt;rson) { if (node-&gt;parent) { if (node-&gt;parent-&gt;lson == node) { node-&gt;parent-&gt;lson = nullptr; } else { node-&gt;parent-&gt;rson = nullptr; } } delete node; node = nullptr; --tree_size; return nullptr; } else if (!node-&gt;lson) { Node *temp = node-&gt;rson; temp-&gt;parent = node-&gt;parent; delete node; node = nullptr; --tree_size; return temp; } else if (!node-&gt;rson) { Node *temp = node-&gt;lson; temp-&gt;parent = node-&gt;parent; delete node; node = nullptr; --tree_size; return temp; } Node *predecessor = node-&gt;lson; while (predecessor-&gt;rson) predecessor = predecessor-&gt;rson; Node *newNode = new Node(predecessor-&gt;data, node-&gt;level, node-&gt;parent, node-&gt;lson, node-&gt;rson); if (newNode-&gt;lson) newNode-&gt;lson-&gt;parent = newNode; if (newNode-&gt;rson) newNode-&gt;rson-&gt;parent = newNode; if (newNode-&gt;parent) { if (newNode-&gt;parent-&gt;lson == node) { newNode-&gt;parent-&gt;lson = newNode; } else { newNode-&gt;parent-&gt;rson = newNode; } } newNode-&gt;lson = erase(newNode-&gt;lson, predecessor-&gt;data.first); if (newNode-&gt;lson) newNode-&gt;lson-&gt;parent = newNode; delete node; node = newNode; } if (node-&gt;lson &amp;&amp; node-&gt;rson) { size_t min_level = node-&gt;lson-&gt;level &lt; node-&gt;rson-&gt;level ? node-&gt;lson-&gt;level : node-&gt;rson-&gt;level; if (node-&gt;level &gt; min_level + 1) { node-&gt;level = min_level + 1; if (node-&gt;rson &amp;&amp; node-&gt;rson-&gt;level &gt; node-&gt;level) node-&gt;rson-&gt;level = node-&gt;level; } } node = skew(node); node-&gt;rson = skew(node-&gt;rson); if (node-&gt;rson) node-&gt;rson-&gt;rson = skew(node-&gt;rson-&gt;rson); node = split(node); node-&gt;rson = split(node-&gt;rson); return node; } Node *find(Node *node, const Key &amp;key) const { while (node) { if (comp(key, node-&gt;data.first)) node = node-&gt;lson; else if (comp(node-&gt;data.first, key)) node = node-&gt;rson; else return node; } return nullptr; } Node *findMin(Node *node) const { if (!node) return nullptr; // printf(&quot;In findmin: %d\n&quot;, (node)); while (node-&gt;lson) node = node-&gt;lson; // printf(&quot;finish find min\n&quot;); return node; } Node *findMax(Node *node) const { if (!node) return nullptr; while (node-&gt;rson) node = node-&gt;rson; return node; } Node *successor(Node *node) const { // printf(&quot;in successor\n&quot;); if (!node) return nullptr; // printf(&quot;in successor2\n&quot;); if (node-&gt;rson) return findMin(node-&gt;rson); // printf(&quot;in successor3\n&quot;); Node *parent = node-&gt;parent; while (parent &amp;&amp; node == parent-&gt;rson) { node = parent; parent = parent-&gt;parent; } // printf(&quot;finish successor\n&quot;); return parent; } Node *predecessor(Node *node) const { if (!node) return nullptr; if (node-&gt;lson) return findMax(node-&gt;lson); Node *parent = node-&gt;parent; while (parent &amp;&amp; node == parent-&gt;lson) { node = parent; parent = parent-&gt;parent; } return parent; } Node *copyTree(Node *node, Node *parent) { if (!node) return nullptr; Node *newNode = new Node(node-&gt;data, node-&gt;level, parent); newNode-&gt;lson = copyTree(node-&gt;lson, newNode); newNode-&gt;rson = copyTree(node-&gt;rson, newNode); return newNode; } void clear(Node *node) { if (!node) return; clear(node-&gt;lson); clear(node-&gt;rson); delete node; node = nullptr; } }; template&lt; class Key, class T, class Compare = std::less &lt;Key&gt; &gt; class map { public: /** * the internal type of data. * it should have a default constructor, a copy constructor. * You can use sjtu::map as value_type by typedef. */ typedef pair&lt;const Key, T&gt; value_type; AAtree&lt;Key, T, Compare&gt; aa_tree; /** * see BidirectionalIterator at CppReference for help. * * if there is anything wrong throw invalid_iterator. * like it = map.begin(); --it; * or it = map.end(); ++end(); */ typedef typename AAtree&lt;Key, T, Compare&gt;::Node Node; class const_iterator; class iterator { private: /** * TODO add data members * just add whatever you want. */ map* container; Node *node; public: iterator(map *c = nullptr, Node *n = nullptr): container(c), node(n) { // TODO } iterator(const iterator &amp;other):container(other.container), node(other.node) { // TODO } /** * TODO iter++ */ iterator operator++(int) { if (!node) throw invalid_iterator(); iterator temp = *this; node = container-&gt;aa_tree.successor(node); return temp; } /** * TODO ++iter */ iterator &amp;operator++() { if (!node) throw invalid_iterator(); node = container-&gt;aa_tree.successor(node); return *this; } /** * TODO iter-- */ iterator operator--(int) { iterator temp = *this; if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return temp; } /** * TODO --iter */ iterator &amp;operator--() { if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return *this; } /** * a operator to check whether two iterators are same (pointing to the same memory). */ value_type &amp;operator*() const { if (!node) throw invalid_iterator(); return node-&gt;data; } bool operator==(const iterator &amp;rhs) const { return node == rhs.node &amp;&amp; container == rhs.container; } bool operator==(const const_iterator &amp;rhs) const { return node == rhs.getNode() &amp;&amp; container == rhs.getContainer(); } /** * some other operator for iterator. */ bool operator!=(const iterator &amp;rhs) const { return node != rhs.node || container != rhs.container; } bool operator!=(const const_iterator &amp;rhs) const { return node != rhs.getNode() || container != rhs.getContainer(); } map *getContainer() const { return container; } Node *getNode() const { return node; } /** * for the support of it-&gt;first. * See &lt;http://kelvinh.github.io/blog/2013/11/20/overloading-of-member-access-operator-dash-greater-than-symbol-in-cpp/&gt; for help. */ value_type *operator-&gt;() const noexcept { // if (!node) throw invalid_iterator(); return &amp;(node-&gt;data); } }; class const_iterator { // it should has similar member method as iterator. // and it should be able to construct from an iterator. private: // data members. map* container; Node *node; public: // const_iterator(const map *c = nullptr, Node *n = nullptr): container(const_cast&lt;map*&gt;(c)), node(n) { // // TODO // } const_iterator(map *c = nullptr, Node *n = nullptr): container(c), node(n) { // TODO } const_iterator(const const_iterator &amp;other): container(other.container), node(other.node) { // TODO } const_iterator(const iterator &amp;other) { // TODO container = other.getContainer(); node = other.getNode(); } /** * TODO iter++ */ const_iterator operator++(int) { if (!node) throw invalid_iterator(); const_iterator temp = *this; node = container-&gt;aa_tree.successor(node); return temp; } /** * TODO ++iter */ const_iterator &amp;operator++() { if (!node) throw invalid_iterator(); node = container-&gt;aa_tree.successor(node); return *this; } /** * TODO iter-- */ const_iterator operator--(int) { const_iterator temp = *this; if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return temp; } /** * TODO --iter */ const_iterator &amp;operator--() { if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return *this; } /** * a operator to check whether two iterators are same (pointing to the same memory). */ const value_type &amp;operator*() const { if (!node) throw invalid_iterator(); return node-&gt;data; } bool operator==(const iterator &amp;rhs) const { return node == rhs.getNode() &amp;&amp; container == rhs.getContainer(); } bool operator==(const const_iterator &amp;rhs) const { return node == rhs.node &amp;&amp; container == rhs.container; } /** * some other operator for iterator. */ bool operator!=(const iterator &amp;rhs) const { return node != rhs.getNode() || container != rhs.getContainer(); } bool operator!=(const const_iterator &amp;rhs) const { return node != rhs.node || container != rhs.container; } map *getContainer() const { return container; } Node *getNode() const { return node; } /** * for the support of it-&gt;first. * See &lt;http://kelvinh.github.io/blog/2013/11/20/overloading-of-member-access-operator-dash-greater-than-symbol-in-cpp/&gt; for help. */ const value_type *operator-&gt;() const noexcept { // if (!node) throw invalid_iterator(); return &amp;(node-&gt;data); } }; /** * TODO two constructors */ map(): aa_tree() {} map(const map &amp;other): aa_tree(other.aa_tree) {} /** * TODO assignment operator */ map &amp;operator=(const map &amp;other) { if (this != &amp;other) { aa_tree = other.aa_tree; } return *this; } /** * TODO Destructors */ ~map() {} /** * TODO * access specified element with bounds checking * Returns a reference to the mapped value of the element with key equivalent to key. * If no such element exists, an exception of type `index_out_of_bound&#39; */ T &amp;at(const Key &amp;key) { auto node = aa_tree.find(aa_tree.root, key); if (!node) throw index_out_of_bound(); return node-&gt;data.second; } const T &amp;at(const Key &amp;key) const { auto node = aa_tree.find(aa_tree.root, key); if (!node) throw index_out_of_bound(); return node-&gt;data.second; } /** * TODO * access specified element * Returns a reference to the value that is mapped to a key equivalent to key, * performing an insertion if such key does not already exist. */ T &amp;operator[](const Key &amp;key) { auto node = aa_tree.find(aa_tree.root, key); if (node) return node-&gt;data.second; aa_tree.root = aa_tree.insert(aa_tree.root, value_type(key, T())); return aa_tree.find(aa_tree.root, key)-&gt;data.second; } /** * behave like at() throw index_out_of_bound if such key does not exist. */ const T &amp;operator[](const Key &amp;key) const { return at(key); } /** * return a iterator to the beginning */ iterator begin() { return iterator(this, aa_tree.findMin(aa_tree.root)); } const_iterator cbegin() const { return const_iterator(const_cast&lt;map*&gt;(this), aa_tree.findMin(aa_tree.root)); } /** * return a iterator to the end * in fact, it returns past-the-end. */ iterator end() { return iterator(this, nullptr); } const_iterator cend() const { return const_iterator(const_cast&lt;map*&gt;(this), nullptr); } /** * checks whether the container is empty * return true if empty, otherwise false. */ bool empty() const { return aa_tree.tree_size == 0; } /** * returns the number of elements. */ size_t size() const { return aa_tree.tree_size; } /** * clears the contents */ void clear() { aa_tree.clear(aa_tree.root); aa_tree.root = nullptr; aa_tree.tree_size = 0; } /** * insert an element. * return a pair, the first of the pair is * the iterator to the new element (or the element that prevented the insertion), * the second one is true if insert successfully, or false. */ pair&lt;iterator, bool&gt; insert(const value_type &amp;value) { auto node = aa_tree.find(aa_tree.root, value.first); if (node) return {iterator(this, node), false}; aa_tree.root = aa_tree.insert(aa_tree.root, value); node = aa_tree.find(aa_tree.root, value.first); return {iterator(this, node), true}; } /** * erase the element at pos. * * throw if pos pointed to a bad element (pos == this-&gt;end() || pos points an element out of this) */ void erase(iterator pos) { if (pos == end() || pos.getContainer() != this) throw invalid_iterator(); aa_tree.root = aa_tree.erase(aa_tree.root, (*pos).first); } /** * Returns the number of elements with key * that compares equivalent to the specified argument, * which is either 1 or 0 * since this container does not allow duplicates. * The default method of check the equivalence is !(a &lt; b || b &gt; a) */ size_t count(const Key &amp;key) const { return aa_tree.find(aa_tree.root, key) ? 1 : 0; } /** * Finds an element with key equivalent to key. * key value of the element to search for. * Iterator to an element with key equivalent to key. * If no such element is found, past-the-end (see end()) iterator is returned. */ iterator find(const Key &amp;key) { return iterator(this, aa_tree.find(aa_tree.root, key)); } const_iterator find(const Key &amp;key) const { return const_iterator(const_cast&lt;map*&gt;(this), aa_tree.find(aa_tree.root, key)); } }; } #endif 这段代码,Q.erase(it--)会失效,为什么?
05-28
/** * implement a container like std::map */ #ifndef SJTU_MAP_HPP #define SJTU_MAP_HPP #include &lt;cstdio&gt; // only for std::less&lt;T&gt; #include &lt;functional&gt; #include &lt;cstddef&gt; #include &quot;utility.hpp&quot; #include &quot;exceptions.hpp&quot; namespace sjtu { template&lt; class Key, class T, class Compare = std::less &lt;Key&gt; &gt; class AAtree{ public: typedef pair&lt;const Key, T&gt; value_type; struct Node { Node *lson, *rson, *parent; int level; value_type data; Node(const value_type &amp;d, int lv = 1, Node *p = nullptr, Node *l = nullptr, Node *r = nullptr) : data(d), level(lv), parent(p), lson(l), rson(r) {} }; Node *root; size_t tree_size; Compare comp; AAtree(): root(nullptr), tree_size(0) {} AAtree(const AAtree &amp;other) { root = copyTree(other.root, nullptr); tree_size = other.tree_size; } AAtree &amp;operator=(const AAtree &amp;other) { if (this != &amp;other) { clear(root); root = copyTree(other.root, nullptr); tree_size = other.tree_size; } return *this; } ~AAtree() { clear(root); tree_size = 0; } Node *skew(Node *node) { if (!node || !node-&gt;lson) return node; if (node-&gt;lson-&gt;level == node-&gt;level) { Node *L = node-&gt;lson; node-&gt;lson = L-&gt;rson; if (L-&gt;rson) L-&gt;rson-&gt;parent = node; L-&gt;rson = node; L-&gt;parent = node-&gt;parent; node-&gt;parent = L; return L; } return node; } Node *split(Node *node) { if (!node || !node-&gt;rson || !node-&gt;rson-&gt;rson) return node; if (node-&gt;level == node-&gt;rson-&gt;rson-&gt;level) { Node *R = node-&gt;rson; node-&gt;rson = R-&gt;lson; if (R-&gt;lson) R-&gt;lson-&gt;parent = node; R-&gt;lson = node; R-&gt;parent = node-&gt;parent; node-&gt;parent = R; ++R-&gt;level; return R; } return node; } Node *insert(Node *node, const value_type &amp;value, Node *parent = nullptr) { if (!node) { ++tree_size; return new Node(value, 1, parent); } if (comp(value.first, node-&gt;data.first)) { node-&gt;lson = insert(node-&gt;lson, value, node); node-&gt;lson-&gt;parent = node; } else if (comp(node-&gt;data.first, value.first)) { node-&gt;rson = insert(node-&gt;rson, value, node); node-&gt;rson-&gt;parent = node; } else return node; node = skew(node); node = split(node); return node; } Node *erase(Node *node, const Key &amp;key) { if (!node) return nullptr; if (comp(key, node-&gt;data.first)) { node-&gt;lson = erase(node-&gt;lson, key); if (node-&gt;lson) node-&gt;lson-&gt;parent = node; } else if (comp(node-&gt;data.first, key)) { node-&gt;rson = erase(node-&gt;rson, key); if (node-&gt;rson) node-&gt;rson-&gt;parent = node; } else { if (!node-&gt;lson &amp;&amp; !node-&gt;rson) { if (node-&gt;parent) { if (node-&gt;parent-&gt;lson == node) { node-&gt;parent-&gt;lson = nullptr; } else { node-&gt;parent-&gt;rson = nullptr; } } delete node; node = nullptr; --tree_size; return nullptr; } else if (!node-&gt;lson) { Node *temp = node-&gt;rson; temp-&gt;parent = node-&gt;parent; delete node; node = nullptr; --tree_size; return temp; } else if (!node-&gt;rson) { Node *temp = node-&gt;lson; temp-&gt;parent = node-&gt;parent; delete node; node = nullptr; --tree_size; return temp; } Node *predecessor = node-&gt;lson; while (predecessor-&gt;rson) predecessor = predecessor-&gt;rson; Node *newNode = new Node(predecessor-&gt;data, node-&gt;level, node-&gt;parent, node-&gt;lson, node-&gt;rson); if (newNode-&gt;lson) newNode-&gt;lson-&gt;parent = newNode; if (newNode-&gt;rson) newNode-&gt;rson-&gt;parent = newNode; if (newNode-&gt;parent) { if (newNode-&gt;parent-&gt;lson == node) { newNode-&gt;parent-&gt;lson = newNode; } else { newNode-&gt;parent-&gt;rson = newNode; } } newNode-&gt;lson = erase(newNode-&gt;lson, predecessor-&gt;data.first); if (newNode-&gt;lson) newNode-&gt;lson-&gt;parent = newNode; delete node; node = newNode; } if (node-&gt;lson &amp;&amp; node-&gt;rson) { size_t min_level = node-&gt;lson-&gt;level &lt; node-&gt;rson-&gt;level ? node-&gt;lson-&gt;level : node-&gt;rson-&gt;level; if (node-&gt;level &gt; min_level + 1) { node-&gt;level = min_level + 1; if (node-&gt;rson &amp;&amp; node-&gt;rson-&gt;level &gt; node-&gt;level) node-&gt;rson-&gt;level = node-&gt;level; } } node = skew(node); node-&gt;rson = skew(node-&gt;rson); if (node-&gt;rson) node-&gt;rson-&gt;rson = skew(node-&gt;rson-&gt;rson); node = split(node); node-&gt;rson = split(node-&gt;rson); return node; } Node *find(Node *node, const Key &amp;key) const { while (node) { if (comp(key, node-&gt;data.first)) node = node-&gt;lson; else if (comp(node-&gt;data.first, key)) node = node-&gt;rson; else return node; } return nullptr; } Node *findMin(Node *node) const { if (!node) return nullptr; // printf(&quot;In findmin: %d\n&quot;, (node)); while (node-&gt;lson) node = node-&gt;lson; // printf(&quot;finish find min\n&quot;); return node; } Node *findMax(Node *node) const { if (!node) return nullptr; while (node-&gt;rson) node = node-&gt;rson; return node; } Node *successor(Node *node) const { // printf(&quot;in successor\n&quot;); if (!node) return nullptr; // printf(&quot;in successor2\n&quot;); if (node-&gt;rson) return findMin(node-&gt;rson); // printf(&quot;in successor3\n&quot;); Node *parent = node-&gt;parent; while (parent &amp;&amp; node == parent-&gt;rson) { node = parent; parent = parent-&gt;parent; } // printf(&quot;finish successor\n&quot;); return parent; } Node *predecessor(Node *node) const { if (!node) return nullptr; if (node-&gt;lson) return findMax(node-&gt;lson); Node *parent = node-&gt;parent; while (parent &amp;&amp; node == parent-&gt;lson) { node = parent; parent = parent-&gt;parent; } return parent; } Node *copyTree(Node *node, Node *parent) { if (!node) return nullptr; Node *newNode = new Node(node-&gt;data, node-&gt;level, parent); newNode-&gt;lson = copyTree(node-&gt;lson, newNode); newNode-&gt;rson = copyTree(node-&gt;rson, newNode); return newNode; } void clear(Node *node) { if (!node) return; clear(node-&gt;lson); clear(node-&gt;rson); delete node; node = nullptr; } }; template&lt; class Key, class T, class Compare = std::less &lt;Key&gt; &gt; class map { public: /** * the internal type of data. * it should have a default constructor, a copy constructor. * You can use sjtu::map as value_type by typedef. */ typedef pair&lt;const Key, T&gt; value_type; AAtree&lt;Key, T, Compare&gt; aa_tree; /** * see BidirectionalIterator at CppReference for help. * * if there is anything wrong throw invalid_iterator. * like it = map.begin(); --it; * or it = map.end(); ++end(); */ typedef typename AAtree&lt;Key, T, Compare&gt;::Node Node; class const_iterator; class iterator { private: /** * TODO add data members * just add whatever you want. */ map* container; Node *node; public: iterator(map *c = nullptr, Node *n = nullptr): container(c), node(n) { // TODO } iterator(const iterator &amp;other):container(other.container), node(other.node) { // TODO } /** * TODO iter++ */ iterator operator++(int) { if (!node) throw invalid_iterator(); iterator temp = *this; node = container-&gt;aa_tree.successor(node); return temp; } /** * TODO ++iter */ iterator &amp;operator++() { if (!node) throw invalid_iterator(); node = container-&gt;aa_tree.successor(node); return *this; } /** * TODO iter-- */ iterator operator--(int) { iterator temp = *this; if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return temp; } /** * TODO --iter */ iterator &amp;operator--() { if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return *this; } /** * a operator to check whether two iterators are same (pointing to the same memory). */ value_type &amp;operator*() const { if (!node) throw invalid_iterator(); return node-&gt;data; } bool operator==(const iterator &amp;rhs) const { return node == rhs.node &amp;&amp; container == rhs.container; } bool operator==(const const_iterator &amp;rhs) const { return node == rhs.getNode() &amp;&amp; container == rhs.getContainer(); } /** * some other operator for iterator. */ bool operator!=(const iterator &amp;rhs) const { return node != rhs.node || container != rhs.container; } bool operator!=(const const_iterator &amp;rhs) const { return node != rhs.getNode() || container != rhs.getContainer(); } map *getContainer() const { return container; } Node *getNode() const { return node; } /** * for the support of it-&gt;first. * See &lt;http://kelvinh.github.io/blog/2013/11/20/overloading-of-member-access-operator-dash-greater-than-symbol-in-cpp/&gt; for help. */ value_type *operator-&gt;() const noexcept { // if (!node) throw invalid_iterator(); return &amp;(node-&gt;data); } }; class const_iterator { // it should has similar member method as iterator. // and it should be able to construct from an iterator. private: // data members. map* container; Node *node; public: // const_iterator(const map *c = nullptr, Node *n = nullptr): container(const_cast&lt;map*&gt;(c)), node(n) { // // TODO // } const_iterator(map *c = nullptr, Node *n = nullptr): container(c), node(n) { // TODO } const_iterator(const const_iterator &amp;other): container(other.container), node(other.node) { // TODO } const_iterator(const iterator &amp;other) { // TODO container = other.getContainer(); node = other.getNode(); } /** * TODO iter++ */ const_iterator operator++(int) { if (!node) throw invalid_iterator(); const_iterator temp = *this; node = container-&gt;aa_tree.successor(node); return temp; } /** * TODO ++iter */ const_iterator &amp;operator++() { if (!node) throw invalid_iterator(); node = container-&gt;aa_tree.successor(node); return *this; } /** * TODO iter-- */ const_iterator operator--(int) { const_iterator temp = *this; if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return temp; } /** * TODO --iter */ const_iterator &amp;operator--() { if (node == nullptr) { node = container-&gt;aa_tree.findMax(container-&gt;aa_tree.root); if (!node) throw invalid_iterator(); } else { node = container-&gt;aa_tree.predecessor(node); if (!node) throw invalid_iterator(); } return *this; } /** * a operator to check whether two iterators are same (pointing to the same memory). */ const value_type &amp;operator*() const { if (!node) throw invalid_iterator(); return node-&gt;data; } bool operator==(const iterator &amp;rhs) const { return node == rhs.getNode() &amp;&amp; container == rhs.getContainer(); } bool operator==(const const_iterator &amp;rhs) const { return node == rhs.node &amp;&amp; container == rhs.container; } /** * some other operator for iterator. */ bool operator!=(const iterator &amp;rhs) const { return node != rhs.getNode() || container != rhs.getContainer(); } bool operator!=(const const_iterator &amp;rhs) const { return node != rhs.node || container != rhs.container; } map *getContainer() const { return container; } Node *getNode() const { return node; } /** * for the support of it-&gt;first. * See &lt;http://kelvinh.github.io/blog/2013/11/20/overloading-of-member-access-operator-dash-greater-than-symbol-in-cpp/&gt; for help. */ const value_type *operator-&gt;() const noexcept { // if (!node) throw invalid_iterator(); return &amp;(node-&gt;data); } }; /** * TODO two constructors */ map(): aa_tree() {} map(const map &amp;other): aa_tree(other.aa_tree) {} /** * TODO assignment operator */ map &amp;operator=(const map &amp;other) { if (this != &amp;other) { aa_tree = other.aa_tree; } return *this; } /** * TODO Destructors */ ~map() {} /** * TODO * access specified element with bounds checking * Returns a reference to the mapped value of the element with key equivalent to key. * If no such element exists, an exception of type `index_out_of_bound&#39; */ T &amp;at(const Key &amp;key) { auto node = aa_tree.find(aa_tree.root, key); if (!node) throw index_out_of_bound(); return node-&gt;data.second; } const T &amp;at(const Key &amp;key) const { auto node = aa_tree.find(aa_tree.root, key); if (!node) throw index_out_of_bound(); return node-&gt;data.second; } /** * TODO * access specified element * Returns a reference to the value that is mapped to a key equivalent to key, * performing an insertion if such key does not already exist. */ T &amp;operator[](const Key &amp;key) { auto node = aa_tree.find(aa_tree.root, key); if (node) return node-&gt;data.second; aa_tree.root = aa_tree.insert(aa_tree.root, value_type(key, T())); return aa_tree.find(aa_tree.root, key)-&gt;data.second; } /** * behave like at() throw index_out_of_bound if such key does not exist. */ const T &amp;operator[](const Key &amp;key) const { return at(key); } /** * return a iterator to the beginning */ iterator begin() { return iterator(this, aa_tree.findMin(aa_tree.root)); } const_iterator cbegin() const { return const_iterator(const_cast&lt;map*&gt;(this), aa_tree.findMin(aa_tree.root)); } /** * return a iterator to the end * in fact, it returns past-the-end. */ iterator end() { return iterator(this, nullptr); } const_iterator cend() const { return const_iterator(const_cast&lt;map*&gt;(this), nullptr); } /** * checks whether the container is empty * return true if empty, otherwise false. */ bool empty() const { return aa_tree.tree_size == 0; } /** * returns the number of elements. */ size_t size() const { return aa_tree.tree_size; } /** * clears the contents */ void clear() { aa_tree.clear(aa_tree.root); aa_tree.root = nullptr; aa_tree.tree_size = 0; } /** * insert an element. * return a pair, the first of the pair is * the iterator to the new element (or the element that prevented the insertion), * the second one is true if insert successfully, or false. */ pair&lt;iterator, bool&gt; insert(const value_type &amp;value) { auto node = aa_tree.find(aa_tree.root, value.first); if (node) return {iterator(this, node), false}; aa_tree.root = aa_tree.insert(aa_tree.root, value); node = aa_tree.find(aa_tree.root, value.first); return {iterator(this, node), true}; } /** * erase the element at pos. * * throw if pos pointed to a bad element (pos == this-&gt;end() || pos points an element out of this) */ void erase(iterator pos) { if (pos == end() || pos.getContainer() != this) throw invalid_iterator(); aa_tree.root = aa_tree.erase(aa_tree.root, (*pos).first); } /** * Returns the number of elements with key * that compares equivalent to the specified argument, * which is either 1 or 0 * since this container does not allow duplicates. * The default method of check the equivalence is !(a &lt; b || b &gt; a) */ size_t count(const Key &amp;key) const { return aa_tree.find(aa_tree.root, key) ? 1 : 0; } /** * Finds an element with key equivalent to key. * key value of the element to search for. * Iterator to an element with key equivalent to key. * If no such element is found, past-the-end (see end()) iterator is returned. */ iterator find(const Key &amp;key) { return iterator(this, aa_tree.find(aa_tree.root, key)); } const_iterator find(const Key &amp;key) const { return const_iterator(const_cast&lt;map*&gt;(this), aa_tree.find(aa_tree.root, key)); } }; } #endif 下面是valgrind的报错: ==9160== Invalid read of size 4 ==9160== at 0x10FDB9: check13() (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x110CC9: main (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== Address 0x6c8bcfc is 28 bytes inside a block of size 40 free&#39;d ==9160== at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==9160== by 0x1150A1: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115292: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x114F98: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== Block was alloc&#39;d at ==9160== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==9160== by 0x1147E3: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x114850: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x114850: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x1148A7: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::insert(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, sjtu::pair&lt;int const, int&gt; const&amp;, sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== Test 13 Passed! Test 14 Passed! ==9160== ==9160== HEAP SUMMARY: ==9160== in use at exit: 0 bytes in 0 blocks ==9160== total heap usage: 325,886 allocs, 325,886 frees, 13,111,520 bytes allocated ==9160== ==9160== All heap blocks were freed -- no leaks are possible ==9160== ==9160== ERROR SUMMARY: 4308 errors from 1 contexts (suppressed: 0 from 0) ==9160== ==9160== 4308 errors in context 1 of 1: ==9160== Invalid read of size 4 ==9160== at 0x10FDB9: check13() (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x110CC9: main (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== Address 0x6c8bcfc is 28 bytes inside a block of size 40 free&#39;d ==9160== at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so) ==9160== by 0x1150A1: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) ==9160== by 0x115001: sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::erase(sjtu::AAtree&lt;int, int, std::less&lt;int&gt; &gt;::Node*, int const&amp;) (in /root/code/STLite/STLite-ACM-2025/map/build/map_three_men) map_three_men: bool check13(){ // erase(it--) sjtu::map&lt;int, int&gt; Q; std::map&lt;int, int&gt; stdQ; int num[30001]; num[0] = 0; for(int i = 1; i &lt;= 30000; i++) num[i] = num[i - 1] + rand() % 325 + 1; for(int i = 1; i &lt;= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]); for(int i = 1; i &lt;= 30000; i++){ int t = rand(); stdQ[num[i]] = t; Q[num[i]] = t; } // cout &lt;&lt; &quot;Stage 1&quot; &lt;&lt; endl; sjtu::map&lt;int, int&gt;::iterator it; std::map&lt;int, int&gt;::iterator stdit; for(int i = 1; i &lt;= 60000; i++) swap(num[rand() % 30000 + 1], num[rand() % 30000 + 1]); for(int i = 1; i &lt;= 10325; i++){ it = Q.find(num[i]); if(it != Q.begin()) { Q.erase(it--); // cout &lt;&lt; &quot;Erase it&quot; &lt;&lt; endl; } stdit = stdQ.find(num[i]); if(stdit != stdQ.begin()) { stdQ.erase(stdit--); // cout &lt;&lt; &quot;Erase it&quot; &lt;&lt; endl; } // cout &lt;&lt; &quot;i = &quot; &lt;&lt; i &lt;&lt; &quot; it, std = &quot; &lt;&lt; (it)-&gt;first &lt;&lt; &quot; &quot; &lt;&lt; stdit-&gt;first &lt;&lt; endl; if(it -&gt; first != stdit -&gt; first)return 0; } // cout &lt;&lt; &quot;Stage 2&quot; &lt;&lt; endl; if(Q.size() != stdQ.size()) return 0; it = Q.begin(); // cout &lt;&lt; &quot;Stage 3&quot; &lt;&lt; endl; for(stdit = stdQ.begin(); stdit != stdQ.end(); stdit++){ if(stdit -&gt; first != it -&gt; first) return 0; if(stdit -&gt; second != (*it).second) return 0; it++; } stdit = --stdQ.end(); for(it = --Q.end(); it != Q.begin(); it--){ if(stdit -&gt; first != it -&gt; first) return 0; if(stdit -&gt; second != (*it).second) return 0; stdit--; } return 1; }
05-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值