- 中序遍历:首先遍历左子树,然后访问根节点,最后遍历右子树(左->根->右)
中序遍历的递归算法
思路:
- 遍历左子树
- 访问根节点
- 遍历右子树
代码如下:
//二叉树的中序遍历(递归)
void BinaryTreePrevOrder(BTNode* root){
if (root){
BinaryTreePrevOrder(root->lChild);
putchar(root->data);
BinaryTreePrevOrder(root->rChild);
}
}
中序遍历的非递归算法
思路:
借助栈来实现
- 传入二叉树根节点
- 从该节点开始遍历左子树,将所有节点入栈,直至左子树为空
- 取出栈顶并打印,再将栈顶出栈
- 如果有右孩子,从步骤2开始;没有右孩子从步骤3开始(直至全部出栈)
图解非递归算法
代码如下:
//二叉树的中序遍历(非递归)
void BinaryTreeInOrderNonR(BTNode * root)
{
BTNode * cur = root;
Stack st;
StackInit(&st, 100);
while (cur || !StackIsEmpty(&st))
{
for (; cur; cur = cur->lChild) //将当前节点及左孩子们入栈
{
StackPush(&st, cur);
}
cur = StackTop(&st);
//1、如果右孩子为空,for循环不进,直接取栈顶
//2、如果右孩子不为空,那么这是一个没有左孩子的节点
//第一种情况是左子树访问完毕,第二种情况是左子树为空,无论哪种,当前节点都要打印
putchar(cur->data);
StackPop(&st);
cur = cur->rChild; //当右子树为空时,检查栈是否为空,如果栈也空了,循环跳出
}
StackDestory(&st);
}
栈函数实现如下:
typedef char BTDataType;
// 二叉链的结构体
typedef struct BinaryTreeNode {
BTDataType data; // 当前节点值域
struct BinTreeNode* lChild; // 指向当前节点左孩子
struct BinTreeNode* rChild;// 指向当前节点右孩子
}BTNode;
typedef BTNode* StDataType;
// 栈的结构体
typedef struct Stack {
StDataType* array; // 指向动态开辟的数组
size_t size; // 有效数据个数
size_t capicity; // 容量空间的大小
}Stack;
void StackInit(Stack* psl, size_t capicity)
{
assert(psl);
psl->capicity = capicity;
psl->array = (StDataType *)malloc(capicity * sizeof(StDataType));
assert(psl->array);
psl->size = 0;
}
void StackDestory(Stack* psl)
{
assert(psl);
if (psl->array)
{
free(psl->array);
psl->array = NULL;
psl->size = 0;
psl->capicity = 0;
}
}
void CheckCapacity(Stack* psl)
{
assert(psl);
if (psl->size == psl->capicity)
{
psl->capicity *= 2;
psl->array = (StDataType *)realloc(psl->array, psl->capicity * sizeof(StDataType));
}
}
void StackPush(Stack* psl, StDataType x)
{
assert(psl);
CheckCapacity(psl);
psl->array[psl->size] = x;
psl->size++;
}
void StackPop(Stack* psl)
{
assert(psl || psl->size);
psl->size--;
}
StDataType StackTop(Stack* psl)
{
if (StackIsEmpty(psl))
{
return (StDataType)0;
}
return psl->array[psl->size - 1];
}
int StackIsEmpty(Stack* psl)
{
return psl->size == 0;
}