1.1递归实现交换二叉树左右子树
void exchange(BiTree T) {
if (T == NULL) {
return;
}
// 交换当前节点的左右子树
BiTree temp = T->lchild;
T->lchild = T->rchild;
T->rchild = temp;
// 递归交换左子树和右子树
exchange(T->lchild);
exchange(T->rchild);
// 最后释放节点内存
free(T);
}
1.2使用栈来实现交换二叉树的左右子树
void exchange(BiTree T)
{
if (T == NULL) {
return;
}
// 创建一个栈
Stack s;
initStack(&s);
// 将根节点压入栈
if(T)
push(&s, T);
while (!isEmpty(&s)) {
// 从栈中弹出一个节点
BiTree node = pop(&s);
// 交换该节点的左右子树
BiTree temp = node->lchild;
node->lchild = node->rchild;
node->rchild = temp;
// 如果该节点有左子树,则将左子树压入栈
if (node->lchild) {
push(&s, node->lchild);
}
// 如果该节点有右子树,则将右子树压入栈
if (node->rchild) {
push(&s, node->rchild);
}
}
}
使用栈来进行操作,更容易理解。主要思路是结点进栈->出栈->执行相关操作->进栈左右节点->执行相关操作
->出栈 ···开始循环
在这里,相关操作指的是交换本次出栈节点的左右子节点。
2.1使用栈非递归实现先序遍历
void ProOrderTraverse(BiTree T,void(*Visit)(TElemType))
{ // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
// 先序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit
SqStack s;//定义并初始化栈
InitStack(s);
BiTNode * p;
if(T==NULL)
return;
Push(s,T);
while(!StackEmpty(s))
{
Pop(s,p);
Visit(p->data);
if(p->rchild)
Push(s, p->rchild);
if(p->lchild)
Push(s, p->lchild);
}
DestroyStack(s);
}
实现先序遍历,由于是根->左->右,主要访问当前节点,便于实现,可以使用:结点进栈->出栈->执行相关操作->进栈左右节点->执行相关操作
->出栈 ···开始循环
这里的相关操作是 访问当前节点。
2.2使用栈非递归实现中序遍历
由于是中序遍历,左->根->右,对任意一个结,先要访问他的左节点,所以就不能:结点进栈->出栈->执行相关操作->进栈左右节点->执行相关操作
->出栈···
// 中序遍历
void inOrderTraversal(struct TreeNode *root) {
struct StackNode *stack = NULL;
struct TreeNode *current = root;
while (current != NULL || !isStackEmpty(stack)) {
// 遍历左子树
while (current != NULL) {
push(&stack, current);
current = current->left;
}
current = pop(&stack);
printf("%d ", current->val); // 访问节点,可以替换为其他操作
current = current->right;
}
}
整个代码段的逻辑是:
尽可能向左走,把每个经过的节点压入栈中。
当无法继续向左走时,从栈中弹出一个节点访问。
访问完弹出的节点后,尝试访问其右子树。
其实当全部左子树压入栈之后,最后的那个叶节点肯定没有左节点,(左已完成)下一步就是针对最小单元的二叉树进行中序遍历。先出栈(根),再入栈右边,再入栈右部分的左子树···