二叉树的链式存储结构:
typedef struct BiTNode {
Elemtype data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
先序遍历(递归)
void PreOrder(BiTNode T) {
if (T != NULL) {
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
先序遍历(非递归)
算法思想:从根结点开始,依次访问结点并将左孩子结点入栈;如果没有左孩子结点,则将该结点出栈并访问其右孩子结点。
void PreOrder_1(BiTree T) {
SqStack S;
InitStack(S);
BiTree p = T;
while (p || !IsEmpty(S)) {
if (p) {
visit(p);
Push(S, p);
p = p->lchild;
} else {
Pop(S, p);
p = p->rchild;
}
}
}
中序遍历(递归)
void InOrder(BiTree T) {
if (T != NULL) {
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
中序遍历(非递归)
算法思想:与先序非递归遍历类似,区别是在出栈时访问结点。
void InOrder_1(BiTree T) {
SqStack S;
InitStack(S);
BiTree p = T;
while (p || !IsEmpty(S)) {
if (p) {
Push(S, p);
p = p->lchild;
} else {
Pop(S, p);
visit(p);
p = p->rchild;
}
}
}
后序遍历(递归)
void PostOrder(BiTree T) {
if (T != NULL) {
PostOrder(T->lchild);
PostOrder(T->rchild);
visit(T);
}
}
后序遍历(非递归)
算法思想:①沿着根的左孩子依次入栈,直到左孩子为空。②读取栈顶元素,若右孩子不为空且未被访问过,则对右子树执行①;否则,栈顶元素出栈并访问。
void PostOrder(BiTree T) {
SqStack S;
InitStack(S);
BiTree p = T;
BiTNode r = NULL;
while (p || !IsEmpty(S)) {
if (p) {
Push(S, p);
p = p->lchild;
} else {
GetTop(S, p);
if (p->rchild && p->rchild!=r) {
p = p->rchild;
Push(S, p);
p = p->lchild;
} else {
Pop(S, p);
visit(p->data);
r = p; // 记录最近访问过的结点
p = NULL; // 结点访问完后,重置p指针
}
}
}
}
注:每次出栈访问完一个结点就相当于遍历完以该结点为根的子树,需将p置NULL。
层次遍历
算法思想:从根结点开始,将结点入队,然后出队访问并将其左右子树入队。
void LevelOrder(BiTree T) {
SqQueue Q;
InitQueue(Q);
BiTree p;
EnQueue(Q, T);
while (!IsEmpty(Q)) {
DeQueue(Q, p);
visit(p);
if (p->lchild != NULL)
EnQueue(Q, p->lchild);
if (p->rchild != NULL)
EnQueue(Q, p->rchild);
}
}
参考文章:《王道数据结构(2021)》