/***********************************************************************/
/* file cnt_bst.cc */
/* contains the implementation of class members of class */
/* cnt_bst. */
/***********************************************************************/
#include "cnt_bst.h"
/***********************************************************************/
/* implementation of class cnt_bst */
/***********************************************************************/
/***********************************************************************/
/* public member operator= */
/* copies all data members' contents of the passed cnt_bst */
/***********************************************************************/
template <class type>
const cnt_bst<type>& cnt_bst<type>::operator=(const cnt_bst<type>& tree)
{
this->sz= tree.sz;
if (this->head != NULL)
{
delete this->head;
}
if (tree.head)
{
this->head= new cnt_bst_item<type>(*tree.head);
}
else
{
this->head= NULL;
}
}
/***********************************************************************/
/* public member function add */
/* takes one argument of type and inserts an item to the bst */
/* if it doesn't already exist. Otherwise the count of the existing */
/* item is increased. It returns a pointer to the added bst_item. */
/***********************************************************************/
template <class type>
cnt_bst_item<type> *cnt_bst<type>::add(const type& dat)
{
return cnt_add(dat, 1);
}
/***********************************************************************/
/* public member function cnt_add */
/* works like add (in doubleity it's vice versa ...) but takes an */
/* argument of int which denotes the count for the added item (or the */
/* increase of count if it already existed in the tree). */
/* As is easy to see add(dat) is simply cnt_add(dat,1). */
/***********************************************************************/
template <class type>
cnt_bst_item<type> *cnt_bst<type>::cnt_add(const type& dat, int cnt)
{
cnt_bst_item<type>* cnt_it= NULL;
if (this->head != NULL)
{
bst_item<type> *parent= parent_search(dat);
if (parent)
{
bst_item<type> *it= child(parent, dat);
if (it)
{
cnt_it= (cnt_bst_item<type> *) it;
cnt_it->count+= cnt;
}
else
{
cnt_it= new cnt_bst_item<type>(dat, cnt);
add_item(parent, cnt_it);
}
}
else
{
cnt_it= (cnt_bst_item<type> *) this->head;
cnt_it->count+= cnt;
}
}
else
{
cnt_it= new cnt_bst_item<type>(dat, cnt);
add_item(this->head, cnt_it);
}
return cnt_it;
}
/***********************************************************************/
/* public member function search */
/* takes an argument of type and returns a pointer to the node where */
/* the first argument was found containing the passed argument as */
/* data, NULL if it wasn't found. type must supply == < > operators. */
/***********************************************************************/
template <class type>
cnt_bst_item<type> *cnt_bst<type>::search(const type& dat)
{
if (this->head->data == dat)
{
return (cnt_bst_item<type> *) this->head;
}
cnt_bst_item<type> *it= NULL;
bst_item<type> *parent= parent_search(dat);
if (parent)
{
it= (cnt_bst_item<type> *) child(parent, dat);
}
return it;
}
/***********************************************************************/
/* protected member function del_item */
/* workhorse for del, deletes an item */
/* overloads the according function of base_bst */
/***********************************************************************/
template <class type>
void cnt_bst<type>::del_item(bst_item<type> *parent,
bst_item<type> *it)
{
assert(it != NULL);
if (it->left)
{
bst_item<type> *old_it= it;
bst_item<type> *next_it= it->left;
while(next_it->right)
{
old_it= next_it;
next_it= next_it->right;
}
it->data= next_it->data;
((cnt_bst_item<type> *) it)->count=
((cnt_bst_item<type> *) next_it)->count;
del_item(old_it, next_it);
}
else
{
if (it->right)
{
bst_item<type> *old_it= it;
bst_item<type> *next_it= it->right;
while(next_it->left)
{
old_it= next_it;
next_it= next_it->left;
}
it->data= next_it->data;
((cnt_bst_item<type> *) it)->count=
((cnt_bst_item<type> *) next_it)->count;
del_item(old_it, next_it);
}
else
{
if (parent)
{
if (it == parent->left)
{
parent->left= NULL;
}
else
{
parent->right= NULL;
}
}
if (it == this->head)
{
this->head= NULL;
}
delete it;
this->sz--;
}
}
}
/***********************************************************************/
/* public member function del */
/* takes a argument of type and deletes the node containing identical */
/* data to the passed argument. It returns 1 if anything was deleted, */
/* 0 otherwise. type must supply == < > operators. */
/***********************************************************************/
template <class type>
int cnt_bst<type>::del(const type& dat, int cnt)
{
if (this->head != NULL)
{
bst_item<type> *parent= parent_search(dat);
if (parent)
{
bst_item<type> *it= child(parent,dat);
if (it)
{
int new_cnt= ((cnt_bst_item<type> *) it)->count - cnt;
if (new_cnt < 1)
{
del_item(parent, it);
}
else
{
((cnt_bst_item<type> *) it)->count= new_cnt;
}
return 1;
}
}
else
{
bst_item<type>* it= this->head;
int new_cnt= ((cnt_bst_item<type> *) it)->count - cnt;
if (new_cnt < 1)
{
del_item(parent, it);
}
else
{
((cnt_bst_item<type> *) it)->count= new_cnt;
}
return 1;
}
}
return 0;
}
/***********************************************************************/
/* public member function count */
/* takes one argument of type and returns the count it has in the */
/* cnt_bst, 0 if it isn't in the cnt_bst. */
/***********************************************************************/
template <class type>
int cnt_bst<type>::count(const type &dat)
{
cnt_bst_item<type> *it= search(dat);
if (it)
{
return it->count;
}
else
{
return 0;
}
}
/***********************************************************************/
/* public member function iterator() */
/* returns a pointer to a freshly created iterator for the cnt_bst. */
/* The Iterator must be deleted by the calling function or it will */
/* continue to exist as garbage indefinitely. */
/***********************************************************************/
template <class type>
cnt_bst_iterator<type> *cnt_bst<type>::iterator()
{
return (new cnt_bst_iterator<type>(this));
}