二叉树的一些性质:
度就是一个节点的分支数
对于任何一个 二叉树,如 果其叶节点的个数为n0,度为2的非叶节点个数是n2,则有n0=n2+1
(n0+n1+n2=2*n2+n1+1)——-(n0=n2+1);
度为1的非叶子节点个数为n1;
节点个数为n0+n1+n2;
边的个数为2*n2+n1;
节点的个数为:边的个数+1;
具有n个节点的完全二叉树的深度K为log2(n+1)向上取整。
一个具有n个节点的完全二叉树,如果按照从上至下从左到右的顺序对所有节点从0开始编号,则对于序号为i的节点有:
1)若>0,双亲信号为:(i-1)/2;
i=0;i为根节点编号,没有双亲
2)若2i+1<n,左孩子编号:2i+1,否则没有左孩子
3)若2i+2<n,右孩子序号:2i+2,否则无右孩子
二叉树形如下图:
1、构建一个二叉树
树的结构体 :
typedef struct BinaryTreeNode//树的结构体
{
Datatype data;
struct BinaryTreeNode* LeftTree;
struct BinaryTreeNode* RightTree;
}BTNode;
思想:创建一棵树,首先应该创建一个 新的树的根节点,遍历一个 数组,数组 的内容就是树的数据,当数组中为“#”时,代表是空树,使用递归的方法依次创建左子树和右子书。
代码如下:
BTNode* CreatTree(Datatype a[],int size,int* index)
{
BTNode* pRoot = (BTNode*)malloc(sizeof(BTNode));
assert(index);
if((*index) >= size)//表示已经将数组遍历完了
{
return NULL;
}
if (a[*index] == '#')//代表子树为空的情况
{
(*index)++;
return NULL;
}
//BTNode* pRoot = (BTNode*)malloc(sizeof(BTNode));
pRoot->data = a[*index];
(*index)++;
pRoot->LeftTree = CreatTree(a, size, index);
pRoot->RightTree = CreatTree(a, size, index);
return pRoot;
}
2、前序遍历
递归方式
void Prevorder(BTNode* pRoot)//前序遍历
{
if (pRoot == NULL)
{
return ;
}
printf("%c-", pRoot->data);//输出根节点
Prevorder(pRoot->LeftTree);//递归左子树
Prevorder(pRoot->RightTree);//递归右子树
}
非递归方式 :
void UnPrevorder(BTNode* pRoot)//前序遍历非递归
{
Stack S;
BTNode* pTop;
StackInit(&S);//栈的初始化
BTNode* pCur=pRoot;
while (!StackEmpty(&S) || (pCur != NULL))
{
while (pCur != NULL)
{
printf("%c ", pCur->data);//输出根节点
StackPush(&S, pCur);//压栈,这个一定要注意,并不是单纯的把数据压入栈,而是将节点压入栈
pCur = pCur->LeftTree;//继续寻找左子树,直到栈为空(遍历完成)或者pCur=NULL(所有的左子树遍历完成)
}//左子树为空时开始寻找右子树
pTop = Top(&S);
StackPop(&S);
pCur = pTop->RightTree;
}
}
3、中序遍历
递归:
void Inorder(BTNode* pRoot)//中序遍历
{
if (pRoot == NULL)
{
return NULL;
}
Inorder(pRoot->LeftTree);
printf("%c-", pRoot->data);
Inorder(pRoot->RightTree);
}
非递归:
void UnInorder(BTNode* pRoot)//中序遍历非递归
{
Stack S;
BTNode* pTop;
StackInit(&S);//栈的初始化
BTNode* pCur = pRoot;
while (!StackEmpty(&S) || (pCur != NULL))
{
while (pCur != NULL)
{
StackPush(&S, pCur);
pCur = pCur->LeftTree;
}
pTop = Top(&S);
StackPop(&S);
printf("%c ", pTop->data);
pCur = pTop->RightTree;
}
}
4、后序遍历
递归
void Postorder(BTNode* pRoot)//后序遍历
{
if (pRoot == NULL)
{
return NULL;
}
Postorder(pRoot->LeftTree);
Postorder(pRoot->RightTree);
printf("%c-", pRoot->data);
}
非递归:
void UnPostorder(BTNode* pRoot)//后序遍历非递归
{
Stack S;
BTNode* pTop;
StackInit(&S);//栈的初始化
BTNode* pCur = pRoot;
BTNode* Last = NULL;
while (!StackEmpty(&S) || (pCur != NULL))//遍历完左子树
{
while (pCur != NULL)
{
StackPush(&S, pCur);
pCur = pCur->LeftTree;
}
pTop = Top(&S);
if (pTop->RightTree == NULL || pTop->RightTree==Last)
{//若栈顶元素的右子树为空,那么就可以输出这个节点的数据,再将这个节点赋给last,、
//如果一个节点的右字数=last,那个这个节点就可以输出
printf("%c ", pTop->data);
StackPop(&S, pTop);
Last = pTop;
continue;
}
pCur = pTop->RightTree;
}
}
5、层序遍历
void UnLevelorder(BTNode* pRoot)//层序遍历非递归
{
Quene q;
BTNode* FrontNode;
if (pRoot == NULL)
{
return NULL;
}
QueneInit(&q);
QuenePush(&q, pRoot);
while (!QueneEmpty(&q))
{
FrontNode = QueneFront(&q);
QuenePop(&q);
printf("%c ", FrontNode->data);
if (FrontNode->LeftTree != NULL)
{
QuenePush(&q, pRoot->LeftTree);
}
if (FrontNode->RightTree != NULL)
{
QuenePush(&q, pRoot->RightTree);
}
}
printf("\n");
}
6、求节点的数量
int CountOfNodeone(BTNode* pRoot)//求节点数量
{
//static int n = 0;
if (pRoot == NULL)
{
return NULL;
}
n++;
CountOfNodeone(pRoot->LeftTree);
CountOfNodeone(pRoot->RightTree);
return n;
}
划分成子问题也可以解决
int CountOfNodetwo(BTNode* pRoot)//求节点数量,分解为子问题
{
if (pRoot==NULL)
{
return NULL;
}
return CountOfNodetwo(pRoot->LeftTree) + CountOfNodetwo(pRoot->RightTree) + 1;
}
7、求叶子节点的个数
int CountOfLeafNode(BTNode* pRoot)//求叶子节点的个数
{
if (pRoot == NULL)
{
return NULL;
}
if ((pRoot->LeftTree)== NULL&&(pRoot->RightTree== NULL))
{
return 1;
}
return CountOfLeafNode(pRoot->LeftTree) + CountOfLeafNode(pRoot->RightTree);
}
8、求第k层节点的个数
int CountKNode(BTNode* pRoot,int k)//求第K层节点的数量
{
if (pRoot == NULL&&k==1)
{
return NULL;
}
if (pRoot != NULL&&k == 1)
{
return 1;
}
return CountKNode(pRoot->LeftTree, k - 1) + CountKNode(pRoot->RightTree, k - 1);
}
9、求树的深度
int DepthOfNode(BTNode* pRoot)//求一棵树的高度
{
if (pRoot == NULL)
{
return NULL;
}
int left = DepthOfNode(pRoot->LeftTree);
int right = DepthOfNode(pRoot->RightTree);
return Max(left, right)+1;
}
10、查找某一个节点
BTNode* FindTreeNode(BTNode* pRoot, Datatype x)
{
if (pRoot == NULL)
{
return NULL;
}
if (pRoot->data == x)
{
return pRoot;
}
BTNode* FoundNode;
FoundNode=FindTreeNode(pRoot->LeftTree, x);
if (FoundNode != NULL)
{
return FoundNode;
}
return FindTreeNode(pRoot->RightTree, x);
}
11、测试函数
test()
{
char arr[] = { 'A', 'B', 'D', '#', '#','#','C', 'E', '#','#', 'F' };
int i = 0;
int ret = 0;
int len = sizeof(arr) / sizeof(arr[0]);
BTNode* Node;
BTNode* pRoot = (BTNode*)malloc(sizeof(BTNode));
pRoot = CreatTree(arr, len, &i);
Prevorder(pRoot);
printf("\n");
UnPrevorder(pRoot);
printf("\n");
Inorder(pRoot);
printf("\n");
UnInorder(pRoot);
printf("\n");
Postorder(pRoot);
printf("\n");
UnPostorder(pRoot);
printf("\n");
ret = CountOfNodetwo(pRoot);
printf("层序遍历:\n");
UnLevelorder(pRoot);
printf("节点总个数为:%d\n", ret);
printf("叶子节点的个数为:%d\n", CountOfLeafNode(pRoot));
printf("第%d层节点的个数为:%d\n",3,CountKNode(pRoot, 3));
printf("该树的深度为:%d\n", DepthOfNode(pRoot));
Node = FindTreeNode(pRoot, 'F');
if (Node == NULL)
{
printf("没有找到!\n");
}
else
{
printf("数据为:%c", Node->data);
}
}