1.二叉树概念
二叉树(Binary Tree)是n(n >= 0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。
2.二叉树的特点
- 每个结点最多有两个子树,所以二叉树中不存在度大于2的结点;注意不是只有两棵子树,而是最多有,没有子树或者由一棵子树都是可以的。
- 左右子树是有顺序的次序不能任意颠倒。
- 即使树中摸个结点只有一棵子树,也要区分它是左子树还是右子树。
3.二叉树的基本形态
- (1)空二叉树
- (2)只有一个根结点
- (3)根结点只有左子树
- (4)根结点只有右子树
- (5)根结点既有左子树又有右子树
注:因此二叉树由以上5种情况组成。
4.特殊二叉树
【1.斜树】
顾名思义,斜树一定是要斜的,但往哪斜还是有讲究的;所有结点只有左子树的二叉树叫左斜树,所有结点只有右子树的二叉树叫右斜树,这两者统称为斜树。斜树有很明显的特点,就是每一层都只有一个结点,结点的个数与二叉树的深度相同。
【2.满二叉树】
在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样的二叉树称为满二叉树。
特点:
- (1)叶子只能出现在最下一层,出现在其他层就不可能达到平衡。
- (2)非叶子结点的度一定是2,否则就是“缺胳膊少腿”了。
- (3)在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。
【3.完全二叉树】
对一棵具有n个结点的二叉树按层序编号,如果编号为i(1 <= i <= n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树。
特点:
- (1)叶子结点只能出现在最下两层。
- (2)最下层的叶子一定集中在左部连续位置。
- (3)倒数第二层,若有叶子结点,一定在右连续位置。
- (4)如果结点度为1,则该结点只有左孩子,即不存在只有右子树的情况。
- (5)同样结点的二叉树,完全二叉树的深度最小。
5.二叉树性质
-
性质1
:在二叉树的第i层上至多有2^(i-1)个结点(i >= 1)。 -
性质2
:深度为k的二叉树至多有2^k -1个结点(i >= 1)。 -
性质3
:对任何一棵二叉树T,如果其终端结点为n0,度为2的结点树为n2,则n0 = n2 +1。 -
性质4
:具有n个结点的完全二叉树的深度为㏒n +1(此处的㏒n表示不大于它的最大整数)。 -
性质5
:如果对一棵有n个结点的完全二叉树的结点按层序编号,对任一结点i(1 <= i <= n)有:- 如果 i =1,则结点i是二叉树的根,无双亲;如果 i > 1,则双亲是结点不大于i/2的整数。
- 如果 2i > n,则结点 i 无左孩子(结点 i 为叶子结点);否则左孩子是 2i。
- 如果 2i + 1 > n,则结点 i 无右孩子;否则右孩子为 2i + 1。
6.完整代码块
/************************************/
//BinTree.h
typedef int BDataType;
typedef struct BTNode
{
struct BTNode *_pLeft;
struct BTNode *_pRight;
BDataType data;
}BTNode;
//创建二叉树
void CrateBinTree(BTNode **pRoot, char *str, int size, int *index, BDataType inValid);
//前序遍历二叉树
void PreOrderBinTree(BTNode *pRoot);
//前序遍历二叉树(非递归)
void PreOrderBinTreeNor(BTNode *pRoot);
//中序遍历二叉树
void InOrderBinTree(BTNode *pRoot);
//中序遍历二叉树(非递归)
void InOrderBinTreeNor(BTNode *pRoot);
//后序遍历二叉树
void PostOrderBinTree(BTNode *pRoot);
//后序遍历二叉树(非递归)
void PostOrderBinTreeNor(BTNode *pRoot);
//层序遍历二叉树
void LevelOrderBintree(BTNode *pRoot);
//拷贝二叉树
BTNode *CopyBinTree(BTNode *pRoot);
//销毁二叉树
void DestoryBinTree(BTNode **pRoot);
//求二叉树结点数
int GetBTNodeCount(BTNode *pRoot);
//求叶子结点数
int GetLeafNodeCount(BTNode *pRoot);
//求低K层结点数
int GetKLevelNodeCount(BTNode *pRoot, int k);
//求二叉树的高度
int HeightBinTree(BTNode *pRoot);
//判断一个结点是否在二叉树中
int IsBTNodeBinTree(BTNode*pRoot, BTNode *pNode);
//查找一个结点的双亲结点
BTNode * GetBTNodeParent(BTNode *pRoot, BTNode *pNode);
//判断是否是完全二叉树
int IsCompleteBinTree(BTNode *pRoot);
//二叉树的镜像
void MirrorBinTree(BTNode *pRoot);
//二叉树的镜像(非递归)
void MirrorBinTreeNor(BTNode *pRoot);
//获取一个结点的左孩子结点
BTNode *LeftChild(BTNode *pRoot);
//获取一个结点的右孩子结点
BTNode *RightChild(BTNode *pRoot);
/************************************/
//BinTree.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "LQueue.h"
#include "Stack.h"
void Swap(BTNode **left, BTNode **right)
{
BTNode *tmp;
tmp = *left;
*left = *right;
*right = tmp;
}
//创建新结点
static BTNode *BuyBTNode(BDataType data)
{
BTNode *pNewNode;
pNewNode = (BTNode *)malloc(sizeof(BTNode));
if (NULL == pNewNode)
{
printf("创建新结点失败!\n");
assert(0);
}
pNewNode->data = data;
pNewNode->_pLeft = NULL;
pNewNode->_pRight = NULL;
}
//创建二叉树
void CrateBinTree(BTNode **pRoot, char *str, int size, int *index, BDataType invalid)
{
if (*index < size && invalid != str[*index])
{
//创建根结点
*pRoot = BuyBTNode(str[*index]);
++(*index);
//创建左子树
CrateBinTree(&((*pRoot)->_pLeft), str, size, index, invalid);
++(*index);
//创建右子树
CrateBinTree(&((*pRoot)->_pRight), str, size, index, invalid);
}
}
//前序遍历二叉树
void PreOrderBinTree(BTNode *pRoot)
{
if (pRoot)
{
printf("%c", pRoot->data);
PreOrderBinTree(pRoot->_pLeft);
PreOrderBinTree(pRoot->_pRight);
}
}
//前序遍历二叉树(非递归)
void PreOrderBinTreeNor(BTNode *pRoot)
{
Stack s;
BTNode *pCur = NULL;
if (NULL == pRoot)
return NULL;
StackInit(&s);
StackPush(&s, pRoot);
while (!StackEmpty(&s))
{
pCur = StackTop(&s);
printf("%c", pCur->data);
StackPop(&s);
if (pCur->_pRight)
StackPush(&s, pCur->_pRight);
if (pCur->_pLeft)
StackPush(&s, pCur->_pLeft);
}
}
//中序遍历二叉树
void InOrderBinTree(BTNode *pRoot)
{
if (pRoot)
{
InOrderBinTree(pRoot->_pLeft);
printf("%c", pRoot->data);
InOrderBinTree(pRoot->_pRight);
}
}
//中序遍历二叉树(非递归)
void InOrderBinTreeNor(BTNode *pRoot)
{
Stack s;
BTNode *pCur = pRoot;
if (NULL == pRoot)
return;
StackInit(&s);
while (!StackEmpty(&s) || pCur)
{
while (pCur)
{
StackPush(&s, pCur);
pCur = pCur->_pLeft;
}
pCur = StackTop(&s);
printf("%c", pCur->data);
StackPop(&s);
pCur = pCur->_pRight;
}
}
//后序遍历二叉树
void PostOrderBinTree(BTNode *pRoot)
{
if (pRoot)
{
PostOrderBinTree(pRoot->_pLeft);
PostOrderBinTree(pRoot->_pRight);
printf("%c", pRoot->data);
}
}
//后序遍历二叉树(非递归)
void PostOrderBinTreeNor(BTNode *pRoot)
{
Stack s;
BTNode *pTop = NULL;
BTNode *pPre = NULL;
BTNode *pCur = pRoot;
if (NULL == pRoot)
return;
StackInit(&s);
while (!StackEmpty(&s) || pCur)
{
while (pCur)
{
StackPush(&s, pCur);
pCur = pCur->_pLeft;
}
pTop = StackTop(&s);
if (NULL == pTop->_pRight || pPre == pTop->_pRight)
{
printf("%c", pTop->data);
pPre = pTop;
StackPop(&s);
}
else
pCur = pTop->_pRight;
}
}
//层序遍历
void LevelOrderBintree(BTNode *pRoot)
{
LQueue q;
BTNode *pCur = NULL;
if (NULL == pRoot)
return;
LQueueInit(&q);
LQueuePush(&q, pRoot);
while (!LQueueEmpty(&q))
{
pCur = LQueueTop(&q);
printf("%c", pCur->data);
if (pCur->_pLeft)
LQueuePush(&q, pCur->_pLeft);
if (pCur->_pRight)
LQueuePush(&q, pCur->_pRight);
LQueuePop(&q);
}
}
//拷贝二叉树
BTNode *CopyBinTree(BTNode *pRoot)
{
if (NULL == pRoot)
return;
if (pRoot)
pRoot = BuyBTNode(pRoot->data);
if (pRoot->_pLeft)
CopyBinTree(pRoot->_pLeft);
if (pRoot->_pRight)
CopyBinTree(pRoot->_pRight);
return pRoot;
}
//销毁二叉树
void DestoryBinTree(BTNode **pRoot)
{
if (NULL == *pRoot)
return;
DestoryBinTree(&((*pRoot)->_pLeft));
DestoryBinTree(&((*pRoot)->_pRight));
free(*pRoot);
*pRoot = NULL;
}
//求二叉树结点数
int GetBTNodeCount(BTNode *pRoot)
{
if (NULL == pRoot)
return 0;
return GetBTNodeCount(pRoot->_pLeft) + GetBTNodeCount(pRoot->_pRight) + 1;
}
//求叶子结点数
int GetLeafNodeCount(BTNode *pRoot)
{
if (NULL == pRoot)
return 0;
if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
return 1;
return GetLeafNodeCount(pRoot->_pLeft) + GetLeafNodeCount(pRoot->_pRight);
}
//求低K层结点数
int GetKLevelNodeCount(BTNode *pRoot, int k)
{
if (NULL == pRoot || 0 == k)
return 0;
if (1 == k)
return 1;
return GetKLevelNodeCount(pRoot->_pLeft, k - 1) + GetKLevelNodeCount(pRoot->_pRight, k - 1);
}
//求二叉树的高度
int HeightBinTree(BTNode *pRoot)
{
if (NULL == pRoot)
return 0;
return (HeightBinTree(pRoot->_pLeft) > HeightBinTree(pRoot->_pRight)) ? HeightBinTree(pRoot->_pLeft)+1 : HeightBinTree(pRoot->_pRight)+1;
}
//判断一个结点是否在二叉树中
int IsBTNodeBinTree(BTNode*pRoot, BTNode *pNode)
{
if (NULL == pRoot || NULL == pNode)
return 0;
if (pRoot == pNode)
return 1;
if (IsBTNodeBinTree(pRoot->_pLeft, pNode))
return 1;
return IsBTNodeBinTree(pRoot->_pRight, pNode);
}
//查找一个结点的双亲结点
BTNode * GetBTNodeParent(BTNode *pRoot, BTNode *pNode)
{
BTNode *Parent = NULL;
if (NULL == pRoot || NULL == pNode || (NULL == pRoot->_pLeft && NULL == pRoot->_pRight))
return NULL;
if (pRoot->_pLeft == pNode || pRoot->_pRight == pNode)
return pRoot;
if (Parent = GetBTNodeParent(pRoot->_pLeft, pNode))
return Parent;
return GetBTNodeParent(pRoot->_pRight, pNode);
}
//判断是否是完全二叉树
int IsCompleteBinTree(BTNode *pRoot)
{
LQueue q;
int flag = 0;
BTNode *pCur = NULL;
if (NULL == pRoot)
return 1;
LQueueInit(&q);
LQueuePush(&q, pRoot);
while (!LQueueEmpty(&q))
{
pCur = LQueueTop(&q);
LQueuePop(&q);
if (1 == flag)
{
if (pCur->_pLeft || pCur->_pRight)
return 0;
}
else
{
if (pCur->_pLeft && pCur->_pRight)
{
LQueuePush(&q, pCur->_pRight);
LQueuePush(&q, pCur->_pLeft);
flag = 0;
}
else if (pCur->_pLeft)
{
LQueuePush(&q, pCur->_pLeft);
flag = 1;
}
else if (pCur->_pRight)
return 0;
else
flag = 1;
}
/*LQueuePop(&q);*/
}
return 1;
}
//二叉树的镜像
void MirrorBinTree(BTNode *pRoot)
{
if (NULL == pRoot)
return;
Swap(&pRoot->_pLeft, &pRoot->_pRight);
if (pRoot->_pLeft)
MirrorBinTree(pRoot->_pLeft);
if(pRoot->_pRight)
MirrorBinTree(pRoot->_pRight);
}
//二叉树的镜像(非递归)
void MirrorBinTreeNor(BTNode *pRoot)
{
LQueue q;
BTNode *pCur = NULL;
if (NULL == pRoot)
return;
LQueueInit(&q);
LQueuePush(&q, pRoot);
while (!LQueueEmpty(&q))
{
pCur = LQueueTop(&q);
printf("%c", pCur->data);
if (pCur->_pLeft)
LQueuePush(&q, pCur->_pLeft);
if (pCur->_pRight)
LQueuePush(&q, pCur->_pRight);
Swap(&pCur->_pLeft, &pCur->_pRight);
LQueuePop(&q);
}
}
//获取一个结点的左孩子结点
BTNode *LeftChild(BTNode *pNode)
{
return (pNode != NULL) ? pNode->_pLeft : NULL;
}
//获取一个结点的右孩子结点
BTNode *RightChild(BTNode *pNode)
{
return (pNode != NULL) ? pNode->_pRight : NULL;
}
void BinTree()
{
BTNode *pRoot;
BTNode *pCP;
char str[] = "ABD###CE##F";
int size = strlen(str);
int index = 0;
int count = 0;
CrateBinTree(&pRoot, &str, size, &index, '#');
printf("前序遍历:");
PreOrderBinTree(pRoot);
printf("\n");
printf("前序遍历(非递归):");
PreOrderBinTreeNor(pRoot);
printf("\n");
printf("中序遍历:");
InOrderBinTree(pRoot);
printf("\n");
printf("中序遍历(非递归):");
InOrderBinTreeNor(pRoot);
printf("\n");
printf("后序遍历:");
PostOrderBinTree(pRoot);
printf("\n");
printf("后序遍历(非递归):");
PostOrderBinTreeNor(pRoot);
printf("\n");
printf("层序遍历:");
LevelOrderBintree(pRoot);
printf("\n");
printf("MirrorBinTree:");
MirrorBinTree(pRoot);
PreOrderBinTree(pRoot);
printf("\n");
printf("MirrorBinTreeNor:");
MirrorBinTreeNor(pRoot);
//PreOrderBinTree(pRoot);
printf("\n");
pCP = CopyBinTree(pRoot);
printf("CopyBinTree:");
PreOrderBinTree(pRoot);
printf("\n");
printf("二叉树结点数 = %d\n", GetBTNodeCount(pRoot));
printf("二叉树叶子结点数 = %d\n", GetLeafNodeCount(pRoot));
printf("第K层结点数 = %d\n", GetKLevelNodeCount(pRoot, 3));
printf("二叉树高度 = %d\n", HeightBinTree(pRoot));
printf("%c\n", GetBTNodeParent(pRoot, 'B'));
if (IsCompleteBinTree(pRoot))
printf("是一个完全二叉树\n");
else
printf("不是一个完全二叉树\n");
if (IsBTNodeBinTree(pRoot, 'B'))
printf("该结点在二叉树中\n");
else
printf("该结点不在二叉树中\n");
DestoryBinTree(&pRoot);
}