一、前序遍历
struct TreeNode{
int val;
TreeNode *leftChild;
TreeNode *rightChild;
}
//前序遍历 循环 根左右
void preVisitTree(TreeNode *rootNode) {
if(rootNode == NULL) {
return;
}
std::stack<TreeNode *> nodes;
TreeNode *tempNode = rootNode;
while(tempNode != NULL || !nodes.isEmpty()) {
while(tempNode != NULL) {
nodes.push(tempNode);
count<<tempNode->val<<" ";
tempNode = tempNode->leftChild;
}
if(!nodes.isEmpty()) {
tempNode = nodes.top();
nodes.pop();
tempNode = tempNode->rightChild;
}
}
}
//前序遍历 递归
void preVisitTreeRecursively(TreeNode *rootNode) {
if(rootNode == NULL) {
return;
}
cout<<rootNode->val<<" ";
preVisitTreeRecursively(rootNode->leftChild);
preVisitTreeRecursively(rootNode->rightChild);
}
二、中序遍历
//中序遍历 循环 左根右
void midVisitTree(TreeNode *rootNode) {
if(rootNode == NULL) {
return;
}
TreeNode *tempNode = rootNode;
while(tempNode != NULL || !nodes.isEmpty()) {
while(tempNode != NULL) {
nodes.push(tempNode);
tempNode = tempNode->leftChild;
}
if(!nodes.isEmpty()) {
tempNode = nodes.top();
nodes.pop();
count<<tempNode->val<<" ";
tempNode = tempNode->rightChild;
}
}
}
//中序遍历 递归
void midVisitTreeRecursively(TreeNode *rootNode) {
if(rootNode == NULL) {
return;
}
midVisitTreeRecursively(rootNode->leftChild);
cout<<rootNode->val<<" ";
midVisitTreeRecursively(rootNode->rightChild);
}
三、后序遍历
第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问, 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是 否是第一次出现在栈顶。
//后序遍历 循环 左右根
struct TreeNode {
int val;
TreeNode *leftChild;
TreeNode *rightChild;
bool isFirst; //是否第一次出现在栈顶
};
void postVisitTree(TreeNode *rootNode) {
if(rootNode == NULL) {
return;
}
std::stack<TreeNode *> nodes;
TreeNode *tempNode = rootNode;
while(tempNode != NULL || !nodes.isEmpty()) {
while(tempNode != NULL) {
tempNode->isFirst = true;
nodes.push(tempNode);
tempNode = tempNode->leftChild;
}
if(!nodes.isEmpty()) {
tempNode = nodes.top();
if(tempNode->isFirst) {
tempNode->isFirst = false;
tempNode = tempNode->rightChild;
} else {
count<<tempNode->val<<" ";
nodes.pop();
tempNode = NULL;
}
}
}
}
第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了 每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
void postVisitTree(TreeNode *rootNode) {
if(rootNode == NULL) {
return;
}
std::stack<TreeNode *> nodes;
nodes.push(rootNode);
TreeNode *curNode = rootNode;
TreeNode *preNode = NULL; //上次访问的节点
while(!nodes.isEmpty()) {
curNode = nodes.top();
if((curNode->leftChild == NULL && curNode->rightChild == NULL) ||
((preNode == curNode->leftChild || preNode == curNode->rightChild) && preNode != NULL)) {
cout<<curNode->val<<" ";
preNode = curNode;
nodes.pop();
} else {
if(curNode->rightChild != NULL) {
nodes.push(curNode->rightChild);
}
if(curNode->leftChild != NULL) {
nodes.push(curNode->leftChild);
}
}
}
}
递归
//后序遍历 递归
void postVisitTreeRecursively(TreeNode *rootNode) {
if(rootNode == NULL) {
return;
}
postVisitTreeRecursively(rootNode->leftChild);
postVisitTreeRecursively(rootNode->rightChild);
cout<<rootNode->val<<" ";
}
参考:https://blog.csdn.net/happyjacob/article/details/83116702