二叉链表的 遍历 是 二叉链表 各种 操作的 基础,例如 :创建 二叉树;求树的 长度;求树的 叶子节点数;求 节点的 层 数;求 树的 深度,宽度 等等。
总之 不掌握 遍历,就没有 掌握 二叉树;
二叉链表的 遍历 根据 根节点的访问顺序有:先(根节点)序,中(根节点)序,后(根节点)序, 和 层序;
算法思路 有两类:
1. 递归 算法,算法 清晰,容易 证明算法的正确性,但是 效率较低 和 受 系统 栈区 大小的限制,不能 递归太多层次
2.非 递归算法,算法 较复杂一些,但是效率高,又 不受 栈区大小的限制
下面 讲解 这两种 算法:
1.递归算法 ,递归没什么 说的,比较 简单
//递归算法 先序
void preOrderTraverse(Tree tree){
if (tree != NULL)
{
printf("%d\t",tree->data);
preOrderTraverse(tree->leftChild);
preOrderTraverse(tree->rightChild);
}
}
//递归算法 中序
void inOrderTraverse(Tree tree){
if (tree != NULL)
{
inOrderTraverse(tree->leftChild);
printf("%d\t",tree->data);
inOrderTraverse(tree->rightChild);
}
}
//递归算法 后序
void postOrderTraverse(Tree tree){
if (tree != NULL)
{
postOrderTraverse(tree->leftChild);
postOrderTraverse(tree->rightChild);
printf("%d\t",tree->data);
}
}
2.1 非递归 先序 算法 总共 有 三种 方法:
下面 的两种算法 思路一致,都是 找左子树最左下角节点的同时访问节点,然后 将 节点的 右子树入栈。然后 重复寻找..
void preOrderTraverse1(Tree t){
linkStack stack;
stackInit(&stack);
stackPush(&stack,t);
while (!stackEmpty(stack))
{
while (stackGetTop(stack,&t) && t)
{
printf("%d\t",t->data);
stackPush(&stack,t->leftChild);
}
stackPop(&stack,&t);//NULL 出栈
if (!stackEmpty(stack))
{
stackPop(&stack,&t);
stackPush(&stack,t->rightChild);
}
}
stackDestory(&stack);
}
void preOrderTraverse2(Tree tree){
linkStack stack;
stackInit(&stack);
while (tree || !stackEmpty(stack))
{
if (tree)
{
printf("%d\t",tree->data);
stackPush(&stack,tree);
tree = tree->leftChild;
}
else
{
stackPop(&stack,&tree);
tree = tree->rightChild;
}
}
stackDestory(&stack);
}
第三种 思路 较 前两种 清晰,更加 易懂
1.空树 不操作 2.将 树根入栈 3.访问 根 节点 ,将根节点出栈 4. 右子树不为空,将 右子树 入栈 5. 左子树 不为空,将左子树入栈 6.重复 3~ 5 步
比较 奇思妙想的是 先 将 右子树