一、二叉树的特点:
1. 每个节点都有唯一的父节点;
2. 每个节点最多只有两个子节点,分别为左孩子和右孩子;
二、链式的建立:
1. 根据特点有:
图 2-1 二叉树节点
2. 定义节点类:
template<typename Type>
class BinTreeNode
{
private:
Type data;
BinTreeNode<Type> *leftchild;
BinTreeNode<Type> *rightchild;
FLAG_TYPE ltag;
FLAG_TYPE rtag;
};
3.定义二叉树类:
template<typename Type>
class BinTree
{
private:
BinTreeNode<Type> *root;
Type StopFlag;
};
三、二叉树的线索化:
添加相应的成员,将节点修改为可以添加线索的类型
typedef enum{LINK, THREAD }FLAG_TYPE;
template<typename Type>
class BinTreeNode
{
friend class BinTree<Type>;
public:
BinTreeNode() :data(Type()), leftchild(NULL), rightchild(NULL), ltag(LINK), rtag(LINK)
{}
BinTreeNode(Type d, BinTreeNode<Type> *l = NULL, BinTreeNode<Type> *r = NULL):
data(d), leftchild(l), rightchild(r), ltag(LINK), rtag(LINK)
{}
~BinTreeNode()
{}
private:
Type data;
BinTreeNode<Type> *leftchild;
BinTreeNode<Type> *rightchild;
FLAG_TYPE ltag;
FLAG_TYPE rtag;
};
四、完整源代码:
BinTree.h
#ifndef _BINTREE_H
#define _BINTREE_H
#include<iostream>
#include<string>
using namespace std;
template<typename Type>
class Queue //实现用于层次遍历需要的功能,也可以#include<queue>
{ //以前有写C语言语法的线性结构,和C++一起用感觉怪怪的所以写了个够用的
public:
Queue(int sz = 50) :m_ncurrentsize(0), m_nmaxsize(sz)
{
if (sz > 0)
{
m_data = new Type[m_nmaxsize];
}
}
~Queue()
{
delete[]m_data;
}
public:
void Push(Type x)
{
m_ncurrentsize++;
for (int j = m_ncurrentsize; j > 0; --j)
{
m_data[j] = m_data[j - 1];
}
m_data[0] = x;
}
void Pop()
{
m_ncurrentsize--;
}
Type Get()
{
return m_data[m_ncurrentsize - 1];
}
bool IsEmpty()
{
return m_ncurrentsize == 0;
}
private:
Type *m_data;
const int m_nmaxsize;
int m_ncurrentsize;
};
template<typename Type>
class BinTree;
//typedef一个枚举类型,表示线索的形式
typedef enum{LINK, THREAD }FLAG_TYPE;
template<typename Type>
class BinTreeNode
{
friend class BinTree<Type>;
public:
BinTreeNode() :data(Type()), leftchild(NULL), rightchild(NULL), ltag(LINK), rtag(LINK)
{}
BinTreeNode(Type d, BinTreeNode<Type> *l = NULL, BinTreeNode<Type> *r = NULL):
data(d), leftchild(l), rightchild(r), ltag(LINK), rtag(LINK)
{}
~BinTreeNode()
{}
private:
Type data;
BinTreeNode<Type> *leftchild;
BinTreeNode<Type> *rightchild;
FLAG_TYPE ltag;
FLAG_TYPE rtag;
};
typedef enum{ NOTH, PRIO, MID, POST }THREAD_TYPE;
template<typename Type>
class BinTree
{
public:
BinTree() :root(NULL)
{}
BinTree(Type ref) :StopFlag(ref)
{}
BinTree(BinTree<Type> &t)//构造结果为无线索二叉树
{
root = Copy(t.root);
StopFlag = t.StopFlag;
}
BinTree& operator=(BinTree<Type> &t)//赋值结果为无线索二叉树
{
if (this == &t)
return *this;
Destory(root);
root = Copy(t.root);
StopFlag = t.StopFlag;
return *this;
}
~BinTree()
{
Destory(root);
}
public:
int Depth()const
{
return Depth(root);
}
void CreateBinTree()
{
Destory(root);
CreateBinTree(root);
}
void CreateBinTree(const char *str)
{
Destory(root);
CreateBinTree(root,str);
}
//尽量使用好的函数名代替注释
void CreateBy_VLR_LVR(const char*svlr,const char *slvr, int n)
{
Destory(root);
CreateBy_VLR_LVR(root, svlr, slvr, n);
}
void CreateBy_LVR_LRV(const char*slvr, const char *slrv, int n)
{
Destory(root);
CreateBy_LVR_LRV(root, slvr, slrv, n);
}
void CreateInPrioThread()
{
BinTreeNode<Type> *pre = NULL;
CreateInPrioThread(root, pre);
ttype = PRIO;
}
void CreateInMidThread()
{
BinTreeNode<Type> *pre = NULL;
CreateInMidThread(root, pre);
pre->rtag = THREAD;
pre->rightchild = NULL;
ttype = MID;
}
void CreateInPostThread()
{
BinTreeNode<Type> *pre = NULL;
CreateInPostThread(root, pre);
pre->ltag = THREAD;
pre->leftchild = NULL;
ttype = POST;
}
void ClearThread()
{
ClearThread(root);
ttype = NOTH;
}
void PreOrder()const
{
PreOrder(root);
}
void InOrder()const
{
InOrder(root);
}
void PostOrder()const
{
PostOrder(root);
}
void LevelOrder()const
{
LevelOrder(root);
}
BinTreeNode<Type> *FirstAsInMidThread()const
{
return FirstAsInMidThread(root);
}
BinTreeNode<Type> *LastAsInMidThread()const
{
return LastAsInMidThread(root);
}
BinTreeNode<Type> *ParentAsInMidThread(BinTreeNode<Type> *cur)const
{
return ParentAsInMidThread(root, cur);
}
BinTreeNode<Type> *ParentAsInMidThread(Type x)const
{
return ParentAsInMidThread(root, FindAsInMidThread(x));
}
BinTreeNode<Type> *FindAsInMidThread(Type x)const
{
return FindAsInMidThread(root, x);
}
BinTreeNode<Type> *prioAsInMidThread(BinTreeNode<Type> *cur)const;
BinTreeNode<Type> *NextAsInMidThread(BinTreeNode<Type> *cur)const;
private:
//如果要求下一个函数参数与上一个函数的调用有关,加指针的引用真实太有必要了
void CreateBinTree(BinTreeNode<Type> *&t, const char *&str);
void CreateBinTree(BinTreeNode<Type> *&t);
void CreateBy_VLR_LVR(BinTreeNode<Type> *&t, const char* svlr, const char* slvr, int n);
void CreateBy_LVR_LRV(BinTreeNode<Type> *&t, const char* slvr, const char* slrv, int n);
int Depth(BinTreeNode<Type> *t)const;
void PreOrder(BinTreeNode<Type> *t)const;
void InOrder(BinTreeNode<Type> *t)const;
void PostOrder(BinTreeNode<Type> *t)const;
void LevelOrder(BinTreeNode<Type> *t)const;
void Destory(BinTreeNode<Type> *t);
BinTreeNode<Type> * Copy(BinTreeNode<Type> *t);
void CreateInPrioThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre);
void CreateInMidThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre);
void CreateInPostThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre);
void ClearThread(BinTreeNode<Type> *t);
BinTreeNode<Type> *FirstAsInMidThread(BinTreeNode<Type> *t)const;
BinTreeNode<Type> *LastAsInMidThread(BinTreeNode<Type> *t)const;
BinTreeNode<Type> *FindAsInMidThread(BinTreeNode<Type> *t, Type &x)const;
BinTreeNode<Type> *ParentAsInMidThread(BinTreeNode<Type> *root, BinTreeNode<Type> *t)const;
private:
BinTreeNode<Type> *root;
Type StopFlag;
THREAD_TYPE ttype;
};
template <typename Type>
void BinTree<Type>::ClearThread(BinTreeNode<Type> *t)
{
if (t != NULL)
{
if (t->ltag != THREAD)
ClearThread(t->leftchild);
else
{
t->ltag = LINK;
t->leftchild = NULL;
}
if (t->rtag != THREAD)
ClearThread(t->rightchild);
else
{
t->rtag = LINK;
t->rightchild = NULL;
}
}
}
template <typename Type>
BinTreeNode<Type> * BinTree<Type>::ParentAsInMidThread(BinTreeNode<Type> *root, BinTreeNode<Type> *t)const
{
if (root == NULL || t == NULL || t == root)
return NULL;
BinTreeNode<Type> *p = t;
for (; p->ltag != THREAD;)
p = p->leftchild;
p = p->leftchild;
if ((p != NULL)&&(p->leftchild == t || p->rightchild == t))
return p;
p = t;
for (; p->rtag != THREAD;)
p = p->rightchild;
return p->rightchild;
}
template <typename Type>
BinTreeNode<Type> * BinTree<Type>::FindAsInMidThread(BinTreeNode<Type> *t, Type &x)const
{
if (t == NULL)
return NULL;
BinTreeNode<Type> *p = NULL;
if (t->data == x)
return t;
else
{
if (t->ltag != THREAD)
p = FindAsInMidThread(t->leftchild,x);
if (p == NULL && t->rtag != THREAD)
p = FindAsInMidThread(t->rightchild,x);
return p;
}
}
template <typename Type>
BinTreeNode<Type> * BinTree<Type>::NextAsInMidThread(BinTreeNode<Type> *cur)const
{
if (cur == NULL)
return NULL;
if (cur->rtag == THREAD)
return cur->rightchild;
else
return FirstAsInMidThread(cur->rightchild);
}
template <typename Type>
BinTreeNode<Type> * BinTree<Type>::FirstAsInMidThread(BinTreeNode<Type> *t)const
{
if (t == NULL)
return NULL;
//中序线索第一个元素必为左子树的最左子节点
while (t->ltag != THREAD)
{
t = t->leftchild;
}
return t;
}
template <typename Type>
BinTreeNode<Type> * BinTree<Type>::LastAsInMidThread(BinTreeNode<Type> *t)const
{
if (t == NULL)
return NULL;
//中序线索最后一个元素必为右子树的最右子节点
while (t->rtag != THREAD)
{
t = t->rightchild;
}
return t;
}
template <typename Type>
BinTreeNode<Type> *BinTree<Type>::prioAsInMidThread(BinTreeNode<Type> *cur)const
{
if (cur == NULL)
return NULL;
if (cur->ltag == THREAD)
return cur->leftchild;
else
return LastAsInMidThread(cur->leftchild);
}
template <typename Type>
void BinTree<Type>::CreateInPrioThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre)
{
if (cur == NULL)
return;
if (cur->leftchild == NULL)
{
cur->ltag = THREAD;
cur->leftchild = pre;
}
if (pre!= NULL && pre->rightchild == NULL)
{
pre->rtag = THREAD;
pre->rightchild = cur;
}
pre = cur;
if (cur->ltag == LINK)
CreateInPrioThread(cur->leftchild, pre);
if (cur->rtag == LINK)
CreateInPrioThread(cur->rightchild, pre);
}
template <typename Type>
void BinTree<Type>::CreateInPostThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre)
{
if (cur == NULL)
return;
CreateInPostThread(cur->rightchild, pre);//初始方向为右
if (cur->rightchild == NULL)
{
cur->rtag = THREAD;
cur-> rightchild= pre;
}
if (pre != NULL && pre-> leftchild== NULL)
{
pre->ltag = THREAD;
pre->leftchild = cur;
}
pre = cur;
CreateInPostThread(cur->leftchild, pre);
}
template <typename Type>
void BinTree<Type>::CreateInMidThread(BinTreeNode<Type> *cur, BinTreeNode<Type> *&pre)
{
if (cur == NULL)
return;
CreateInMidThread(cur->leftchild, pre);//初始方向为左
if (cur->leftchild == NULL)
{
cur->ltag = THREAD;
cur->leftchild = pre;
}
if (pre != NULL && pre->rightchild == NULL)
{
pre->rtag = THREAD;
pre->rightchild = cur;
}
pre = cur;
CreateInMidThread(cur->rightchild, pre);
}
template <typename Type>
void BinTree<Type>::CreateBy_LVR_LRV(BinTreeNode<Type> *&t, const char* slvr, const char* slrv, int n)
{
if (n == 0)
return;
int i = 0;
while (slrv[n - 1] != slvr[i])
{
++i;
}
//char *lvr = "CBEDF A GH"
//char *lrv = "CEFDB HG A";
t = new BinTreeNode<Type>(slvr[i]);
CreateBy_LVR_LRV(t->rightchild, slvr + i + 1, slrv + i, n - i - 1);
CreateBy_LVR_LRV(t->leftchild, slvr, slrv, i);
}
template <typename Type>
void BinTree<Type>::CreateBy_VLR_LVR(BinTreeNode<Type> *&t,const char* svlr,const char* slvr,int n)
{
if (n == 0)
return;
int i = 0;
while (svlr[0] != slvr[i])
{
++i;
}
//char *vlr = "ABCDEFGH";
//char *lvr = "CBEDFAGH";
t = new BinTreeNode<Type>(slvr[i]);
CreateBy_VLR_LVR(t->leftchild, svlr + 1, slvr, i);
CreateBy_VLR_LVR(t->rightchild, svlr + i + 1, slvr + i + 1, n - i - 1);
}
template <typename Type>
BinTreeNode<Type> * BinTree<Type>::Copy(BinTreeNode<Type> *t)
{
if (t == NULL)
return NULL;
BinTreeNode<Type> *p = new BinTreeNode<Type>;
p->data = t->data;
if (t->ltag != THREAD)
p->leftchild = Copy(t->leftchild);
else
p->leftchild = NULL;
if (t->rtag != THREAD)
p->rightchild = Copy(t->rightchild);
else
p->rightchild = NULL;
return p;
}
template <typename Type>
void BinTree<Type>::Destory(BinTreeNode<Type> *t)
{
if (t == NULL)
return;
if (t->ltag != THREAD)
Destory(t->leftchild);
if (t->rtag != THREAD)
Destory(t->rightchild);
delete t;
}
template <typename Type>
void BinTree<Type>::PreOrder(BinTreeNode<Type> *t)const
{
if (t != NULL )
{
cout << t->data;
//添加遍历线索后需要添加判断语句来结束递归
if(t->ltag != THREAD)
PreOrder(t->leftchild);
if (t->rtag != THREAD)
PreOrder(t->rightchild);
}
}
template <typename Type>
void BinTree<Type>::CreateBinTree(BinTreeNode<Type> *&t, const char *&str)
{
char ch = str[0];
str++;
if (ch == StopFlag)
{
t = NULL;
}
else
{
t = new BinTreeNode<Type>(ch);
CreateBinTree(t->leftchild, str);
CreateBinTree(t->rightchild, str);
}
}
template <typename Type>
void BinTree<Type>::CreateBinTree(BinTreeNode<Type> *&t)
{
Type item;
cin >> item;
if (item == StopFlag)
t = NULL;
else
{
t = new BinTreeNode<Type>(item);
CreateBinTree(t->leftchild);
CreateBinTree(t->rightchild);
}
}
template <typename Type>
int BinTree<Type>::Depth(BinTreeNode<Type> *t)const
{
int dleft, dright, max;
if (t == NULL)
return 0;
else
{
dleft = Depth(t->leftchild);
dright = Depth(t->rightchild);
max = dleft > dright ? dleft : dright;
return max + 1;
}
}
template <typename Type>
void BinTree<Type>::InOrder(BinTreeNode<Type> *t)const
{
if (t != NULL)
{
if (t->ltag != THREAD)
InOrder(t->leftchild);
cout << t->data;
if (t->rtag != THREAD)
InOrder(t->rightchild);
}
}
template <typename Type>
void BinTree<Type>::PostOrder(BinTreeNode<Type> *t)const
{
if (t != NULL)
{
if (t->ltag != THREAD)
PostOrder(t->leftchild);
if (t->rtag != THREAD)
PostOrder(t->rightchild);
cout << t->data;
}
}
template <typename Type>
void BinTree<Type>::LevelOrder(BinTreeNode<Type> *t)const
{
Queue<BinTreeNode<Type>*> Que;
Que.Push(t);
BinTreeNode<Type>* s = NULL;
while (!Que.IsEmpty())
{
s = Que.Get();
cout << s->data;
if (s->leftchild != NULL && s->ltag != THREAD)//要出它,便先入它的孩子
Que.Push(s->leftchild);
if (s->rightchild != NULL && s->rtag != THREAD)
Que.Push(s->rightchild);
Que.Pop();
}
}
#endif
Test.cpp
#include"BinTree.h"
int main(int argc, char *argv[])
{
char *ch = "ABC##DE##F##G#H##";
BinTree<char> bin('#');
bin.CreateBinTree(ch);
bin.PreOrder();
cout << endl;
bin.InOrder();
cout << endl;
bin.PostOrder();
cout << endl;
bin.LevelOrder();
cout << endl;
cout << bin.Depth() << endl;
//为bin添加中序线索
bin.CreateInMidThread();
//在中序中做一些查找操作
BinTreeNode<char> *p1 = bin.FirstAsInMidThread();
BinTreeNode<char> *p2 = bin.NextAsInMidThread(p1);
BinTreeNode<char> *q1 = bin.LastAsInMidThread();
BinTreeNode<char> *q2 = bin.prioAsInMidThread(q1);
BinTreeNode<char> *pp = bin.FindAsInMidThread('H');
BinTreeNode<char> *ppp = bin.ParentAsInMidThread(pp);
BinTreeNode<char> *pppp = bin.ParentAsInMidThread('H');
//修改后的遍历函数可以适应各种情况
bin.PreOrder();
cout << endl;
bin.InOrder();
cout << endl;
bin.PostOrder();
cout << endl;
bin.LevelOrder();
cout << endl;
bin.ClearThread();
char *vlr = "ABCDEFGH";
char *lvr = "CBEDFAGH";
char *lrv = "CEFDBHGA";
BinTree<char> bin2('#');
bin2.CreateBy_VLR_LVR(vlr, lvr, strlen(lvr));
bin2.CreateInPrioThread();
BinTree<char> bin3(bin2);
bin3.CreateBy_LVR_LRV(lvr, lrv, strlen(lvr));
bin3.CreateInPostThread();
system("pause");
return 0;
}
五、运行及测试结果:
图 5-1 添加中序线索的树示例