# Morris, recursive binary tree before, during and after traversal

Experiment time: 11.10

catalogue

Generating complete binary tree

Implementation of Morris algorithm

Introduction to morris traversal

Implementation principle of morris traversal

The essence of morris traversal

Briefly describe the algorithm process

Recursive implementation

Experimental results (including time, space and output results):

source code

# Generating complete binary tree

Just use queue generation.

```//Using queues, a complete binary tree is generated
void CreateTreeNode(TreeNode *root, int Num) {
queue<TreeNode *> Q;
Q.push(root);//Root node join
int data = 1;//The value of the root is 1
while (data < Num) {
TreeNode *curr_node = Q.front();//Take the first element of the team
Q.pop();//Team first team
curr_node->left = new TreeNode;
curr_node->left->val = data++;
Q.push(curr_node->left);//Left subtree at the end of the team

curr_node->right = new TreeNode;
curr_node->right->val = data++;
Q.push(curr_node->right);//Right subtree at the end of the team
}
}```

# Implementation of Morris algorithm

Reference here Divine traversal - morris - Zhihu (zhihu.com)

## Introduction to morris traversal

morris traversal is a super advanced algorithm of binary tree traversal algorithm, which follows the spatial complexity of recursive and non recursive (stack implementation). morris traversal can reduce the spatial complexity of non recursive traversal to O(1). Thus, a sophisticated algorithm with time complexity of O(N) and space complexity of O(1) is realized.
morris traversal uses that the left and right children of the leaf nodes of the tree are empty (a large number of free pointers of the tree), so as to reduce the space overhead to the limit.

## Implementation principle of morris traversal

Record the current node as cur.

1. If cur has no left child, cur moves to the right (cur=cur.right)
2. If cur has left children, find the rightmost node on cur's left subtree and record it as most right
1. If the right pointer of mostright points to null, let it point to cur, and cur moves to the left (cur=cur.left)
2. If the right pointer of mostright points to cur, let it point to null, and cur moves to the right (cur=cur.right)

Implement the above principles, that is, morris traversal.

## The essence of morris traversal

Establish a mechanism for Nodes without a left subtree arrive only once, and nodes with a left subtree arrive twice

## Briefly describe the algorithm process

Cur is the current node, and next is used for the rightmost node in the left subtree of cur

while (cur is not empty)

If cur - > left is empty

Output cur - > val

Cur points to cur - > right

else

next points to cur - > left

Wihile next - > right is not null and not equal to cur

Next points to next - > right

If next - > right is empty, it indicates that the node is reached for the first time

Next - > right points to cur

If the preamble traverses, the value of cur is output here

else indicates the second arrival at the node

Next - > right is set to NULL

If it is traversed in middle order, the value of cur is output here

After traversal, all the nodes in the rightmost column of cur - > left can be output

Cur points to cur - > right

For post order traversal, you also need to output all the nodes in the rightmost column of the root node head

```//Output the nodes in the rightmost column of temp in reverse order
void ReverserPrint(TreeNode *temp) {
stack<int> tempList;
while (temp) {//Put all the right child nodes of the current node into the stack
tempList.push(temp->val);
temp = temp->right;
}

while (!tempList.empty()) {//Output stack elements
cout << setw(4) << tempList.top();
tempList.pop();
}
}

//Traversal binary tree implemented by Morris
//flag 1 2 3 corresponds to the first order, middle order and last order traversal
void MorrisTraversal(TreeNode *head, const int &flag) {
//next is used to find the rightmost node of the cur left subtree of the current node
TreeNode *next = NULL, *cur = head;

//Until the node is empty
while (cur) {
//Judge whether the left subtree of the current node is empty. If it is empty, the current node will be output
if (!cur->left) {
if (flag != 3) {
cout << setw(4) << cur->val;
}
cur = cur->right;//The current node cur points to the right subtree
} else {//The left subtree of the current node is not empty
//Find the rightmost node of the left subtree and point to the current node cur
next = cur->left;
while (next->right && next->right != cur) {//If the node is empty or cur, the loop ends
next = next->right;
}

//The first arrival is null, pointing to cur
if (!next->right) {
if (flag == 1) {//Preorder traversal
cout << setw(4) << cur->val;
}

next->right = cur;//cur pointing to current node
cur = cur->left;//Point to right subtree
} else {//Second arrival, recovery
next->right = NULL;//Leave blank

if (flag == 2) {//Medium order traversal
cout << setw(4) << cur->val;
}
if (flag == 3) {//In subsequent traversal, the rightmost column of cur - > left is output in reverse order
ReverserPrint(cur->left);
}

cur = cur->right;//Point to right subtree
}
}
}
if (flag == 3) {//Output the rightmost column of the last head node
}
}```

# Recursive implementation

```//Traversal of recursive implementation
//flag 1 2 3 corresponds to the first order, middle order and last order traversal
void RecursiveTraversal(TreeNode *Node, const int &flag) {
if (Node != NULL) {
if (flag == 1) {
cout << setw(4) << Node->val;
}
RecursiveTraversal(Node->left, flag);
if (flag == 2) {
cout << setw(4) << Node->val;
}
RecursiveTraversal(Node->right, flag);
if (flag == 3) {
cout << setw(4) << Node->val;
}
}
}```

# Experimental results (including time, space and output results): # source code

```#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<iomanip>
using namespace std;

struct TreeNode {
int val = 0;
TreeNode *left = NULL;
TreeNode *right = NULL;
};

//Using queues, a complete binary tree is generated
void CreateTreeNode(TreeNode *root, int Num) {
queue<TreeNode *> Q;
Q.push(root);//Root node join
int data = 1;//The value of the root is 1
while (data < Num) {
TreeNode *curr_node = Q.front();//Take the first element of the team
Q.pop();//Team first team
curr_node->left = new TreeNode;
curr_node->left->val = data++;
Q.push(curr_node->left);//Left subtree at the end of the team

curr_node->right = new TreeNode;
curr_node->right->val = data++;
Q.push(curr_node->right);//Right subtree at the end of the team
}
}

//Using the queue, the binary tree is traversed hierarchically
void LevelOrderTraversal(TreeNode *root) {
queue<TreeNode *> Q;
Q.push(root);//Root node queue
while (!Q.empty()) {//If the queue is not empty, it will be traversed all the time
TreeNode *curr_node = Q.front();//Take the first element of the team
cout<< setw(4) << curr_node->val;//Outputs the value of the current element
Q.pop();//Team first team
if (curr_node->left) {//Left subtree is not empty
Q.push(curr_node->left);//Left subtree at the end of the team
}

if (curr_node->right) {//ditto
Q.push(curr_node->right);
}
}
}

//Traversal of recursive implementation
//flag 1 2 3 corresponds to the first order, middle order and last order traversal
void RecursiveTraversal(TreeNode *Node, const int &flag) {
if (Node != NULL) {
if (flag == 1) {
cout << setw(4) << Node->val;
}
RecursiveTraversal(Node->left, flag);
if (flag == 2) {
cout << setw(4) << Node->val;
}
RecursiveTraversal(Node->right, flag);
if (flag == 3) {
cout << setw(4) << Node->val;
}
}
}

//Output the nodes in the rightmost column of temp in reverse order
void ReverserPrint(TreeNode *temp) {
stack<int> tempList;
while (temp) {//Put all the right child nodes of the current node into the stack
tempList.push(temp->val);
temp = temp->right;
}

while (!tempList.empty()) {//Output stack elements
cout << setw(4) << tempList.top();
tempList.pop();
}
}

//Traversal binary tree implemented by Morris
//flag 1 2 3 corresponds to the first order, middle order and last order traversal
void MorrisTraversal(TreeNode *head, const int &flag) {
//next is used to find the rightmost node of the cur left subtree of the current node
TreeNode *next = NULL, *cur = head;

//Until the node is empty
while (cur) {
//Judge whether the left subtree of the current node is empty. If it is empty, the current node will be output
if (!cur->left) {
if (flag != 3) {
cout << setw(4) << cur->val;
}
cur = cur->right;//The current node cur points to the right subtree
} else {//The left subtree of the current node is not empty
//Find the rightmost node of the left subtree and point to the current node cur
next = cur->left;
while (next->right && next->right != cur) {//If the node is empty or cur, the loop ends
next = next->right;
}

//The first arrival is null, pointing to cur
if (!next->right) {
if (flag == 1) {//Preorder traversal
cout << setw(4) << cur->val;
}

next->right = cur;//cur pointing to current node
cur = cur->left;//Point to right subtree
} else {//Second arrival, recovery
next->right = NULL;//Leave blank

if (flag == 2) {//Medium order traversal
cout << setw(4) << cur->val;
}
if (flag == 3) {//In subsequent traversal, the rightmost column of cur - > left is output in reverse order
ReverserPrint(cur->left);
}

cur = cur->right;//Point to right subtree
}
}
}
if (flag == 3) {//Output the rightmost column of the last head node
}
}

// All code needs to be written in the Algo class to define other required variables or functions
class Algo {
public:
Algo() {
cout << "algo ok" << endl;
}

cout << "Hierarchical traversal implementation:\t";

for (auto i = 1; i <= 3; ++i) {
if (i == 1) {
cout <<"\n\n Preorder traversal \nMorris realization:\t";
cout << "\n Recursive implementation:\t";
} else if (i == 2) {
cout  << "Medium order traversal\nMorris realization:\t";
cout  << "\n Recursive implementation:\t";
} else if (i == 3) {
cout << "Postorder traversal\nMorris realization:\t";
cout<< "\n Recursive implementation:\t";
}
cout << "\n\n";
}
return 0; //Modify to return the correct result
}
};

int main() {
Algo algo;