遍历二叉树是以一定的规则将二叉树中的结点排列成一个线性序列的过程。与线性表相比,二叉树的遍历存在以下问题:
(1).遍历算法复杂而费时
(2).为检索或查找二叉树中某结点在某种遍历下的前驱结点和后继结点,必须从根结点开始遍历,直到找到该结点的前驱结点和后继结点。
为此,我们引入线索二叉树的概念,线索二叉树可以简化遍历算法,提高遍历效率。
其中,
ltag
为0
时,lchild
域指向结点的左孩子,ltag
为1
时,lchild
指向结点的前驱;rtag
为0
时,rchild
域指向结点的右孩子,rtag
为1
时,rchild
域指向结点的后继。
树的存储结构常分为:
由树的定义知,除根结点之外,树中的每个结点都有唯一的双亲。根据这一特点,双亲表示法可以用一组连续的存储空间存放结点信息,即用一维数组来存储树中的各个结点。数据元素为结构体类型,其中包括结点本身信息以及指示其双亲结点在数组中的位置信息。
双亲表示法在类型定义如下:
#define MaxSize 100
typedef int ElemType;
typedef struct PtNode
{
ElemType data;
int parent;
}PtNode;
typedef struct
{
PtNode nodes[MaxSize];
int r, n;
}PTree;
孩子链表表示法存储单元的主体是一个与结点个数一样大小的一维数组,数组的每一个元素由两个域组成,一个域用来存放结点自身的数据信息,另一个用来存放指针,该指针指向由该结点孩子组成的单链表的表头。单链表的结点结构也有两个域组成,一个存放孩子结点在一维数组中的下标,另一个是指针域,指向下一个孩子。
#define MaxSize 100
typedef struct CtNode
{
int child;
CtNode* next;//指向下一个孩子结点
}CtNode;
typedef struct
{
char data;
int parent;
CtNode* firstchild;//指向第一个孩子
int r, n;
}CtBox;
class CTree
{
private:
CtBox nodes[MaxSize];
int r, n;
public:
int LocateNode(char x);//查找结点x在树中的下标
void CreateCtree(int k);//创建k个结点的树
int DegreeNode(char x);//计算结点x的度数
void InsertNode(char u, char v);//插入结点u的孩子v
};
int CTree::LocateNode(char x)
{
for (int i = 0; i < n; i++)
{
if (x == nodes[i].data)
return i;
else
return -1;
}
}
void CTree::CreateCtree(int k)
{
int i;
for (i = 0; i < k; i++)
{
cin >> nodes[i].data;
nodes[i].firstchild = NULL;
}
n = k;
r = 0;
char u, v;
int h, t;
CtNode* p;
for (i = 0; i < k; i++)
{
cin >> u;
h = LocateNode(u);
cin >> v;
while (v != '.')
{
t = LocateNode(v);
p = new CtNode;
p->child = t;
p->next = nodes[h].firstchild;
nodes[h].firstchild = p;
cin >> v;
}
}
}
int CTree::DegreeNode(char x)
{
int h = LocateNode(x);
CtNode* p = nodes[h].firstchild;
int count = 0;
while (p)
{
count++;
p = p->next;
}
return count;
}
void CTree::InsertNode(char u, char v)
{
int h = LocateNode(u);
if (h == -1)
return;
nodes[n].data = v;
nodes[n].firstchild = NULL;
n++;
CtNode* p = new CtNode;
int t = LocateNode(v);
p->child = t;
p->next = nodes[h].firstchild;
nodes[h].firstchild = p;
}
孩子兄弟表示法又称二叉链表表示法或二叉树表示法。即以二叉链表作为树的存储结构,链表中结点的两个链域分别指向结点的第一个孩子结点和下一个兄弟结点。
typedef char ElemType;
typedef struct CSNode
{
ElemType data;
CSNode* firstchild;
CSNode* nextsibling;
}CSNode;
已知一棵树以孩子兄弟表示法为其存储结构,设计一个递归算法计算树的高度。
int CSTreeHeight(CSNode* t)
{
int m, max = 0;
CSNode* p;
if (t == NULL)
return 0;
else
{
p = t->firstchild;
while (p)
{
m = CSTreeHeight(p);
if (max < m)
max = m;
p = p->nextsibling;
}
return 1 + max;
}
}
题目:递归创建一棵二叉树,中序输出二叉树序列,计算树的深度,计算度数为1的结点数,计算度数为1的结点数以及判断两棵树是否相似。
#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
typedef struct BitNode
{
char data;
BitNode* lchild;
BitNode* rchild;
}BitNode;
class BiTree
{
private:
BitNode* bt;
void Rcreate(BitNode*& t);//递归创建一棵二叉树
void InTraverse(BitNode* t);//中序输出二叉树序列
int BTNodeDepth(BitNode* t);//计算树的深度
int CountNode1(BitNode* t);//计算度数为1的结点数
int CountNode2(BitNode* t);//计算度数为1的结点数
public:
BiTree()
{
bt = NULL;
}
void RecreateBiTree();
void InTraverseBiTree();
int BTNodeDepthBiTree();
int CountNode1BiTree();
int CountNode2BiTree();
int Alike(BitNode* s, BitNode* t);//判断两棵树是否相似
BitNode*& GetRoot()
{
return bt;
}
};
void BiTree::Rcreate(BitNode*& t)
{
char ch;
cin >> ch;
if (ch == '*')
{
t = NULL;
}
else
{
t = new BitNode;//申请空间
t->data = ch;
Rcreate(t->lchild);//递归创建左子树
Rcreate(t->rchild);//递归创建右子树
}
}
void BiTree::RecreateBiTree()
{
BitNode* t;
Rcreate(t);
bt = t;
}
void BiTree::InTraverse(BitNode* t)
{
if (t)
{
InTraverse(t->lchild);
cout << t->data << " ";
InTraverse(t->rchild);
}
}
void BiTree::InTraverseBiTree()
{
BitNode* p = bt;
InTraverse(p);
}
int BiTree::BTNodeDepth(BitNode* t)
{
if (t == NULL)
{
return 0;
}
else
{
int m = 1 + BTNodeDepth(t->lchild);
int n = 1 + BTNodeDepth(t->rchild);
if (m >= n)
return m;
else
return n;
}
}
int BiTree::BTNodeDepthBiTree()
{
BitNode* p = bt;
cout<< BTNodeDepth(p);
return 1;
}
int BiTree::CountNode1(BitNode* t)
{
if (t == NULL)
return 0;
if (t->lchild == NULL && t->rchild != NULL)
return 1 + CountNode1(t->rchild);
if (t->rchild == NULL && t->lchild != NULL)
return 1 + CountNode1(t->lchild);
return CountNode1(t->lchild) + CountNode1(t->rchild);
}
int BiTree::CountNode1BiTree()
{
BitNode* p = bt;
cout << CountNode1(p);
return 1;
}
int BiTree::CountNode2(BitNode* t)
{
if (t == NULL)
return 0;
if (t->lchild != NULL && t->rchild != NULL)
return 1 + CountNode2(t->lchild) + CountNode2(t->rchild);
return CountNode2(t->lchild) + CountNode2(t->rchild);
}
int BiTree::CountNode2BiTree()
{
BitNode* p = bt;
cout << CountNode2(p);
return 1;
}
int BiTree::Alike(BitNode* s, BitNode* t)
{
if (s == NULL && t == NULL)
{
return 1;
}
else if (s == NULL || t == NULL)
{
return 0;
}
else
return Alike(s->lchild, t->lchild) && Alike(s->rchild, t->rchild);
}
int main()
{
BiTree t,t1,t2;
cout << "递归创建t: ";
t.RecreateBiTree();
cout << "中序遍历的序列为:";
t.InTraverseBiTree();
cout << endl;
cout << "树的深度为:";
t.BTNodeDepthBiTree();
cout << endl;
cout << "度为1的结点数为:";
t.CountNode1BiTree();
cout << endl;
cout << "度为2的结点数为:";
t.CountNode2BiTree();
cout << endl;
cout << "递归创建t1: ";
t1.RecreateBiTree();
cout << "递归创建t2: ";
t2.RecreateBiTree();
if (t.Alike(t1.GetRoot(), t2.GetRoot()))
cout << "t1和t2相似" << endl;
else
cout << "t1和t2不相似" << endl;
return 0;
}