介绍
给定一个N个节点的二叉树,完成前、中、后序遍历,要求时间复杂度为O(N),额外空间复杂度为O(1)
相关阅读
Morris遍历过程
(1)如果当前节点的左子树为空,则当前节点向右移动
(2)如果当前节点的左子树不为空,则找到左子树上最右的节点
a.如果最右节点的右孩子为空,则将最右节点的右孩子指向当前节点,当前节点向左移动
b.如果最后节点的右孩子指向当前节点,则将最右节点的右孩子指向空,当前节点向右移动
Morris遍历代码
void morris(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
}
}
cur = cur->right;
}
}
Morris前中、后、序遍历
Morris遍历整个过程最多到达一个节点两次,前中序遍历只是输出的时机不同
前序遍历
第一次到达该节点就输出
void morrisPre(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cout << cur->data;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
}
}else{
cout << cur->data;
}
cur = cur->right;
}
cout << endl;
}
中序遍历
第二次到达该节点就输出
void morrisIn(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
}
}
cout << cur->data;
cur = cur->right;
}
cout << endl;
}
后序遍历
由于后序遍历的输出时机是第三次到达一个节点,但是Morris遍历最多只能到达一个节点两次,因此需要特殊处理。
对于可以到达两次的节点,在第二次到达时逆序输出该节点的左子树的右边界。
最后输出整棵树的右边界即可。
对于逆序输出,由于额外空间的限制我们需要进行类似于单链表反转的操作。
反转代码
Node* reverseEdge(Node *node){
Node *pre = NULL;
Node *next = NULL;
while(node != NULL){
next = node->right;
node->right = pre;
pre = node;
node = next;
}
return pre;
}
后序遍历代码
void morrisPos(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
printRight(cur->left);
}
}
cur = cur->right;
}
printRight(head);
cout << endl;
}
完整代码
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
typedef struct Node{
char data;
Node *left;
Node *right;
Node(char c): data(c), left(NULL), right(NULL){}
}Node;
Node* reverseEdge(Node *node){
Node *pre = NULL;
Node *next = NULL;
while(node != NULL){
next = node->right;
node->right = pre;
pre = node;
node = next;
}
return pre;
}
void printRight(Node *node){
Node *tail = reverseEdge(node);
Node *cur = tail;
while(cur != NULL){
cout << cur->data;
cur = cur->right;
}
reverseEdge(tail);
}
void morris(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
}
}
cur = cur->right;
}
}
void morrisPre(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cout << cur->data;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
}
}else{
cout << cur->data;
}
cur = cur->right;
}
cout << endl;
}
void morrisIn(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
}
}
cout << cur->data;
cur = cur->right;
}
cout << endl;
}
void morrisPos(Node *head){
Node *cur = head;
Node *mostRight = NULL;
while(cur != NULL){
mostRight = cur->left;
if(mostRight != NULL){
while(mostRight->right != NULL && mostRight->right != cur){
mostRight = mostRight->right;
}
if(mostRight->right == NULL){
mostRight->right = cur;
cur = cur->left;
continue;
}else if(mostRight->right == cur){
mostRight->right = NULL;
printRight(cur->left);
}
}
cur = cur->right;
}
printRight(head);
cout << endl;
}
void createBTree(Node* &node){
char c;
cin >> c;
if(c == '#'){
node = NULL;
}else{
node = new Node(c);
createBTree(node->left);
createBTree(node->right);
}
}
//abd##fe###cg#h##i##
int main()
{
Node *BTree;
createBTree(BTree);
morrisPre(BTree);
morrisPos(BTree);
morrisIn(BTree);
return 0;
}