基于二叉搜索树的map的c++实现

background: COMP 2012H assignment 5

level: *****

最近几周在学template的时候感觉总是心不在焉,导致基本对这些内容没有理解。dekai如今布置了一道用binary search tree的数据结构来实现map的assignment,我也一时间陷入了迷茫。

以前总是觉得写code这件事情的无用功做的太多了,总是想不清楚自己要干什么。

我一位很亲近的朋友告诉我,你写code当然不像你做数学做一道就是一道,你写code自然要花费许多无用功,但是不要不信你所得到的经验。

做每一步都思考的话可能真的会有提高吧。


关于基于template的文件为什么都只有一个hpp文件的原因,是因为这货不像是平常的c++的class或者function了,template这东西只有在被调用的时候才进行实例化,所以如果按平常一样把其定义和声明分开是会造成linker报错的。解决方法是有几个不同的,但是一般都是直接把定义和声明都放在.hpp的文件里面。

(好吧虽然很丑但是我就是这么干了你来打我啊)


#include <iostream>
#include <utility>
#include <iterator>

#ifndef BSTMAP_HPP
#define BSTMAP_HPP

using namespace std;
template<typename Key, typename T>
class bstmap
{
  typedef pair<const Key, T>  value_type;
  typedef bstmap<Key, T>      Self;
  typedef Key                 key_type;
  typedef T                   data_type;
  typedef T                   mapped_type;
  typedef unsigned int        size_type;
  typedef int                 difference_type;

private:
  // definition of node struct, use it as a node in the whole tree
  // parent_m record parent node
  // left_m record left_child, right_m record right_child
  struct node_t {
    node_t(const pair<const Key,T>& x) : value_m(x),
					 parent_m(NULL),
					 left_m(NULL),
					 right_m(NULL) {}
    pair<const Key,T> value_m;
    node_t* parent_m;
    node_t* left_m;
    node_t* right_m;
  };
  
public:
  // default constructor of a bstmap
  bstmap() : root_m(NULL), size_m(0) {}
  
  // overload copy constructor to do a deep copy
  bstmap(const Self& x) {
    root_m = _copy(x.root_m);
    size_m = x.size_m;
  }

public:
  class iterator {
  public:
    typedef std::input_iterator_tag iterator_category;
    typedef value_type* pointer;
    typedef value_type& reference;
    
    // make bstmap as a friend class so bstmap can use iterator
    friend class bstmap;
    
    // we donnot need to deep copy since this iterator point to same container
    iterator(bstmap* map, node_t* node) : map_m(map),node_m(node) {}
    iterator(const iterator& x) : map_m(x.map_m),node_m(x.node_m) {}

    // iterator::it_begin() return the leftmost node in the whole tree
    iterator it_begin() {
      node_t* result = NULL;
      while (node_m != NULL ) {
	result = node_m;
	node_m = node_m -> left_m;
      }
      return iterator(map_m,result);
    }
    
    // iterator::it_end() return the NULL iterator
    iterator it_end() {
      return iterator(map_m,NULL);
    }

    // overload operator, need not be deep copy
    iterator& operator=(const iterator& x) {
      map_m = x.map_m;
      node_m = x.node_m;
      return *this;
    }

    // overload comparison operator
    bool operator==(const iterator& x) {
      return node_m == x.node_m;
    }
    
    bool operator!=(const iterator& x) {
      return node_m != x.node_m;
    }
    
    reference operator*() {
      if (node_m == NULL) {
	pair<const Key,T> m = make_pair(Key(),T());
	node_m = new node_t(m);
      }
      return node_m -> value_m;
    }

    pointer operator->() {
      if (node_m == NULL) {
	pair<const Key,T> m = make_pair(Key(),T());
	node_m = new node_t(m);
      }
      return &(node_m -> value_m);
    }

    iterator operator++() {
      node_m = map_m -> _successor(node_m);
      return *this;
    }

    iterator operator++(int) {
      iterator ret(*this);
      node_m = map_m -> _successor(node_m);
      return ret;
    }

    // data members in the iterator class
  private:
    // iterator need to know which node it is pointing to
    bstmap* map_m; 
    node_t* node_m;
  };

  class const_iterator {
    typedef std::input_iterator_tag iterator_category;
    typedef const pair<const Key,T> value_type;
    typedef value_type* pointer;
    typedef value_type& reference;

    friend class iterator;
    friend class bstmap;
  public:
    // default constructor of const_iterator
    const_iterator(bstmap* map,node_t* node) : map_m(map_m), node_m(node) {}
    
    // copy constructor of const_iterator
    const_iterator(const const_iterator& x) : map_m(x.map_m), node_m(x.node_m) {}
    
    const_iterator(const iterator& x) : map_m(x.map_m), node_m(x.node_m) {}
    
    const_iterator it_begin() {
      node_t* result = NULL;
      while (node_m != NULL) {
	result = node_m;
	node_m = node_m -> left_m;
      }
      return const_iterator(map_m,result);
    }

    const_iterator it_end() {
      return iterator(map_m,NULL);
    }

    const_iterator& operator=(const const_iterator& x) {
      map_m = x.map_m;
      node_m = x.node_m;
      return *this;
    }
  
    bool operator==(const const_iterator& x) {
      return node_m == x.node_m;
    }

    bool operator!=(const const_iterator& x) {
      return node_m != x.node_m;
    }

    reference operator*() {
      if (node_m == NULL) {
	const pair<const Key,T> m = make_pair(Key(),T());
	node_m = new node_t(m);
      }
      return node_m -> value_m;
    }

    pointer operator->() {
      if (node_m == NULL) {
	const pair<const Key,T> m = make_pair(Key(),T());
	node_m = new node_t(m);
      }
      return &(node_m -> value_m);
    }

    const_iterator operator++() {
      node_m = map_m -> _successor(node_m);
      return *this;
    }

    const_iterator operator++(int) {
      const_iterator ret(*this);
      node_m = map_m -> _successor(node_m);
      return ret;
    }

  private:
    bstmap* map_m;
    node_t* node_m;
  };
  


  // implementation of member functions in bstmap
public:
  
  // overload assignment operator, need to do deep copy
  Self& operator=(const bstmap<Key,T>& x) {
    clear();
    root_m = _copy(x.root_m);
    return *this;
  }

  // return the left_most leaf in the tree structure
  iterator begin() {
    iterator it_ret(this,root_m);
    return it_ret.it_begin();
  }

  const_iterator begin() const {
    const_iterator it_ret(this,root_m);
    return it_ret.it_begin();
  }

  iterator end() {
    iterator it_ret(this,root_m);
    return it_ret.it_end();
  }

  const_iterator end() const {
    const_iterator it_ret(this,root_m);
    return it_ret.it_end();
  }

  bool empty() const {
    if (this->size() == 0) return true;
    else return false;
  }

  size_type size() const {
    return size_m;
  }


  // the insert function
  pair<iterator,bool> insert(const pair<const Key, T>& x) {
    // case 1: if the tree is empty now, take x as the empty node
    if (root_m == NULL) {
      root_m = new node_t(x);
      size_m += 1;
      return make_pair(iterator(this,root_m),true);
    }

    // then try to find whether the key is inserted
    pair<node_t*,bool> m = _find(x.first);
    
    if (m.second) {
      // if the equivalent key exists
      return make_pair(iterator(this,m.first),false);
    } else {
      // else we can insert it
      node_t* new_node = new node_t(x);
      // compare two key , x.first is the new_node's key
      // m.first->value_m.first is the closest parent key
      if (x.first > (m.first -> value_m).first) {
	new_node -> parent_m = m.first;
	(m.first) -> right_m = new_node;	
	size_m += 1;
	return make_pair(iterator(this,new_node),true);
      } else {
	new_node -> parent_m = m.first;
	(m.first) -> left_m = new_node;
	size_m += 1;
	return make_pair(iterator(this,new_node),true);
      }
    }
  }

  // the erase function
  void erase(iterator pos) {
    node_t* target_node = pos.node_m;
    if (target_node == NULL) return;
    if (target_node -> right_m == NULL && target_node -> left_m == NULL) {
      node_t* parent_node = target_node -> parent_m;  
      // when the target node has parent node
      if (parent_node != NULL) {
	if (parent_node -> left_m == target_node) {
	  parent_node -> left_m = NULL;
	  size_m -= 1;
	} else {
	  parent_node -> right_m = NULL;
	  size_m -= 1;
	}
      }
      // the target_node is a single node in this tree
      else {
	root_m = NULL;
	size_m -= 1;
      }
    } else if (target_node -> right_m != NULL && target_node -> left_m != NULL){
      node_t* y = _successor(target_node);
      node_t* z = target_node;
      _swap_node(y,z);
      if (z->right_m == NULL) {
	node_t* parent_node = z->parent_m;
	parent_node -> left_m = NULL;
	size_m -= 1;
      } else {
	node_t* parent_node = z -> parent_m;
	node_t* changed_node = z -> right_m;
	parent_node -> left_m = changed_node;
	z -> parent_m = NULL;
	z -> right_m = NULL;
	size_m -= 1;
      }
    } else {
      node_t* parent_node = target_node -> parent_m;
      node_t* changed_node = (target_node -> right_m == NULL) ? target_node -> left_m : target_node -> right_m;
      if (parent_node == NULL) {
	// erase a root node which has one child
	size_m -= 1;
	root_m = changed_node;
	changed_node -> parent_m = NULL;
      } else if (parent_node -> left_m == target_node) {
	parent_node -> left_m = changed_node;
	changed_node -> parent_m = parent_node;
	size_m -= 1;
      } else if (parent_node -> right_m == target_node) {
	parent_node -> right_m = changed_node;
	changed_node -> parent_m = parent_node;
	size_m -= 1;
      }
    }
  }

  size_type erase(const Key& x) {
    pair<node_t*, bool> m = _find(x);
    if (m.second) {
      node_t* target_node = m.first;
      iterator it(this,target_node);
      this->erase(it);
      return 1;
    } else {
      return 0;
    }
  }

  void clear() {
    _recursive_destroy(root_m);
    root_m = NULL;
    size_m = 0;
  }
  
  iterator find(const Key& x) {
    pair<node_t*, bool> m = _find(x);
    if (m.second) {
      return iterator(this,m.first);
    } else {
      return iterator(this,NULL);
    }
  }

  const_iterator find(const Key& x) const {
    pair<node_t*, bool> m = _find(x);
    if (m.second) {
      return iterator(this,m.first);
    } else {
      return iterator(this,NULL);
    }
  }

  size_type count(const Key& x) const {
    pair<node_t*, bool> m = _find(x);
    if (m.second) return 1;
    else return 0;
  }
  
  T& operator[](const Key& k) {
    pair<node_t*, bool> m = _find(k);
    if (m.second) {
      return (m.first -> value_m).second;
    } else {
      this->insert(make_pair(k,T()));
      pair<node_t*, bool> n = _find(k);
      return (n.first -> value_m).second;
    }
    // whether insert or not?
  }

private:

  void _recursive_destroy(node_t* node_m) {
    if (node_m == NULL) return; 
    if (node_m -> left_m != NULL) {
      _recursive_destroy(node_m->left_m);
      node_m -> left_m = NULL;
    }

    if (node_m -> right_m != NULL) {
      _recursive_destroy(node_m->right_m);
      node_m -> right_m = NULL;
    }
    node_t* parent_node = node_m -> parent_m;
    if (parent_node != NULL) {
      if (parent_node -> left_m == node_m) {
	parent_node -> left_m = NULL;
      } else {
	parent_node -> right_m = NULL;
      }
    }
    node_m = NULL;
  }

  // swap function
  void _swap_node(node_t* node1, node_t* node2) {
    node_t* parent1_tmp = node1 -> parent_m;
    node_t* left1_tmp = node1 -> left_m;
    node_t* right1_tmp = node1 -> right_m;
    node_t* parent2_tmp = node2 -> parent_m;
    node_t* left2_tmp = node2 -> left_m;
    node_t* right2_tmp = node2 -> right_m;
    node_t* node_2 = node2;
    if (parent1_tmp -> left_m == node1) {
      parent1_tmp -> left_m = node2;
    } else {
      parent1_tmp -> right_m = node2;
    }
    node2 -> left_m = left1_tmp;
    node2 -> right_m = right1_tmp;
    if (parent2_tmp -> left_m = node_2) {
      parent2_tmp -> left_m = node1;
    } else {
      parent2_tmp -> right_m = node1;
    }
    node1 -> left_m = left2_tmp;
    node1 -> right_m = right2_tmp;
  }
 
  // here is a copy function for deep_copy
  // avoid shallow copy for improper destruction
  node_t* _copy(node_t* node_m) {
    if (node_m == NULL) return NULL;
    node_t* new_node = new node_t(node_m->value_m);
    new_node -> left_m = _copy(node_m->left_m);
    if (new_node -> left_m != NULL) {
      new_node -> left_m -> parent_m = new_node;
    }
    new_node -> right_m = _copy(node_m->right_m);
    if (new_node -> right_m != NULL) {
      new_node -> right_m -> parent_m = new_node;
    }    
    return new_node;
  }

  // here is the function to find the successor
  node_t* _successor(node_t* ele) const {
    // result node
    node_t* result = NULL;
    if (ele != NULL) {
      // if the child has a right subtree, the leftmost element in the right subtree
      if (ele -> right_m != NULL) {
	node_t* tmp = ele->right_m;
	node_t* tmp_left = tmp->left_m;
	while (tmp_left != NULL) {
	  tmp = tmp_left;
	  tmp_left = tmp->left_m;
	}
	result = tmp;
      } else {
	// check if it is the left child of a node
	node_t* parent = ele -> parent_m;
	if (parent != NULL) {
	  if (parent -> left_m == ele) {
	    result = parent;
	  } else {
	    while (parent != NULL && (parent -> right_m == ele)) {
	      ele = parent;
	      parent = parent -> parent_m;
	    }
	    result = parent;
	  }
	}
      }
    }
    return result;
  }


  // here is the find function
  pair<node_t*, bool> _find(const Key& x) const {
    node_t* curr_parent = NULL;
    node_t* curr = root_m;
    pair<node_t*, bool> result = make_pair(curr,false);
    while (curr != NULL) {
      curr_parent = curr;
      if (x < curr->value_m.first) {
	curr = curr->left_m;
      } else if (x > curr->value_m.first) {
	curr = curr->right_m;
      } else {
	result.first = curr;
	result.second = true;
	return result;
      }
      result.first = curr_parent;
    }
    return result;
  }


private:
  // data member in the bstmap
  // root_m is a pointer to the root of the tree_map
  node_t* root_m;
  // size_m stands for the number of nodes in the tree
  size_type size_m;
};

#endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值