先看几条定义:
1、二叉树是一种每个结点最多只能有两个孩子的树。
2、每一个子集本身又是一棵符合定义的树,叫做根节点的子树。
3、每一棵子树的根叫做根 r 的孩子,而 r 是每一棵子树的根的双亲。
4、具有相同双亲的结点称为兄弟。
5、树中结点所在的最大层次称为树的深度(或高度)。
6、树的访问顺序一般有先序、中序、后序、层次四种。
先序:根结点->左子树->右子树
中序:左子树->根结点->右子树
后序:左子树->右子树->根结点
层次:逐层访问,从左到右
这里我采用的是先序创建。用来测试程序的二叉树为ABD#G###CE##F##,后续插入操作插入的二叉树为HJK####(基于先序顺序)。如图所示:
基本数据结构:
typedef struct BiTNode {
char data; //数据
struct BiTNode* lchild; //左孩子
struct BiTNode* rchild; //右孩子
}BiTNode, * BiTree;
1、初始化
void Init_Tree(BiTree& T) //1、初始化
{
T = (BiTNode*)malloc(sizeof(BiTNode));
T->data = '#';
T->lchild = NULL;
T->rchild = NULL;
}
2、销毁(基于后序顺序)
void Destroy_Tree(BiTree& T) //2、销毁(基于后序顺序)
{
if (T) {
Destroy_Tree(T->lchild); //销毁左子树
Destroy_Tree(T->rchild); //销毁右子树
free(T); //释放结点
}
}
3、创建(基于先序顺序)
void Create_Tree(BiTree& T) //3、创建(基于先序顺序)
{
char c;
cin >> c;
if (c == '#') { // # 代表空指针
T = NULL;
}
else { //创建根节点
T = (BiTNode*)malloc(sizeof(BiTNode));
T->data = c;
Create_Tree(T->lchild); //先序创建左分支
Create_Tree(T->rchild); //先序创建右分支
}
}
4、清空(释放根之外的空间)
void Clear_Tree(BiTree& T) //4、清空(释放根之外的空间)
{
Destroy_Tree(T->lchild); //销毁T的左子树
Destroy_Tree(T->rchild); //销毁T的右子树
T = NULL;
}
5、判段是否为空
bool Empty_Tree(BiTree T) //5、判空
{
if (T == NULL || T->data == '#') {
return true;
}
else {
return false;
}
}
6、求深度
int Depth_Tree(BiTree T) //6、返回深度
{
int leftdepth, rightdepth;
if (T == NULL) {
return 0; //到空时,返回0
}
else {
leftdepth = Depth_Tree(T->lchild); //求左子树深度
rightdepth = Depth_Tree(T->rchild); //求右子树深度
return max(leftdepth + 1, rightdepth + 1); //最终取较大深度
}
}
7、返回根的元素值
8、返回p指针指向的结点值
char Root_Tree(BiTree T) //7、返回根的元素值
{
if (T != NULL) { //树不为空
return T->data;
}
else {
return '#';
}
}
char Value_Tree(BiTree T, BiTree p) //8、返回p指针指向的结点值
{
if (T == NULL || p == NULL) {
return '#';
}
else {
return p->data;
}
}
9、若p非T的根节点,则返回其双亲指针,否则返回NULL
10、返回p的左孩子指针,若没有返回NULL
11、返回p的右孩子指针,若没有返回NULL
12、返回p的左兄弟指针,若没有返回NULL
13、返回p的右兄弟指针,若没有返回NULL
BiTree Parent_Tree(BiTree T, BiTree p) //9、若p非T的根节点,则返回其双亲指针,否则返回NULL
{
BiTree q = NULL;
if (T == NULL || p == T) { //如果p等于根节点,返回NULL
return NULL;
}
else {
if (T->lchild == p || T->rchild == p) { //T是p的双亲,返回T
return T;
}
q = Parent_Tree(T->lchild, p); //在左分支中查找
if (q == NULL) { //左分支中没有找到,查找右分支
q = Parent_Tree(T->rchild, p);
return q;
}
return q;
}
}
BiTree LeftChild_Tree(BiTree T, BiTree p) //10、返回p的左孩子指针,若没有返回NULL
{
if (T != NULL && p != NULL) {
return p->lchild;
}
else {
return NULL;
}
}
BiTree RightChild_Tree(BiTree T, BiTree p) //11、返回p的右孩子指针,若没有返回NULL
{
if (T != NULL && p != NULL) {
return p->rchild;
}
else {
return NULL;
}
}
BiTree LeftBrother_Tree(BiTree T, BiTree p) //12、返回p的左兄弟指针,若没有返回NULL
{
if (T == NULL) {
return NULL;
}
else {
BiTree q = Parent_Tree(T, p); //先找到双亲结点
if (q != NULL && q->lchild != p) {
return q->lchild;
}
else {
return NULL;
}
}
}
BiTree RightBrother_Tree(BiTree T, BiTree p) //13、返回p的右兄弟指针,若没有返回NULL
{
if (T == NULL) {
return NULL;
}
else {
BiTree q = Parent_Tree(T, p);
if (q != NULL && q->rchild != p) {
return q->rchild;
}
else {
return NULL;
}
}
}
14、先序遍历并打印
15、中序遍历并打印
16、后序遍历并打印
void PrePrint_Tree(BiTree T) //14、先序遍历并打印
{
if (T != NULL) {
cout << T->data; //访问根节点
PrePrint_Tree(T->lchild); //先序遍历左子树
PrePrint_Tree(T->rchild); //先序遍历右子树
}
}
void InPrint_Tree(BiTree T) //15、中序遍历并打印
{
if (T != NULL) {
InPrint_Tree(T->lchild); //中序遍历左子树
cout << T->data; //访问根节点
InPrint_Tree(T->rchild); //中序遍历右子树
}
}
void PostPrint_Tree(BiTree T) //16、后序遍历并打印
{
if (T != NULL) {
PostPrint_Tree(T->lchild); //后序遍历左子树
PostPrint_Tree(T->rchild); //后序遍历右子树
cout << T->data; //访问根节点
}
}
17、层次遍历并打印
void LevelPrint_Tree(BiTree T) //17、层次遍历并打印
{
BiTree p;
queuequ; //定义队列,存放二叉树结点指针(这里使用了STL的queue类型)
qu.push(T); //根节点入队
while (!qu.empty()) {
p = qu.front();
cout << p->data; //访问队首结点
qu.pop(); //队首结点出队
if (p->lchild != NULL) {
qu.push(p->lchild); //若结点有左孩子,则左孩子入队
}
if (p->rchild != NULL) {
qu.push(p->rchild); //若结点有右孩子,则左孩子入队
}
}
}
18、将p结点元素赋值为c
19、插入(插入的为非空二叉树,且右子树为空)
void Assign_Tree(BiTree& T, BiTree p, char c) //18、将p结点元素赋值为c
{
if (T == NULL || p == NULL) {
return;
}
else {
p->data = c;
}
}
void Insert_Tree(BiTree& T, BiTree p, int LR, BiTree c) //19、插入(c为非空二叉树,且右子树为空)
{
if (T == NULL || p == NULL || c == NULL) {
return;
}
else {
if (LR == 0) { //LR为0,则c作为p的左子树;为1,则c作为p的右子树
c->rchild = p->lchild; //把原来的左子树连接在c的右子树上
p->lchild = c;
}
else {
c->rchild = p->rchild; //把原来的右子树连接在c的右子树上
p->rchild = c;
}
}
}
20、删除子树
void Delete_Tree(BiTree& T, BiTree p, int LR) //20、删除子树
{
if (T == NULL || p == NULL) {
return;
}
if (LR == 0) { //删除p的左子树
Destroy_Tree(p->lchild);
p->lchild = NULL;
}
else { //删除p的右子树
Destroy_Tree(p->rchild);
p->rchild = NULL;
}
}
21、先序查找指定元素值的结点
BiTree Find_Tree(BiTree T, char c) //21、先序查找指定元素值的二叉树结点
{
BiTree p = NULL;
if (T == NULL) {
return NULL;
}
else if (T->data == c) { //访问的当前结点值等于c,返回当前指针,查找结束
return T;
}
else {
p = Find_Tree(T->lchild, c); //在左分支中先序查找
if (p == NULL) {
p = Find_Tree(T->rchild, c); //左分支中未找到,继续先序查找右分支
return p; //返回右分支查找结果
}
return p; //左分支中找到,返回当前指针,查找结束
}
}
主函数(用于测试):
int main()
{
BiTree T;
Init_Tree(T); //1、初始化
bool t = Empty_Tree(T); //5、判空
if (t) {
cout << "二叉树为空" << endl;
}
else {
cout << "二叉树非空" << endl;
}
cout << "按先序顺序输入元素:";
Create_Tree(T); //3、创建
int d = Depth_Tree(T); //6、返回深度
cout << "二叉树的深度:" << d << endl;
char c = Root_Tree(T); //7、返回根的元素值
cout << "根的元素值为:" << c << endl;
BiTree p, q; //p为检验程序时使用,可随意更改p的指向
cout << "请设置p指针指向的元素:";
cin >> c;
p = Find_Tree(T, c); //21、先序查找指定元素值的二叉树结点
c = Value_Tree(T, p); //8、返回p指针指向的结点值
cout << "p指向的结点值:" << c << endl;
q = Parent_Tree(T, p); //9、若p非T的根节点,则返回其双亲指针,否则返回NULL
cout << "p的双亲指针q指向的元素:" << Value_Tree(T, q) << endl;
q = LeftChild_Tree(T, p); //10、返回p的左孩子指针,若没有返回NULL
cout << "p的左孩子指针q指向的元素:" << Value_Tree(T, q) << endl;
q = RightChild_Tree(T, p); //11、返回p的右孩子指针,若没有返回NULL
cout << "p的右孩子指针q指向的元素:" << Value_Tree(T, q) << endl;
q = LeftBrother_Tree(T, p); //12、返回p的左兄弟指针,若没有返回NULL
cout << "p的左兄弟指针q指向的元素:" << Value_Tree(T, q) << endl;
q = RightBrother_Tree(T, p); //13、返回p的右兄弟指针,若没有返回NULL
cout << "p的右兄弟指针q指向的元素:" << Value_Tree(T, q) << endl;
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
cout << "中序遍历二叉树:";
InPrint_Tree(T); //15、中序遍历并打印
cout << endl;
cout << "后序遍历二叉树:";
PostPrint_Tree(T); //16、后序遍历并打印
cout << endl;
cout << "层次遍历二叉树:";
LevelPrint_Tree(T); //17、层次遍历并打印
cout << endl;
cout << "想要更改的元素值:";
cin >> c;
q = Find_Tree(T, c); //21、先序查找指定元素值的二叉树结点
cout << "更改后的元素值:";
cin >> c;
Assign_Tree(T, q, c); //18、将p结点元素赋值为c
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
BiTree S; //另创建一个根节点右子树为空的二叉树,作为插入的样本
Init_Tree(S); //1、初始化
cout << "按先序顺序输入要插入的二叉树(根节点右子树为空)的元素:";
Create_Tree(S); //3、创建
int LR;
cout << "请选择要插入的部位(0.p的左子树 1.p的右子树):";
cin >> LR;
Insert_Tree(T, p, LR, S); //19、插入(S为非空二叉树,且右子树为空)
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
cout << "请选择要删除的部位(0.p的左子树 1.p的右子树):";
cin >> LR;
Delete_Tree(T, p, LR); //20、删除子树
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
cout << "二叉树已清空" << endl;
Clear_Tree(T); //4、清空(释放根之外的空间)
t = Empty_Tree(T); //5、判空
if (t) {
cout << "二叉树为空" << endl;
}
else {
cout << "二叉树非空" << endl;
}
Destroy_Tree(T); //2、销毁(基于后序顺序)
cout << "二叉树已销毁" << endl;
return 0;
}
下面是全部代码:
# include
# include
# include
# define SIZE 256
using namespace std;
typedef struct BiTNode {
char data;
struct BiTNode* lchild; //左孩子
struct BiTNode* rchild; //右孩子
}BiTNode, * BiTree;
void Init_Tree(BiTree& T) //1、初始化
{
T = (BiTNode*)malloc(sizeof(BiTNode));
T->data = '#';
T->lchild = NULL;
T->rchild = NULL;
}
void Destroy_Tree(BiTree& T) //2、销毁(基于后序顺序)
{
if (T) {
Destroy_Tree(T->lchild); //销毁左子树
Destroy_Tree(T->rchild); //销毁右子树
free(T);
}
}
void Create_Tree(BiTree& T) //3、创建(基于先序顺序)
{
char c;
cin >> c;
if (c == '#') { // # 代表空指针
T = NULL;
}
else { //创建根节点
T = (BiTNode*)malloc(sizeof(BiTNode));
T->data = c;
Create_Tree(T->lchild); //先序创建左分支
Create_Tree(T->rchild); //先序创建右分支
}
}
void Clear_Tree(BiTree& T) //4、清空(释放根之外的空间)
{
Destroy_Tree(T->lchild); //销毁T的左子树
Destroy_Tree(T->rchild); //销毁T的右子树
T = NULL;
}
bool Empty_Tree(BiTree T) //5、判空
{
if (T == NULL || T->data == '#') {
return true;
}
else {
return false;
}
}
int Depth_Tree(BiTree T) //6、返回深度
{
int leftdepth, rightdepth;
if (T == NULL) {
return 0; //到空时,返回0
}
else {
leftdepth = Depth_Tree(T->lchild); //求左子树深度
rightdepth = Depth_Tree(T->rchild); //求右子树深度
return max(leftdepth + 1, rightdepth + 1); //最终取较大深度
}
}
char Root_Tree(BiTree T) //7、返回根的元素值
{
if (T != NULL) { //树不为空
return T->data;
}
else {
return '#';
}
}
char Value_Tree(BiTree T, BiTree p) //8、返回p指针指向的结点值
{
if (T == NULL || p == NULL) {
return '#';
}
else {
return p->data;
}
}
BiTree Parent_Tree(BiTree T, BiTree p) //9、若p非T的根节点,则返回其双亲指针,否则返回NULL
{
BiTree q = NULL;
if (T == NULL || p == T) { //如果p等于根节点,返回NULL
return NULL;
}
else {
if (T->lchild == p || T->rchild == p) { //T是p的双亲,返回T
return T;
}
q = Parent_Tree(T->lchild, p); //在左分支中查找
if (q == NULL) { //左分支中没有找到,查找右分支
q = Parent_Tree(T->rchild, p);
return q;
}
return q;
}
}
BiTree LeftChild_Tree(BiTree T, BiTree p) //10、返回p的左孩子指针,若没有返回NULL
{
if (T != NULL && p != NULL) {
return p->lchild;
}
else {
return NULL;
}
}
BiTree RightChild_Tree(BiTree T, BiTree p) //11、返回p的右孩子指针,若没有返回NULL
{
if (T != NULL && p != NULL) {
return p->rchild;
}
else {
return NULL;
}
}
BiTree LeftBrother_Tree(BiTree T, BiTree p) //12、返回p的左兄弟指针,若没有返回NULL
{
if (T == NULL) {
return NULL;
}
else {
BiTree q = Parent_Tree(T, p); //先找到双亲结点
if (q != NULL && q->lchild != p) {
return q->lchild;
}
else {
return NULL;
}
}
}
BiTree RightBrother_Tree(BiTree T, BiTree p) //13、返回p的右兄弟指针,若没有返回NULL
{
if (T == NULL) {
return NULL;
}
else {
BiTree q = Parent_Tree(T, p);
if (q != NULL && q->rchild != p) {
return q->rchild;
}
else {
return NULL;
}
}
}
void PrePrint_Tree(BiTree T) //14、先序遍历并打印
{
if (T != NULL) {
cout << T->data; //访问根节点
PrePrint_Tree(T->lchild); //先序遍历左子树
PrePrint_Tree(T->rchild); //先序遍历右子树
}
}
void InPrint_Tree(BiTree T) //15、中序遍历并打印
{
if (T != NULL) {
InPrint_Tree(T->lchild); //中序遍历左子树
cout << T->data; //访问根节点
InPrint_Tree(T->rchild); //中序遍历右子树
}
}
void PostPrint_Tree(BiTree T) //16、后序遍历并打印
{
if (T != NULL) {
PostPrint_Tree(T->lchild); //后序遍历左子树
PostPrint_Tree(T->rchild); //后序遍历右子树
cout << T->data; //访问根节点
}
}
void LevelPrint_Tree(BiTree T) //17、层次遍历并打印
{
BiTree p;
queuequ; //定义队列,存放二叉树结点指针(这里使用了STL的queue类型)
qu.push(T); //根节点入队
while (!qu.empty()) {
p = qu.front();
cout << p->data; //访问队首结点
qu.pop(); //队首结点出队
if (p->lchild != NULL) {
qu.push(p->lchild); //若结点有左孩子,则左孩子入队
}
if (p->rchild != NULL) {
qu.push(p->rchild); //若结点有右孩子,则左孩子入队
}
}
}
void Assign_Tree(BiTree& T, BiTree p, char c) //18、将p结点元素赋值为c
{
if (T == NULL || p == NULL) {
return;
}
else {
p->data = c;
}
}
void Insert_Tree(BiTree& T, BiTree p, int LR, BiTree c) //19、插入(c为非空二叉树,且右子树为空)
{
if (T == NULL || p == NULL || c == NULL) {
return;
}
else {
if (LR == 0) { //LR为0,则c作为p的左子树;为1,则c作为p的右子树
c->rchild = p->lchild; //把原来的左子树连接在c的右子树上
p->lchild = c;
}
else {
c->rchild = p->rchild; //把原来的右子树连接在c的右子树上
p->rchild = c;
}
}
}
void Delete_Tree(BiTree& T, BiTree p, int LR) //20、删除子树
{
if (T == NULL || p == NULL) {
return;
}
if (LR == 0) { //删除p的左子树
Destroy_Tree(p->lchild);
p->lchild = NULL;
}
else { //删除p的右子树
Destroy_Tree(p->rchild);
p->rchild = NULL;
}
}
BiTree Find_Tree(BiTree T, char c) //21、先序查找指定元素值的二叉树结点
{
BiTree p = NULL;
if (T == NULL) {
return NULL;
}
else if (T->data == c) { //访问的当前结点值等于c,返回当前指针,查找结束
return T;
}
else {
p = Find_Tree(T->lchild, c); //在左分支中先序查找
if (p == NULL) {
p = Find_Tree(T->rchild, c); //左分支中未找到,继续先序查找右分支
return p; //返回右分支查找结果
}
return p; //左分支中找到,返回当前指针,查找结束
}
}
int main()
{
BiTree T;
Init_Tree(T); //1、初始化
bool t = Empty_Tree(T); //5、判空
if (t) {
cout << "二叉树为空" << endl;
}
else {
cout << "二叉树非空" << endl;
}
cout << "按先序顺序输入元素:";
Create_Tree(T); //3、创建
int d = Depth_Tree(T); //6、返回深度
cout << "二叉树的深度:" << d << endl;
char c = Root_Tree(T); //7、返回根的元素值
cout << "根的元素值为:" << c << endl;
BiTree p, q; //p为检验程序时使用,可随意更改p的指向
cout << "请设置p指针指向的元素:";
cin >> c;
p = Find_Tree(T, c); //21、先序查找指定元素值的二叉树结点
c = Value_Tree(T, p); //8、返回p指针指向的结点值
cout << "p指向的结点值:" << c << endl;
q = Parent_Tree(T, p); //9、若p非T的根节点,则返回其双亲指针,否则返回NULL
cout << "p的双亲指针q指向的元素:" << Value_Tree(T, q) << endl;
q = LeftChild_Tree(T, p); //10、返回p的左孩子指针,若没有返回NULL
cout << "p的左孩子指针q指向的元素:" << Value_Tree(T, q) << endl;
q = RightChild_Tree(T, p); //11、返回p的右孩子指针,若没有返回NULL
cout << "p的右孩子指针q指向的元素:" << Value_Tree(T, q) << endl;
q = LeftBrother_Tree(T, p); //12、返回p的左兄弟指针,若没有返回NULL
cout << "p的左兄弟指针q指向的元素:" << Value_Tree(T, q) << endl;
q = RightBrother_Tree(T, p); //13、返回p的右兄弟指针,若没有返回NULL
cout << "p的右兄弟指针q指向的元素:" << Value_Tree(T, q) << endl;
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
cout << "中序遍历二叉树:";
InPrint_Tree(T); //15、中序遍历并打印
cout << endl;
cout << "后序遍历二叉树:";
PostPrint_Tree(T); //16、后序遍历并打印
cout << endl;
cout << "层次遍历二叉树:";
LevelPrint_Tree(T); //17、层次遍历并打印
cout << endl;
cout << "想要更改的元素值:";
cin >> c;
q = Find_Tree(T, c); //21、先序查找指定元素值的二叉树结点
cout << "更改后的元素值:";
cin >> c;
Assign_Tree(T, q, c); //18、将p结点元素赋值为c
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
BiTree S; //另创建一个根节点右子树为空的二叉树,作为插入的样本
Init_Tree(S); //1、初始化
cout << "按先序顺序输入要插入的二叉树(根节点右子树为空)的元素:";
Create_Tree(S); //3、创建
int LR;
cout << "请选择要插入的部位(0.p的左子树 1.p的右子树):";
cin >> LR;
Insert_Tree(T, p, LR, S); //19、插入(S为非空二叉树,且右子树为空)
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
cout << "请选择要删除的部位(0.p的左子树 1.p的右子树):";
cin >> LR;
Delete_Tree(T, p, LR); //20、删除子树
cout << "先序遍历二叉树:";
PrePrint_Tree(T); //14、先序遍历并打印
cout << endl;
cout << "二叉树已清空" << endl;
Clear_Tree(T); //4、清空(释放根之外的空间)
t = Empty_Tree(T); //5、判空
if (t) {
cout << "二叉树为空" << endl;
}
else {
cout << "二叉树非空" << endl;
}
Destroy_Tree(T); //2、销毁(基于后序顺序)
cout << "二叉树已销毁" << endl;
return 0;
}
测试结果:
二叉树为空
按先序顺序输入元素:ABD#G###CE##F##
二叉树的深度:4
根的元素值为:A
请设置p指针指向的元素:C
p指向的结点值:C
p的双亲指针q指向的元素:A
p的左孩子指针q指向的元素:E
p的右孩子指针q指向的元素:F
p的左兄弟指针q指向的元素:B
p的右兄弟指针q指向的元素:#
先序遍历二叉树:ABDGCEF
中序遍历二叉树:DGBAECF
后序遍历二叉树:GDBEFCA
层次遍历二叉树:ABCDEFG
想要更改的元素值:D
更改后的元素值:X
先序遍历二叉树:ABXGCEF
按先序顺序输入要插入的二叉树(根节点右子树为空)的元素:HJK####
请选择要插入的部位(0.p的左子树 1.p的右子树):0
先序遍历二叉树:ABXGCHJKEF
请选择要删除的部位(0.p的左子树 1.p的右子树):0
先序遍历二叉树:ABXGCF
二叉树已清空
二叉树为空
二叉树已销毁
以上是我个人的学习成果,很高兴能与大家分享。