概述
二叉树是数据结构中十分重要的一类结构, 其中有很多应用.
二叉树的特点:
- 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
- 二叉树的子树有左右之分,其子树的次序不能颠倒。
二叉树根据存储的结构可分为链式存储和顺序存储,
本文只涉及链式存储, 顺序存储请参展作者上一篇文章:二叉树的顺序存储–堆
结构
typedef char BTDataType;
typedef struct BTNode
{
struct BTNode* _pLeft;
struct BTNode* _pRight;
BTDataType _data;
}BTNode;
难点
初次学习二叉树主要以递归创建, 销毁,遍历 … 为主.
待后续学习c++/java等语言时刻直接调用堆栈队列等数据结构较为方便, 本文只涉及递归.
二叉树的最主要操作
BTNode* BinTreeCreate(char* array, int size, char invalid);
void BinTreeDestroy(BTNode** pRoot);
void PreOrder(BTNode* pRoot);
void InOrder(BTNode* pRoot);
void PostOrder(BTNode* pRoot);
二叉树的创建
BTNode* BuyBinTeeNode(BTDataType data)
{
BTNode* newBTNode = (BTNode*)malloc(sizeof(BTNode));
if (NULL == newBTNode)
{
assert(0);
return NULL;
}
newBTNode->_data = data;
newBTNode->_pLeft = NULL;
newBTNode->_pRight = NULL;
return newBTNode;
}
BTNode* DealBinTreeCreate(char* array, int size, int* index, char invalid)
{
BTNode* pRoot = NULL;
if (*index < size && invalid != array[*index])
{
pRoot = BuyBinTeeNode(array[*index]);
(*index)++;
pRoot->_pLeft = DealBinTreeCreate(array, size, index, invalid);
(*index)++;
pRoot->_pRight = DealBinTreeCreate(array, size, index, invalid);
}
return pRoot;
}
BTNode* BinTreeCreate(char* array, int size, char invalid)
{
//封装一层, 少写一个Index
int index = 0;
return DealBinTreeCreate(array, size, &index, invalid);
}
二叉树的销毁
void BinTreeDestroy(BTNode** pRoot)
{
// 因为无法改变根节点的指向, 故传二级指针
assert(pRoot);
// 销毁思想为后续遍历, 否则会丢失节点
if (*pRoot)
{
BinTreeDestroy(&(*pRoot)->_pLeft);
BinTreeDestroy(&(*pRoot)->_pRight);
free(*pRoot);
pRoot = NULL;
}
}
遍历
void PreOrder(BTNode* pRoot)
{
if (pRoot)
{
printf("%c ", pRoot->_data);
PreOrder(pRoot->_pLeft);
PreOrder(pRoot->_pRight);
}
}
void InOrder(BTNode* pRoot)
{
if (pRoot)
{
InOrder(pRoot->_pLeft);
printf("%c ", pRoot->_data);
InOrder(pRoot->_pRight);
}
}
void PostOrder(BTNode* pRoot)
{
if (pRoot)
{
PostOrder(pRoot->_pLeft);
PostOrder(pRoot->_pRight);
printf("%c ", pRoot->_data);
}
}
其他的操作
int BinTreeGetKLevelNodeCount(BTNode* pRoot, int k);
int BinTreeGetLeafCount(BTNode* pRoot);
int BinTreeGetHeight(BTNode* pRoot); // 求深度
BTNode* BinTreeFind(BTNode* pRoot, BTDataType x);
int BinTreeGetKLevelNodeCount(BTNode* pRoot, int k)
{
if (NULL == pRoot || k <= 0)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinTreeGetKLevelNodeCount(pRoot->_pLeft, k - 1) +
BinTreeGetKLevelNodeCount(pRoot->_pRight, k - 1);
}
BTNode* BinTreeFind(BTNode* pRoot, BTDataType x)
{
if (NULL == pRoot)
{
return 0;
}
if (pRoot->_data == x)
{
return pRoot;
}
BTNode* pRet = NULL;
if (pRet = BinTreeFind(pRoot->_pLeft, x))
{
return pRet;
}
return BinTreeFind(pRoot->_pRight, x);
}
int BinTreeGetLeafCount(BTNode* pRoot)
{
if (NULL == pRoot)
{
return 0;
}
if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
{
return 1;
}
return BinTreeGetLeafCount(pRoot->_pLeft) + BinTreeGetLeafCount(pRoot->_pRight);
}
int BinTreeGetHeight(BTNode* pRoot)
{
if (NULL == pRoot)
{
return 0;
}
int left = BinTreeGetHeight(pRoot->_pLeft);
int right = BinTreeGetHeight(pRoot->_pRight);
return (left > right) ? left + 1 : right + 1;
}