本文中所使用的栈、队列的基本操作均在《顺序栈》、《链式队列》中。
链接:
https://blog.youkuaiyun.com/lw13572259173/article/details/82927983
https://blog.youkuaiyun.com/lw13572259173/article/details/84866916
二叉树的定义
typedef int BDataType;
typedef struct BTNode
{
struct BTNode* pLeft; //左孩子
struct BTNode* pRight; //右孩子
BDataType data;
}BTNode, *pBTNode;
创建新结点
pBTNode BTBuyNode(BDataType d)
{
pBTNode newNode = (pBTNode)malloc(sizeof(BTNode));
if (NULL == newNode)
{
assert(0);
}
newNode->data = d;
newNode->pLeft = NULL;
newNode->pRight = NULL;
return newNode;
}
前序遍历
递归
void PreOrder(pBTNode pbtree)
{
//树不为空
if (pbtree)
{
printf("%d ", pbtree->data);//遍历根节点
PreOrder(pbtree->pLeft);//遍历左孩子
PreOrder(pbtree->pRight);//遍历右孩子
}
}
非递归
方法1
void PreOrderNor1(pBTNode pbtree)
{
//树不为空
if (NULL == pbtree)
{
return;
}
Stack stack;
StackInit(&stack);//初始化
//根结点入栈
StackPush(&stack, (int)pbtree);//压栈
while (!StackEmpty(&stack))//栈是否为空
{
pBTNode btnode = (pBTNode)StackTop(&stack);//查看栈顶元素
printf("%d ", btnode->data);
StackPop(&stack);//出栈
if (btnode->pRight) //右孩子存在
{
StackPush(&stack, (int)(btnode->pRight));//压栈
}
if (btnode->pLeft) //左孩子存在
{
StackPush(&stack, (int)(btnode->pLeft));//压栈
}
}
}
方法2
void PreOrderNor2(pBTNode pbtree)
{
//树不为空
if (NULL == pbtree)
{
return;
}
Stack stack;
StackInit(&stack);//初始化
StackPush(&stack, (int)pbtree);//压栈
while (!StackEmpty(&stack))//栈是否为空
{
pBTNode btnode = (pBTNode)StackTop(&stack);//查看栈顶元素
StackPop(&stack);//出栈
while (btnode)
{
printf("%d ", btnode->data);
if (btnode->pRight) //右孩子存在
{
StackPush(&stack, (int)(btnode->pRight));//压栈
}
btnode = btnode->pLeft;
}
}
}
中序遍历
递归
void InOrder(pBTNode pbtree)
{
//树不为空
if (pbtree)
{
InOrder(pbtree->pLeft);//遍历左孩子
printf("%d ", pbtree->data);//打印根节点
InOrder(pbtree->pRight);//遍历右孩子
}
}
非递归
void InOrderNor(pBTNode pbtree)
{
//树不为空
if (NULL == pbtree)
{
return;
}
Stack stack;
StackInit(&stack);//初始化
pBTNode cur = pbtree;
//找到最左端的结点
while (!StackEmpty(&stack) || NULL != cur)//根结点
{
while (NULL != cur) //遍历左子树
{
StackPush(&stack, (int)cur);//压栈
cur = cur->pLeft;
}
cur = (pBTNode)StackTop(&stack);//查看栈顶元素
printf("%d ", cur->data);//遍历根节点
StackPop(&stack);//出栈
cur = cur->pRight;//以右子树为根节点
}
}
后序遍历
递归
void PostOrder(pBTNode pbtree)
{
//树不为空
if (pbtree)
{
PostOrder(pbtree->pLeft);//遍历左孩子
PostOrder(pbtree->pRight);//遍历右孩子
printf("%d ", pbtree->data);//遍历根节点
}
}
非递归
void PostOrderNor(pBTNode pbtree)
{
//树不为空
if (NULL == pbtree)
{
return;
}
Stack stack;
StackInit(&stack);//初始化
pBTNode cur = pbtree;
pBTNode pPrev = NULL; //标记
while (!StackEmpty(&stack) || NULL != cur)
{
while (NULL != cur) //遍历左子树
{
StackPush(&stack, (int)cur);//压栈
cur = cur->pLeft;
}
pBTNode pTop = (pBTNode)StackTop(&stack);//查看栈顶元素
if (NULL == pTop->pRight || pTop->pRight == pPrev) //不能直接遍历根结点,需要右子树为空或者右子树已经遍历过
{
printf("%d ", pTop->data);//遍历根节点
pPrev = pTop;
StackPop(&stack);//出栈
}
else
{
cur = pTop->pRight; //遍历右节点
}
}
}
创建二叉树
void CreateBinTree(pBTNode* pbtree, const char* str, int size, int* count)
{
if (size > *count && *(str + (*count)) != '#')
{
*pbtree = BTBuyNode(*(str + (*count)++)); //创建根结点
CreateBinTree(&((*pbtree)->pLeft), str, size, count); //创建左子树
CreateBinTree(&((*pbtree)->pRight), str, size, count); //创建右子树
}
else
{
(*count)++;
}
}
拷贝二叉树
void CopyeBinTree(pBTNode pbtree, pBTNode* pnewbtree)
{
if (pbtree)
{
*pnewbtree = BTBuyNode(pbtree->data); //创建根结点
CopyeBinTree(pbtree->pLeft, &((*pnewbtree)->pLeft));
CopyeBinTree(pbtree->pRight, &((*pnewbtree)->pRight));
}
}
销毁二叉树
void DestnyBinTree(pBTNode* pbtree)
{
if (*pbtree)
{
DestnyBinTree(&((*pbtree)->pLeft));
DestnyBinTree(&((*pbtree)->pRight));
free(*pbtree);
*pbtree = NULL;
}
}
结点个数
int GetBTNodeCount(pBTNode pbtree)
{
if (pbtree == NULL)//根结点不存在
return 0;
return GetBTNodeCount(pbtree->pLeft) + GetBTNodeCount(pbtree->pRight) + 1;//根结点存在
}
叶子结点个数
int GetLeafBTNodeCount(pBTNode pbtree)
{
if (pbtree == NULL)//根结点不存在
return 0;
if (NULL == pbtree->pLeft &&NULL == pbtree->pRight) //左右孩子不存在
return 1;
return GetLeafBTNodeCount(pbtree->pLeft) + GetLeafBTNodeCount(pbtree->pRight);
}
第k层结点
int GetKLevelBTNodeCount(pBTNode pbtree, BDataType k)
{
if (pbtree == NULL)//根结点不存在
return 0;
if (k <= 0)
return 0;
if (1 == k)
return 1;
return GetKLevelBTNodeCount(pbtree->pLeft, k - 1) + GetKLevelBTNodeCount(pbtree->pRight, k - 1);
}
树的高度
int Height(pBTNode pbtree)
{
if (NULL == pbtree)
return 0;
int highL = Height(pbtree->pLeft);
int highR = Height(pbtree->pRight);
return highL > highR ? highL + 1 : highR + 1;
}
获取左孩子结点
pBTNode BTNodeLeft(pBTNode pNode)
{
if (NULL == pNode)
return NULL;
return pNode->pLeft;
}
获取右孩子结点
pBTNode BTNodeRight(pBTNode pNode)
{
if (NULL == pNode)
return NULL;
return pNode->pRight;
}
判断一个结点是否在一颗二叉树上
int IsBTNodeInBintree(pBTNode pbtree, pBTNode pNode)
{
if (NULL == pbtree || NULL == pNode) //树为空或结点为空
{
return 0;
}
if (pNode == pbtree) //结点为根
{
return 1;
}
if (IsBTNodeInBintree(pbtree->pLeft, pNode)) //结点在左子树
{
return 1;
}
if (IsBTNodeInBintree(pbtree->pRight, pNode)) //结点在右子树
{
return 1; //可以直接返回此次调用的返回值
//return IsBTNodeInBintree(pbtree->pRight, pNode);
}
return 0;
}
获得一个结点的双亲结点
pBTNode GetNodeParent(pBTNode pbtree, pBTNode pNode)
{
pBTNode parent = NULL;
if (NULL == pbtree || NULL == pNode) //树为空或结点为空
{
return NULL;
}
if (pNode == pbtree) //结点为根
{
return NULL;
}
if (pNode == pbtree->pLeft || pNode == pbtree->pRight) //为根的左孩子或者右孩子
{
return pbtree;
}
if (parent = GetNodeParent(pbtree->pLeft, pNode)) //以根的左孩子为根结点
{
return parent;
}
if (parent = GetNodeParent(pbtree->pRight, pNode)) //以根的右孩子为根结点
{
return parent; //可以直接返回此次调用的返回值
//return GetNodeParent(pbtree->pRight, pNode);
}
return NULL;
}