Binary Search Trees各种迭代遍历总结(C language)

写在前面:第一次写博。此文是自己对于BST的各种递归遍历的理解。包括思路比较简单的层序和前序,以及不太容易想的中序和后序。

LevelOrder:

void levelOrderTraversal(BSTNode* root)

{

    Queue q;

    q.tail = q.head =NULL;

    BSTNode *temp = root;

    if(temp==NULL)

        return;

    enqueue(&q.head,&q.tail,temp);

    while(!isEmpty(q.head))

    {

        temp=dequeue(&q.head,&q.tail);

        printf("%d ",temp->item);

        if(temp->left)

            enqueue(&q.head,&q.tail,temp->left);

        if(temp->right)

            enqueue(&q.head,&q.tail,temp->right);

    }

}

void preOrderIterative(BSTNode *root)

{

    Stack s;

    s.top =NULL;

    BSTNode*temp = root;

    if(root==NULL)

        return;

    push(&s,temp);

    while(!isEmpty(&s))

    {

        temp = pop(&s);

        printf("%d ", temp->item);

        if(temp->right!=NULL)

            push(&s,temp->right);

        if(temp->left!=NULL)

            push(&s,temp->left);

    }

}

Level-order, pre-order

相同:都是:先访问根,再访问子树。

不同:preorder用stack, levelorder用queue. 

Stack:LIFO, 起到的效果是:可以依次向左访问,先根不断向左,在向左的过程中,先访问根,再访问左子树。

再右子树不断向左遍历。此时右子树起到根的效果,在向左的过程中,先访问右子树,再访问右子树的左子树,最后访问右子树本身。

注意⚠️:压入过程中需先压右再压左。

Queue:FIFO,起到的效果:可以依次按层压入再输出,先压左再压右。再输出过程中,因为是FIFO,所以访问并出队的依次是根的直接左和右,达到左右兼顾的效果。

Inorder: 

void inOrderTraversal(BSTNode *root)

{

    BSTNode*temp = root;

    Stack s;

    s.top =NULL;

    if(root==NULL)

        return;

    while(1)

    {

        if(temp!=NULL)

        {

            push(&s, temp);

            temp = temp->left;

        }

        else

        {

            if(!isEmpty(&s))

            {

                temp = pop(&s);

                printf("%d ",temp->item);

                temp = temp->right;

            }

            else

                break;

        }

    }

}

Inorder: 每个节点的左子女都后被压入栈,依次每个节点的左子女都先出栈,先被处理;每个节点都先处理自己再将右节点压入栈。—保证了左中右的顺序。

循环维持条件:cur不为空或stack不为空:这保证了还有未处理的节点。

从上往下遍历:先处理左再处理根;从下往上:子女OK,可以处理根了。

void postOrderIterativeS1(BSTNode *root)

{

    Stack s;

    s.top =NULL;

    BSTNode*temp=root;

    do {

        while (temp) {

            if (temp->right)如果根有右子树

        {   

            push(&s, temp->right);压入右

            push(&s, temp);压入根

            temp = temp->left;往左走

        }

        temp = pop(&s);如果已经走的左尽头

       看有无右

       有右:把右弹出,把根本身压入,去找右的左

        if (temp->right && peek(&s) == temp->right) {

            pop(&s);

            push(&s, temp);

            temp = temp->right;

        } 

       没有右就直接打印

       else 

        {

            printf("%d ", temp->item);

            temp =NULL;

        }

    }while(!isEmpty(&s));

}

用一个栈:

向左走,过程中,先把根压入,再吧右压入。

到最走边后,再去遍历最左边的右。

void postOrderIterativeS2(BSTNode *root)

{

    BSTNode*temp = root;

    Stack s1,s2;

    s1.top = s2.top=NULL;

    push(&s1, temp);

    while(!isEmpty(&s1))

    {

        temp = pop(&s1);

        push(&s2, temp);

        if(temp->left!=NULL)

            push(&s1, temp->left);

        if(temp->right!=NULL)

            push(&s1, temp->right);

    }

    while(!isEmpty(&s2))

    {

        printf("%d ",pop(&s2)->item);

    }

}

用两个栈:

先把根压入栈底,再去遍历左右子女。

左先进栈1-右先进栈二-左先出栈二。

接下来到左的左先进栈1。

整体:

先让根进栈2,再让从浅到深的所有右都进栈2,最后左进栈。

从深到浅的左出,右出,根出。

Reverse的:

任何一颗树的根比右子树先进,右子树比左子树先进。

反过来:

任何一颗树的左子树比右子树先出,右子树比根先出。

你可能感兴趣的:(详解)