问题描述
使用morris遍历树,生成
先序
、中序
、后序
遍历结点;
1) cur先来到头节点;
2) 若cur没有左孩子,cur向右移动;
3) 若cur有左孩子,找到左树上最右的结点mostRight;
a. 若mR的右指针为空,则让其指向cur,在将cur向左移动;
b. 若mR的右指针指向cur,让其指向null,在将cur右移;
4) cur为空时停止;
【先序】:遍历中只出现一次的节点,直接打印,出现两次的,第一次打印;
【中序】:遍历中只出现一次的节点,直接打印,出现两次的,第二次打印;
【后序】:出现两次的结点,第二次回到自己的时候逆序打印左树的右边界,最后在单独逆序打印整棵树的右边界;
解析
代码
/*----------------------------------------------------------------------
> File Name: morrisDemo.cpp
> Author: Jxiepc
> Mail: Jxiepc
> Created Time: Mon 14 Mar 2022 10:00:38 AM CST
----------------------------------------------------------------------*/
/**
* 时间复杂度O(N),额外空间复杂度O(1)
* > 1) cur先来到头节点
* > 2) 若cur没有左孩子,cur向右移动
* > 3) 若cur有左孩子,找到左树上最右的结点mostRight
* a. 若mR的右指针为空,则让其指向cur,在将cur向左移动
* b. 若mR的右指针指向cur,让其指向null,在将cur右移
* > 4) cur为空时停止
* */
/** 树结构 */
struct node {
int val;
struct node* left;
struct node* right;
};
typedef struct node Node;
/** 先序遍历 */
void Premorris(Node *head) {
if(head == nullptr)
return;
Node *cur = head;
Node *mostRight = nullptr;
/* 结点不为空 */
while(cur != nullptr) {
/* cur的左孩子 */
mostRight = cur->left;
/* 左孩子的最右结点 */
if(mostRight != nullptr) {
while(mostRight->right != nullptr && mostRight->right != cur) {
mostRight = mostRight->right;
}
/* 最右结点的右指针是否为空 */
if(mostRight->right == nullptr) {
std::cout << cur->val << " ";
mostRight->right = cur;
cur = cur->left;
continue;
}else {
mostRight->right = nullptr;
}
}else {
std::cout << cur->val << " ";
}
/* 若没有左孩子和mR的右指针指向cur */
cur = cur->right;
}
}
/** 中序遍历 */
void Midmorris(Node *head) {
if(head == nullptr)
return;
Node *cur = head;
Node *mostRight = nullptr;
/* 结点不为空 */
while(cur != nullptr) {
/* cur的左孩子 */
mostRight = cur->left;
/* 左孩子的最右结点 */
if(mostRight != nullptr) {
while(mostRight->right != nullptr && mostRight->right != cur) {
mostRight = mostRight->right;
}
/* 最右结点的右指针是否为空 */
if(mostRight->right == nullptr) {
mostRight->right = cur;
cur = cur->left;
continue;
}else {
mostRight->right = nullptr;
}
}
std::cout << cur->val << " ";
/* 若没有左孩子和mR的右指针指向cur */
cur = cur->right;
}
}
Node* reverseEdge(Node *from) {
Node *pre = nullptr;
Node *next = nullptr;
while(from != nullptr) {
next = from->right;
from->right = pre;
pre = from;
from = next;
}
return pre;
}
void printEdge(Node *head) {
Node *tail = reverseEdge(head);
Node *cur = tail;
while(cur != nullptr) {
std::cout << cur->val << " ";
cur = cur->right;
}
reverseEdge(tail);
}
/** 后序遍历 */
void Backmorris(Node *head) {
if(head == nullptr)
return;
Node *cur = head;
Node *mostRight = nullptr;
/* 结点不为空 */
while(cur != nullptr) {
/* cur的左孩子 */
mostRight = cur->left;
/* 左孩子的最右结点 */
if(mostRight != nullptr) {
while(mostRight->right != nullptr && mostRight->right != cur) {
mostRight = mostRight->right;
}
/* 最右结点的右指针是否为空 */
if(mostRight->right == nullptr) {
//std::cout << cur->val << " ";
mostRight->right = cur;
cur = cur->left;
continue;
}else {
mostRight->right = nullptr;
printEdge(cur->left);
}
}
/* 若没有左孩子和mR的右指针指向cur */
cur = cur->right;
}
printEdge(head);
}
int main(int argc, char* argv[])
{
Node n1= {1, nullptr, nullptr};
Node n2= {2, nullptr, nullptr};
Node n3= {3, nullptr, nullptr};
Node n4= {4, nullptr, nullptr};
Node n5= {5, nullptr, nullptr};
Node n6= {6, nullptr, nullptr};
Node n7= {7, nullptr, nullptr};
n1.left = &n2;
n1.right = &n3;
n2.left = &n4;
n2.right = &n5;
n3.left = &n6;
n3.right = &n7;
std::cout << "pre: ";
Premorris(&n1);
std::cout << std::endl;
std::cout << "mid: ";
Midmorris(&n1);
std::cout << std::endl;
std::cout << "back: ";
Backmorris(&n1);
std::cout << std::endl;
return 0;
}
复杂度
时间复杂度
O(N)
,额外空间复杂度O(1)
;