目录
我们事先定义如果树结点的数据域为‘#’时,则这个结点为叶子节点,没有左右孩子,当然也可以直接把这个结点定义为NULL。
如果对树中进行增加或删除结点的操作,需要对函数形参中的树名用引用的方式传入,因为形参在函数调用结束后编译器会自动对形参释放空间,即使用指针进行传入,释放后也会对原树增加或删除结点的操作无效。
1、树的类型定义
typedef struct tree
{
char date;
struct tree* lchild;
struct tree* rchild;
}*pnode,node;
2、创建二叉树
//创建二叉树
int creattree(pnode &tree, string s,unsigned int n)
{
char c = s[n];
n = n + 1;
if (c != '\0')
{
if (c == '#')
{
tree = new node;
tree->date = '#';
tree->lchild = NULL;
tree->rchild = NULL;
}
else
{
tree = new node;
tree->date = c;
n = creattree(tree->lchild, s, n);
n = creattree(tree->rchild, s, n);
}
}
return n;
}
3、三种遍历方式
①、先序遍历
//先序输出
void preorder(pnode tree)
{
if (tree->date != '#')
{
cout << tree->date;
preorder(tree->lchild);
preorder(tree->rchild);
}
}
②、中序遍历
//中序输出
void inorder(pnode tree)
{
if (tree->date != '#')
{
inorder(tree->lchild);
cout << tree->date;
inorder(tree->rchild);
}
}
③、后序遍历
//后序输出
void postorder(pnode tree)
{
if (tree->date != '#')
{
postorder(tree->lchild);
postorder(tree->rchild);
cout << tree->date;
}
}
④、层次遍历
void leveloutput(pnode tree)
{
queue<pnode>q;
if (tree->date != '#')
{
q.push(tree);
}
while (!q.empty())
{
cout << q.front()->date;
q.pop();
if (tree->lchild->date != '#')
{
q.push(tree->lchild);
}
if (tree->rchild->date != '#')
{
q.push(tree->rchild);
}
if (!q.empty())
{
tree = q.front();
}
}
}
4、二叉树的复制
//复制二叉树
void copytree(pnode &tree, pnode &newtree)
{
if (tree == NULL)
{
newtree = NULL;
}
else
{
newtree = new node;
newtree->date = tree->date;
copytree(tree->lchild, newtree->lchild);
copytree(tree->rchild, newtree->rchild);
}
}
5、计算树的深度
//计算树的深度
int depth(pnode tree)
{
int ld = 0, rd;
if (tree->date == '#')
{
return 0;
}
else
{
ld = depth(tree->lchild);
rd = depth(tree->rchild);
return (ld > rd ? ld : rd) + 1;
}
}
6、统计结点个数
①、统计结点总数
//统计树的结点个数
int nodenum(pnode tree)
{
if (tree->date == '#')
{
return 0;
}
else
{
return nodenum(tree->lchild) + nodenum(tree->rchild) + 1;
}
}
②、统计叶子节点个数
//统计叶子节点个数
int nodenum0(pnode tree)
{
int count;
if (tree->date == '#')
{
count = 0;
}
else
{
if (tree->lchild->date == '#'&&tree->rchild->date == '#')
{
count = 1;
}
else
{
count = nodenum0(tree->lchild) + nodenum0(tree->rchild);
}
}
return count;
}
③、统计度数为1的结点个数
//统计度数为1的结点个数
int nodenum1(pnode tree)
{
int count;
if (tree->date == '#')
{
count = 0;
}
else
{
if ((tree->lchild->date == '#'&&tree->rchild->date != '#')
|| (tree->lchild->date != '#'&&tree->rchild->date == '#'))
{
count = 1;
}
else
{
count = nodenum1(tree->lchild) + nodenum1(tree->rchild);
}
}
return count;
}
④ 、统计度数为2的结点个数
//统计度数为2的结点个数
int nodenum2(pnode &tree)
{
int count;
if (tree->date == '#')
{
count = 0;
}
else
{
if (tree->lchild->date != '#'&&tree->rchild->date != '#')
{
count = 1;
}
else
{
count = nodenum1(tree->lchild) + nodenum1(tree->rchild);
}
}
return count;
}
7、树的反转
//反转树
void rotation(pnode tree, pnode &newtree)
{
if (tree->date == '#')
{
newtree = new node;
newtree->date = '#';
newtree->lchild = NULL;
newtree->rchild = NULL;
}
else
{
newtree = new node;
newtree->date = tree->date;
rotation(tree->lchild, newtree->rchild);
rotation(tree->rchild, newtree->lchild);
}
}
8、主函数的测试代码段
int main()
{
//ab#f##gc###
pnode ptree1 = NULL, ptree2 = NULL, ptree3 = NULL;
string s;
cout << "请输入字符串:";
cin >> s;
if (s.size() == creattree(ptree1, s, 0))
{
cout << "二叉树建立成功!" << endl;
}
cout << "先序遍历:";
preorder(ptree1);
cout << "\n中序遍历:";
inorder(ptree1);
cout << "\n后序遍历:";
postorder(ptree1);
cout << "\n层次遍历:";
leveloutput(ptree1);
cout << "\n树的深度:" << depth(ptree1) << endl;
cout << "树的结点个数:" << nodenum(ptree1) << endl;
cout << "树的叶子结点个数:" << nodenum0(ptree1) << endl;
cout << "树的度为1的结点个数:" << nodenum1(ptree1) << endl;
cout << "树的度为2的结点个数:" << nodenum2(ptree1) << endl;
}
9、效果图