自己看着书,实现的,废话不多说,上代码
转载请注明出处http://blog.csdn.net/u010632868
#include <iostream>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
using namespace std;
template <class Type>
class BinSearchTreee;
//下面是对于树节点的声明和定义
template <class Type>
class Tree_Node
{
private:
bool IsHeader; //判断是否是根节点,一棵树只有一个根节点
Type Date; //显然这是数据部分,当然根节点的数据部分,未作要求
Tree_Node* Parent; //没一个节点都一个父节点。这里的数据结构的一大特点是,根节点的父亲节点是头节点,而头节点的父亲节点是根节点
Tree_Node* Left; //左儿子,对于根节点来说,Left指向元素最小的那个节点
Tree_Node* Right; //右儿子,对于根节点来说,Right指向元素最大的那个节点
public:
Tree_Node(bool isheader = false,Type date = *(new Type),Tree_Node* parent = NULL,
Tree_Node *left = NULL,Tree_Node* right = NULL) :
IsHeader(isheader),Date(date),Parent(parent),
Left(left),Right(right) {}
Tree_Node(const Tree_Node &tmp) : IsHeader(tmp.IsHeader),Date(tmp.Date),
Parent(tmp.Parent),Left(tmp.Left),Right(tmp.Right) {}
template <class T>
friend class BinSearchTree; //把数结构定义为友元类
~Tree_Node()
{
cout<<"Destroy Node"<<endl;
}
};
template <class Type>
class BinSearchTree
{
private:
typedef Tree_Node<Type> Node; //把类型的别名写在里面。我在想如果写在外面,感觉根本没法写啊。
typedef Tree_Node<Type>* Link;//有人知道怎么给template 的量typedef吗,知道的请告诉我,我们一起交流交流
public:
class Iterator //在BinSearchTree类中嵌套定义类Iterator,主要是为更好的模仿STL的风格
{
Link link; //里面就一个Link类型,作用就不用我多说了
public:
Iterator(Link p = NULL) : link(p) {} //类的定义和初始化
Iterator(const Iterator &p);
Iterator& operator=(const Iterator &itr);
bool operator==(const Iterator &itr);
bool operator!=(const Iterator &itr);
Type& operator*();
Iterator& operator++();
Iterator& operator--(); //后置的我省略了,反正都一样
friend class BinSearchTree;
};
private:
Link Header; //指向根节点的指针,看名字很显然
size_t Size; //记录容器内有多少元素
private:
Iterator Find(const Type &item); //查询
void Prune(Link &link); //当link指向的节点至少有一个空节点时,调用介个家伙。
void DeleteLink(Link &link); //删除link指向的节点
void Destroy(Link &link); //自顶向下数据呈现扩张的状态,所以这里选择用自顶向下的递归调用销毁树节点
public:
BinSearchTree();
Iterator Insert(const Type &item); //插入Date为item的新元素
void Erase(Iterator itr); //按位置删除元素
size_t Length() {return Size;} //返回容器大小
Iterator Begin(){return Iterator(Header->Left);} //指向第一个元素
Iterator End(){return Iterator(Header);} //将根节点作为end();
~BinSearchTree(); //析构函数
};
template <class Type>
BinSearchTree<Type>::Iterator::Iterator(const Iterator &itr)
{
link = itr.link;
}
template <class Type>
class BinSearchTree<Type>::Iterator& BinSearchTree<Type>::Iterator::operator=(const Iterator &itr)
{
link = itr.link;
return *this;
}
template <class Type>
bool BinSearchTree<Type>::Iterator::operator==(const Iterator &itr)
{
return link == itr.link;
}
template <class Type>
bool BinSearchTree<Type>::Iterator::operator!=(const Iterator &itr)
{
return link != itr.link;
}
template <class Type>
Type& BinSearchTree<Type>::Iterator::operator*()
{
return link->Date;
}
template <class Type>
class BinSearchTree<Type>::Iterator& BinSearchTree<Type>::Iterator::operator++()
{
//第一先判断是否有右子数,不行就从父亲节点开始找。
if(link->Right != NULL)
{
Link child = link->Right;
while(child->Left != NULL)
{
child = child->Left;
}
link = child;
}
else //找父亲节点的关键是,当前节点为左节点
{
if(link->Parent->Left == link)
{
link = link->Parent;
}
else
{
Link parent = link->Parent;
if(parent->Parent->Parent == parent) //一个很蛋疼的特例,当当前节点刚刚好是头节点的时候,必须额外判断。
{
link = parent;
}
else
{
while(parent->Parent->Right == parent)
{
parent = parent->Parent;
}
link = parent->Parent;
}
}
}
return *this;
};
//--的思路同++,唯一的不同在最后面
template <class Type>
class BinSearchTree<Type>::Iterator& BinSearchTree<Type>::Iterator::operator--()
{
if(link->Left != NULL)
{
Link child = link->Left;
while(child->Right != NULL)
{
child = child->Right;
}
link = child;
}
else
{
if(link->Parent->Right == link)
{
link = link->Parent;
}
else
{
Link parent = link->Parent;
if(parent->Parent->Parent == parent)
{
link = parent;
}
else
{
while(parent->Parent->Left == parent)
{
parent = parent->Parent;
}
link = parent->Parent;
}
}
}
//为了实现逆序迭代器的功能原型,让--begin的结果为Right;
//不过这里我并没有做相关的函数,这里只是为了以后的补充做一个方便。
if(link->IsHeader)
{
link = link->Right;
}
return *this;
};
template <class Type>
BinSearchTree<Type>::BinSearchTree()
{
Header = new Node;
Header->IsHeader = true; //只有根节点的是true,其他的都是false;
Header->Parent = NULL;
Header->Left = Header;
Header->Right = Header;
Size = 0;
}
template <class Type>
void BinSearchTree<Type>::Destroy(Link &link)
{
if(link == NULL)
{
return ;
}
else
{
Destroy(link->Right);
Destroy(link->Left);
delete link;
}
}
template <class Type>
class BinSearchTree<Type>::Iterator BinSearchTree<Type>::Find(const Type &item)
{
Link parent = Header;
Link child = parent->Parent;
//之所以不用==符号,是为了加速。之所以为什么会更快,分析如下
//在同为能找到的时候,该操作的时间期望都是log(n),当如果没有找到
//那么用==判断的话,因为要先判断是否相等,如果不想等,判断在哪边,
//这样的话,如果没有找到,该操作的期望时间就变为2*log(n);但是
//一下这种方法,依旧是log(n);
while(child != NULL)
{
if(!(child->Date > item))
{
child = child->Left;
}
else
{
parent = child;
child = child->Right;
}
}
if(parent == Header || parent->Date > item)
{
return End();
}
else
{
return parent;
}
}
template <class Type>
class BinSearchTree<Type>::Iterator BinSearchTree<Type>::Insert(const Type &item)
{
++Size;
Link parent = Header;
Link child = Header->Parent;
if(child == NULL) //当树为空的时候。
{
Link tmp = new Node(false,item,Header,NULL,NULL);
Header->Parent = tmp;
Header->Left = tmp;
Header->Right = tmp;
return tmp;
}
else
{
while(child)
{
parent = child;
if(!(item > child->Date))
{
child = child->Left;
}
else
{
child = child->Right;
}
}
if(!(item > parent->Date))
{
parent->Left = new Node(false,item,parent,NULL,NULL);
if(Header->Left == parent) { Header->Left = parent->Left;}
return parent->Left;
}
else
{
parent->Right = new Node(false,item,parent,NULL,NULL);
if(Header->Right == parent) { Header->Right = parent->Right;}
return parent->Right;
}
}
}
template <class Type>
void BinSearchTree<Type>::Erase(Iterator itr)
{
//删除操作,分三种情况,一种是,所要删除的节点是头节点。
//除此之外,所要删除的节点没有子节点和有字节点的情况
assert(!(itr.link->IsHeader));
if(itr.link->Parent->Parent == itr.link)
{
DeleteLink(itr.link->Parent->Parent);
}
else if(itr.link->Parent->Right == itr.link)
{
DeleteLink(itr.link->Parent->Right);
}
else
{
DeleteLink(itr.link->Parent->Left);
}
}
template <class Type>
void BinSearchTree<Type>::DeleteLink(Link &link)
{//注意这里是引用,这是为什么函数Erase中,要从父亲节点那里调用指向自身节点的原因。为了直接修改父亲节点的指针
if(link->Right != NULL && link->Left != NULL)
{
Link child = link->Left;
while(child->Right != NULL)
{
child = child->Right;
}
link->Date = child->Date;
if(child == link->Left)
{
Prune(link->Left);
}
else
{
Prune(child->Parent->Right);
}
}
else
{
Prune(link);
}
}
template <class Type>
void BinSearchTree<Type>::Prune(Link &link)//这货专门用来删除至少一个子节点为空的情况
{
--Size;
Link tmp = link;
if(link->Right == NULL && link->Left == NULL)//两个都为空直接删除就好了
{
link = NULL;
delete tmp;
}
else if(link->Right != NULL)
{
link->Right->Parent = link->Parent;//因为是引用所以这里直接修改了父亲指针
link = link->Right;
if(Header->Left == tmp) //因为删除的是左边的节点,左边的节点可能是Left,所以需要做必要的判断和更新。
{
Link left = link;
while(left->Left != NULL) { left = left->Left; }
Header->Left = left;
}
delete tmp;
}
else
{
link->Left->Parent = link->Parent;
link = link->Left;
if(Header->Right == tmp) //同样因为是右边的节点,所以可以是原来的Right,所以做判断更新
{
Link right = link;
while(right->Right != NULL) { right = right->Right; }
Header->Right = right;
}
delete tmp;
}
}
template <class Type>
BinSearchTree<Type>::~BinSearchTree()
{
Destroy(Header->Parent);//递归的方式释放空间。
delete Header;
}
int main()
{
BinSearchTree<int> Coll;
int i,k;
for(i = 0;i < 10;++i)
{
k = rand()%100;
Coll.Insert(k);
}
class BinSearchTree<int>::Iterator pos;
for(pos = Coll.Begin();pos != Coll.End();++pos)
{
cout<<*pos<<' ';
}
cout<<"Size is : "<<Coll.Length()<<endl;
pos = Coll.Insert(5);
cout<<*pos<<endl;
for(pos = Coll.Begin();pos != Coll.End();++pos)
{
cout<<*pos<<' ';
}
cout<<"Size is : "<<Coll.Length()<<endl;
pos = Coll.Begin();
++pos;
++pos;
Coll.Erase(pos);
for(pos = Coll.Begin();pos != Coll.End();++pos)
{
cout<<*pos<<' ';
}
cout<<"Size is : "<<Coll.Length()<<endl;
return 0;
}