二叉树的非递归遍历

来源:互联网 发布:炒股软件官方下载 编辑:程序博客网 时间:2024/05/17 07:46

二叉树的非递归遍历


说明:非递归的三种遍历都要借助来实现。先序、中序写法类似也较易实现,后序稍难。


树结点结构:

struct BinTree{BinTree* lchild,*rchild;int val;}


一、先序遍历(树根->左子树->右子树)

思路:

1.从当前树根结点开始,一直向左走,挨个入栈并访问,走到尽头(为NULL的结点);

2.栈顶结点出栈,将p的右孩子赋给p(p=p->rchild),此时p为当前树根,重复1;

3.直到栈空。


代码如下:

void preOrder(BinTree *root){stack<BinTree *> s;BinTree *p = root;while (p || !s.empty()){while (p)  // 1{printf("%d ", p->val);s.push(p);p = p->lchild;}if (!s.empty())  // 2{p = s.top();s.pop();p = p->rchild;}}}


二、中序遍历(左子树->树根->右子树)


思路:

1.从当前树根结点开始,一直向左走,挨个入栈(这里先不访问),走到尽头(为NULL的结点);

2.栈顶结点出栈并访问将p的右孩子赋给p(p=p->rchild),此时p为当前树根,重复1;

3.直到栈空。


代码如下:

void inOrder(BinTree *root){stack<BinTree *> s;BinTree *p = root;while (p || !s.empty()){while (p)  // 1{s.push(p);p = p->lchild;}if (!s.empty())  // 2{p = s.top();printf("%d ", p->val);s.pop();p = p->rchild;}}}


由前序遍历与中序遍历代码可以看出,中序遍历与前序遍历只是访问结点的时机不同,

前序遍历在结点入栈时访问,后序遍历在结点出栈时访问。



三、后序遍历(左子树->右子树->树根)

思路1:需要加入标志(创建另一种结点结构,加入isFirst标志),当结点第2次出现在栈顶时访问(这种方法与上面两种遍历代码也有许多相似之处,比较好记)。

1.从当前树根结点开始,一直向左走,挨个(转化成Node结点)入栈(这里先不访问)并标记为第1次出现,走到尽头(为NULL的结点);

2.栈顶结点p出栈,如果:

  1)结点为第1次出现在栈顶(不包括入栈时),结点p(转化Node结点)再入栈并标记为第2次,此时p为当前树根,重复1;

  2)结点为第2次出现在栈顶(不包括入栈时),访问该结点,重复2。

3.直到栈空。


struct Node{    BinTree *binTree;    bool isFirst;};


代码如下:

void postOrder(BinTree *root){stack<Node *> s;BinTree *p = root;Node *tmp;while (p || !s.empty()){while (p)  // 1{Node *node = (Node *)malloc(sizeof(Node));node->binTree = p;node->isFirst=true;s.push(node);p = p->lchild;}if (!s.empty()){tmp = s.top();s.pop();if (tmp->isFirst)  // 2 1){tmp->isFirst = false;s.push(tmp);p = tmp->binTree->rchild;}else  // 2 2){printf("%d ", tmp->binTree->val);p = NULL;}}}}



思路2:

1.根结点入栈;

2.取栈顶结点cur,判断:

  1)cur无孩子结点,或其孩子结点已经被访问,则访问cur结点;

  2)cur有孩子结点,cur的(如果有)右孩子入栈,再cur的(如果有)左孩子入栈(注意顺序)。

3.直到栈空。


代码如下:

void postOrder2(BinTree *root){stack<BinTree *> s;BinTree *cur;BinTree *pre = NULL;s.push(root);  // 1while (!s.empty()){cur = s.top();if ((NULL == cur->lchild && NULL == cur->rchild) ||(NULL != pre && (pre == cur->lchild || pre == cur->rchild)))  // 2 1){printf("%d ", cur->val);s.pop();}else  // 2 2){if (cur->rchild) s.push(cur->rchild);if (cur->lchild) s.push(cur->lchild);}}}



0 0
原创粉丝点击