迭代优化的思路:
在后序遍历中,我们会先从左向右依次后序遍历每个子节点为根的子树,再遍历根节点本身。此时利用栈先进后出的原理,依次从右向左将子节点入栈,这样出栈的时候即可保证从左向右依次遍历每个子树。
参考方法二的原理,可以提前将后续需要访问的节点压入栈中。首先把根节点入栈,因为根节点是前序遍历中的第一个节点。随后每次我们找到栈顶节点 u ,如果当前节点的子节点没有遍历过,则应该先把 u 的所有子节点从右向左逆序压入栈中,这样出栈的节点则是顺序从左向右的,同时对节点 u 进行标记,表示该节点的子节点已经全部入栈;
如果当前节点 u 为叶子节点或者当前节点的子节点已经全部遍历过,则从栈中弹出节点 u ,并记录节点 u 的值。例如 u 的子节点从左到右为 v1 , v2 , v3 ,那么入栈的顺序应当为 v3, v2 , v1,这样就保证了下一个遍历到的节点(即 u 的左侧第一个孩子节点 v1 )出现在栈顶的位置。此时,访问第一个子节点 v1 时,仍然按照此方法则会先访问 v1 的左侧第一个孩子节点。
代码
Java
class Solution {
public List<Integer> postorder(Node root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Deque<Node> stack = new ArrayDeque<Node>();
Set<Node> visited = new HashSet<Node>();
stack.push(root);
while (!stack.isEmpty()) {
Node node = stack.peek();
/* 如果当前节点为叶子节点或者当前节点的子节点已经遍历过 */
if (node.children.size() == 0 || visited.contains(node)) {
stack.pop();
res.add(node.val);
continue;
}
for (int i = node.children.size() - 1; i >= 0; --i) {
stack.push(node.children.get(i));
}
visited.add(node);
}
return res;
}
}
C++
class Solution {
public:
vector<int> postorder(Node* root) {
vector<int> res;
if (root == nullptr) {
return res;
}
stack<Node *> st;
unordered_set<Node *> visited;
st.emplace(root);
while (!st.empty()) {
Node * node = st.top();
/* 如果当前节点为叶子节点或者当前节点的子节点已经遍历过 */
if (node->children.size() == 0 || visited.count(node)) {
res.emplace_back(node->val);
st.pop();
continue;
}
for (auto it = node->children.rbegin(); it != node->children.rend(); it++) {
st.emplace(*it);
}
visited.emplace(node);
}
return res;
}
};
C#
public class Solution {
public IList<int> Postorder(Node root) {
IList<int> res = new List<int>();
if (root == null) {
return res;
}
Stack<Node> stack = new Stack<Node>();
ISet<Node> visited = new HashSet<Node>();
stack.Push(root);
while (stack.Count > 0) {
Node node = stack.Peek();
/* 如果当前节点为叶子节点或者当前节点的子节点已经遍历过 */
if (node.children.Count == 0 || visited.Contains(node)) {
stack.Pop();
res.Add(node.val);
continue;
}
for (int i = node.children.Count - 1; i >= 0; i--) {
stack.Push(node.children[i]);
}
visited.Add(node);
}
return res;
}
}
C
#define MAX_NODE_SIZE 10000
typedef struct {
void * key;
UT_hash_handle hh;
} HashItem;
void freeHash(HashItem ** obj) {
HashItem * curr = NULL, * next = NULL;
HASH_ITER(hh, *obj, curr, next) {
HASH_DEL(*obj, curr);
free(curr);
}
}
int* postorder(struct Node* root, int* returnSize) {
if (NULL == root) {
*returnSize = 0;
return NULL;
}
int * res = (int *)malloc(sizeof(int) * MAX_NODE_SIZE);
struct Node ** stack = (struct Node **)malloc(sizeof(struct Node *) * MAX_NODE_SIZE);
int pos = 0, top = 0;
stack[top++] = root;
HashItem * visited = NULL;
HashItem * pEntry = NULL;
while (top != 0) {
struct Node * node = stack[top - 1];
pEntry = NULL;
HASH_FIND_PTR(visited, &node, pEntry);
/* 如果当前节点为叶子节点或者当前节点的子节点已经遍历过 */
if (node->numChildren == 0 || NULL != pEntry) {
res[pos++] = node->val;
top--;
continue;
}
for (int i = node->numChildren - 1; i >= 0; i--) {
stack[top++] = node->children[i];
}
pEntry = (HashItem *)malloc(sizeof(HashItem));
pEntry->key = node;
HASH_ADD_PTR(visited, key, pEntry);
}
free(stack);
*returnSize = pos;
return res;
}
好了,今天的文章分享就到这里了,希望对大家的学习有帮助哦!