对于二叉树的遍历,先序的方式是比较简单的,但是中序和后序的方式还是有点麻烦的,这里先给出一个用C++stack的遍历方式:
1.如果当前结点不为空 把当前结点压入栈 p=p->left转向其左孩子 2.如果当前结点为空(证明这半棵子树已经遍历完成,需要从栈顶找到树根) 取栈顶元素为当前结点,栈做一次弹栈操作 访问当前结点 p=p->right转向其右孩子 3.重复1、2操作,直到栈为空并且当前结点为NULL,结束。
算法代码实现:
vector<int> inOrder(TreeNode *root) { vector<int> result; const TreeNode *cur; stack<const TreeNode*> s; cur = root; while(!s.empty() || cur != NULL) { if(cur != NULL) { s.push(cur); cur = cur->left; }//if else { cur = s.top(); s.pop(); result.push_back(cur->val); cur = cur->right; } }//while return result; }
这种利用栈的遍历方法很简单,在之前我也设计了一个自己的遍历的方法:
1.如果当前结点为空(NULL) 取栈顶元素为当前结点,栈做一次弹栈操作 访问当前结点 p=p->right转向其右孩子 2.如果当前结点不为空 如果当前结点有左孩子 把当前结点压入栈 p=p->left转向其左孩子 如果当前结点没有左孩子 访问当前结点 p=p->right转向其右孩子 3.重复1、2操作,直到栈为空并且当前结点为NULL,结束。
代码实现:
vector<int> inOrder(TreeNode *root) { const TreeNode* cur; stack<const TreeNode*> s; vector<int> result; cur = root; while(!s.empty() || cur != NULL) { if(cur == NULL) { cur = s.top(); s.pop(); result.push_back(cur->val); cur = cur->right; }//if else { if(cur->left != NULL) { s.push(cur); cur = cur->left; } else { result.push_back(cur->val); cur = cur->right; } }//else }//while return result; }
上面介绍了两种利用栈对树中序遍历的方法,下面还是说一下Morris的遍历方法
1.如果当前结点有左子树 找到左子树的最右叶子结点 如果最右叶子结点的右指针域为空(NULL) 使最右叶子结点的右指针域指向当前结点 p=p->left转向其左子树 如果最右叶子结点的右指针域已经指向了当前结点 访问当前结点 断开Morris链接 p=p->right转向其子树 2.如果当前结点没有左子树 访问当前结点 p=p->right转向其子树 3.重复1、2操作,直到当前结点为NULL,结束。
算法代码实现:
vector<int> InOrder(TreeNode *root) { TreeNode *cur = NULL; TreeNode *temp = NULL; cur = root; vector<int> result; while(cur != NULL) { if(cur->left != NULL) { temp = cur->left; while(temp->right != NULL && temp->right != cur) { temp = temp->right; } if(temp->right == NULL) { temp->right = cur; cur = cur->left; } else //temp->right == cur { result.push_back(cur->val); temp->right = NULL; cur = cur->right; } } else //没有左子树 { result.push_back(cur->val); cur = cur->right; } }//while return result; }