**1.**树概念及结构
1.1****树的概念
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因****为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
注意:树形结构中,子树之间不能有交集,否则就不是树形结构

1.2 树的相关概念

**结点的度:**一个结点含有的子树的个数称为该结点的度; 如上图:A的为6
**叶结点或终端结点:**度为0的结点称为叶结点; 如上图:B、C、H、I...等结点为叶结点
**非终端结点或分支结点:**度不为0的结点; 如上图:D、E、F、G...等结点为分支结点
**双亲结点或父结点:**若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图:A是B的父结点
**孩子结点或子结点:**一个结点含有的子树的根结点称为该结点的子结点; 如上图:B是A的孩子结点
**兄弟结点:**具有相同父结点的结点互称为兄弟结点; 如上图:B、C是兄弟结点
**树的度:**一棵树中,最大的结点的度称为树的度; 如上图:树的度为6
**结点的层次:**从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
**树的高度或深度:**树中结点的最大层次; 如上图:树的高度为4
**堂兄弟结点:**双亲在同一层的结点互为堂兄弟;如上图:H、I互为兄弟结点
**结点的祖先:**从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先
**子孙:**以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙
**森林:**由m(m>0)棵互不相交的树的集合称为森林;
1.3****树的表示
树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,既然保存值域,也要保存结点和结点之间****的关系,实际中树有很多种表示方式如:双亲表示法,孩子表示法、孩子双亲表示法以及孩子兄弟表示法 等。我们这里就简单的了解其中最常用的孩子兄弟表示法。
typedef int DataType;
struct Node
{
struct Node* firstChild1; // 第一个孩子结点
struct Node* pNextBrother; // 指向其下一个兄弟结点
DataType data; // 结点中的数据域
};

2.二叉树概念及结构
2.1概念
一棵二叉树是结点的一个有限集合,该集合:
1. 或者为空
2. 由一个根结点加上两棵别称为左子树和右子树的二叉树组成

从上图可以看出:
-
二叉树不存在度大于2的结点
-
二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树
注意:对于任意的二叉树都是由以下几种情况复合而成的:

2.2 特殊的二叉树:
**1. 满二叉树:**一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是 说,如果一个二叉树的层数为K,且结点总数是2,则它就是满二叉树。
**2. 完全二叉树:**完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K 的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对 应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。

2.3 二叉树的性质
-
若规定根结点的层数为1,则一棵非空二叉树的第i层上最有 个个结点.
-
若规定根结点的层数为1,则深度为h的二叉树的最大结点数是 .
-
对任何一棵二叉树, 如果度为0其叶结点个数为 , 度为2的分支结点个数为 ,则有 = +1
3.二叉树的顺序结构及实现
3.1 二叉树的顺序结构
普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。

3.2二叉树的实现
创建二叉树的结构
typedef struct Tree
{
struct Tree *left;
struct Tree *right;
int data;
}T;
创建二叉树的叶子结点
T* newtree(int x)
{
T *tree = (T *)malloc(sizeof(int) );
if (tree == nullptr)
{
perror("fail malloc");
return;
}
tree->left=nullptr;
tree->right=nullptr;
tree->data=x;
return tree;
}
形成一棵二叉树树
T* tee()
{
T *tree1 = newtree(1);
T *tree2= newtree(2);
T *tree3 = newtree(3);
T *tree4 = newtree(4);
T *tree5 = newtree(5);
T *tree6 = newtree(6);
tree1->left=tree2;
tree1->right=tree4;
tree2->left=tree3;
tree4->left=tree5;
tree4->right=tree6;
return tree1;
}
前序遍历
//根 左 右
void Preoder(T*tree)
{
if(tree==nullptr)
{
printf("N ");
return ;
}
cout<<tree->data<<endl;
Preoder(tree->left);
Preoder(tree->right);
}
// 1 2 3 N N N 4 5 N N 6 N N

中序遍历
//左 根 右
void Inorder(T*tree)
{
if(tree==nullptr)
{
printf("N ");
return ;
}
Preoder(tree->left);
cout<<tree->data<<endl;
Preoder(tree->right);
}
//N 3 N 2 N 1 N 5 N 4 N 6 N

后序遍历
//左 右 根
void odrer(T*tree)
{
if(tree==nullptr)
{
printf("N ");
return ;
}
Preoder(tree->left);
Preoder(tree->right);
cout<<tree->data<<endl;
}
// N N 3 N 2 N N 5 N N 6 4 1

统计节点总数
int treesize(T *tree)
{
return tree == nullptr ? 0 : treesize(tree->left) +
treesize(tree->right) + 1;
}

统计叶子节点数
int TreeLeafSize(T*tree)
{
if (tree == NULL)
return 0;
if (tree->left == NULL && tree->right == NULL)
return 1;
return TreeLeafSize(left) + TreeLeafSize(right);
}

树的高度
int TreeHeight(T *tree)
{
if (tree == NULL)
return 0;
int leftH = TreeHeight(tree->left);
int rightH = TreeHeight(tree->right);
return leftH > rightH ? leftH + 1 : rightH + 1;
}

查找第K层有几个结点
//查找第K层有几个结点 查找第三层为例
int Find(T*tree,int k)
{
if (tree == NULL)
return 0;
if(k==1)
{
return 1;
}
return Find(tree->left,k-1)+
Find(tree->right,k-1);
}

查找某节点
//查找x结点 以5结点为例
T* treeFind(T*tree,int x)
{
if (tree == NULL)
return 0;
if(tree->data ==x )
{
return tree;
}
//遍历树的左节点
T* ret= treeFind(tree->left,x);
if(ret)
{
return ret;
}
//遍历树的右节点
T* ret1= treeFind(tree->right,x);
if(ret1)
{
return ret1;
}
return nullptr;
}

判断完全二叉树
// 判断完全二叉树
bool isCompleteTree(T* tree)
{
if (tree == NULL)
return true;
T* queue[1000];
int front = 0, rear = 0;
queue[rear++] = tree; // 把 1 入队
bool meetNull = false;
while (front < rear)
{
T* cur = queue[front++];//出队列
if (cur == NULL)
{
meetNull = true;
}
else
{
if (meetNull)
return false;
queue[rear++] = cur->left;
queue[rear++] = cur->right;
}
}
return true;
}

二叉树的销毁
void Destroy(T *tree)
{
if (tree == NULL)
return ;
Destroy(tree->left);
Destroy(tree->right);
free(tree);
}
4.前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
#include <iostream>
using namespace std;
// 创建单个树结构
typedef char BTDataType;
typedef struct BinaryTree
{
struct BinaryTree* left;
struct BinaryTree* right;
BTDataType data;
} BTNode;
// 存数据的数组 数组长度 pi数组下标指针
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
// 越界或为# //越界是递归处理完所有字符的正常标志
if (*pi >= n || a[*pi] == '#')
{
(*pi)++;
return nullptr;
}
// 有数据建树 . 创建根节点
BTNode* tree = new BTNode;
tree->data = a[*pi];
(*pi)++; // 用过了
// 2. 递归建左子树
tree->left = BinaryTreeCreate(a, n, pi);
// 3. 递归建右子树
tree->right = BinaryTreeCreate(a, n, pi);
return tree;
}
void Preoder(BTNode* tree)
{
if (tree == nullptr)
{
printf("# ");
return;
}
cout << tree->data << endl;
Preoder(tree->left);
Preoder(tree->right);
}
int main()
{
char str[] = "ABD##E#H##CF##G##";
int n = sizeof(str) / sizeof(str[0]) - 1; // 字符串长度
int i = 0;
BTNode* tree = BinaryTreeCreate(str, n, &i);
cout << "二叉树构建完成!" << endl;
cout << "打印二叉树: " << endl;
Preoder(tree);
return 0;
}


