Robson方法遍历二叉树

来源:互联网 发布:乐高电机有哪些端口 编辑:程序博客网 时间:2024/06/15 18:35

逆转链方法遍历二叉树:

在检测指针指向左子树或右子树遍历下去时,把原来的左子女指针或右子女指针逆转,记忆父节点。

在回溯时,再把指向父节点的指针逆转回来。

为了识别是从左子女翻上去还是从右子女翻上去的,需要为每个节点增加一个标志tag---在翻转左子女指针的时候tag = 1,在翻转右子女指针的时候tag = 0;

在退回到父节点后,若tag = 1,恢复左子女的指针指向,否则恢复右子女的指针的指向。

#include<iostream>using namespace std;#include"BinaryTree.h"template<class T>void Robson(BinTreeNode<T> *BT){    if(BT == NULL)return;    BinTreeNode<T> *p = BT,*q = NULL,*r = BT,*avail,*top = NULL;    do{        if(p->leftChild != NULL || p->rightChild != NULL){            if(p->leftChild != NULL){    //下降进入左子树                q = p->leftChild;p->leftChild = r;                r = p;p = q;            }            else{                q = p->rightChild;p->rightChild = r;                r = p;p = q;            }        }        else{            cout << p->data << endl;            avail = p;               //此叶节点可以用来存储栈元素            while(p != BT && (r != NULL && (r->rightChild == NULL || r->leftChild == NULL || (top != NULL && r == top->rightChild)))){      //连续上升,父节点的左指针或者右指针指向当前节点                                                                                                               // ,上升到父节点,若无指针指向当前节点,则取出栈顶元素,在判断指针时限判断是否不为空                if(r->rightChild == NULL){         //从左子树上升                    q = r->leftChild;r->leftChild = p;      //回复左子树指针的指向                    p = r; r = q;                }                if(r->leftChild == NULL){          //从右子树上升                    q = r->rightChild;r->rightChild = p;                    p = r; r = q;                }                if(r == top->rightChild){           //从右子树回溯,退栈,top的rightChild存储刚进栈的叶节点p的地址                    q = top; top = top->leftChild;  //top->leftChild是栈顶的下一个元素                    q->leftChild = q->rightChild = NULL;                    q = r->rightChild;        //q存储回溯之后的父节点                    r->rightChild = p;                    p = r;r = q;                }                cout << p->data << endl;            }            if(p != BT){      //从左子树退回并进入右子树                avail->leftChild = top;avail->rightChild = r;                top = avail;//当前节点进栈                q = r->rightChild; r->rightChild = r->leftChild;                r->leftChild = p; p = q;            }        }    }while(p != BT);}int main(){    BinaryTree<char> A;    Robson(A.getRoot());    return 0;}

Robson方法遍历二叉树的特点如下:

1)使用逆转链的思想

2)不适用tag标志,而是用内嵌的栈代替tag的作用。使用叶节点作为栈的结构,不另设存储空间。

3)利用栈解决在回溯时分辨究竟是从左子树还是右子树上升的问题


#include<iostream>using namespace std;#include"BinaryTree.h"template<class T>void Reverse_chain(BinTreeNode<T> *BT){    if(BT == NULL)return;    BinTreeNode<T> *p = BT,*q,*r = NULL;    do{        cout << p->data << endl;        if(p->leftChild != NULL || p->rightChild != NULL){            if(p->leftChild != NULL){     //逆转左子树                p->tag = 1;        //标志左子树                q = p->leftChild; p->leftChild = r;                r = p; p = q;            }            else{                q = p->rightChild; p->rightChild = r;                r = p; p = q;            }        }        else{            while(r != NULL && r->tag == 0 || r!=NULL && r->tag == 1 && r->rightChild == NULL){                if(r != NULL && r->tag == 0){           //从右子树上升                    q = r->rightChild;                    r->rightChild = p;         //恢复右子树                    p = r; r = q;                }                else{             //从左子树上升                    r->tag = 0;                    q = r->leftChild;                    r->leftChild = p;                    p = r; r = q;                }            }            if(r != NULL){                r->tag = 0;                q = r->rightChild;                r->rightChild = r->leftChild;     //逆转右子树                r->leftChild = p;      //恢复左子树                p = q;            }//从r的左子树上升进入右子树        }    }while(r != NULL);    //父节点为空则结束}int main(){    BinaryTree<char> A;    Reverse_chain(A.getRoot());    return 0;}


0 0
原创粉丝点击