Morris in-order traversal (c++ implementation)

1. In-order traversal

Binary tree middle-order traversal is to traverse the left subtree first , then traverse itself , and finally traverse the right subtree to form a left root right form. The recursive method is very simple as follows:

void dfs(root){
    
    
	if(!root)
		return;
	dfs(root->left);	// 先递归左子树
	cout<<root->val<<",";	//再对根节点操作
	dfs(root->right);	// 最后递归右子树
}

2. Morris ideas:

1. For a root node root, find the last element pre traversed in the left subtree, and assign pre->right = root (so that after traversing the left subtree again, you can traverse the root node root).
2. Each node can be the root node. After the first step is executed, set root = root -> left, and then repeat the first step until there is no left child node, you can operate on root.
3. When there is no left child, traverse the right child node, root = root ->right, and then continue to the first step.
The basic code framework is as follows:

	while (root) {
    
    
		if (!root->left) {
    
    
			// 对 root进行操作(访问完左孩子就访问根节点)
			root = root->right; //(再访问右孩子)
			continue;
		}
		pre = root->left;
		while (pre->right && pre->right != root) {
    
    
			pre = pre->right;	// 获取 root->left 最右孩子节点,也就是中序遍历的最后一个节点
		}
		if (!pre->right) {
    
    	// 为空说明是第一次访问该节点,
			pre->right = root;	//赋值前缀
			root = root->left;	//获取下一个要遍历的节点
		}
		else {
    
    		// 前缀不为空,说明 该root的左孩子树已经走过了
			pre->right = nullptr;	// 恢复之前状态
			// 对 root进行操作
			root = root->right;		// 开始遍历 root->right 的节点
		}
	}

As shown:

Insert picture description here
Demonstration steps (ABCDEF below refers to the nodes in the above figure):

  1. root = A, pre = A->left = B, and then use the following code to get the prefix of A (the last value of the in-order traversal of the left child tree):
	pre = root->left;	//初始赋值
	while (pre->right && pre->right != root) {
    
    
		pre = pre->right;
	}
	pre->right = root;
	root = root->left;		// 寻找下一个左孩子树根节点

The final pre = E, and the assignment pre->right = A (E->right = A), that is to say, the node after the in-order traversal of E is A.

2. After executing the above code, root = B, and then repeat step 1:
pre = D, pre->right = B, (because D has no right child node, so after the final traversal of D, return to traverse B)
root = B -> left = D
3. D = the root, no left child node D, in accordance with the left and right root of the traversal of the root node D operation, and then returns to traverse D-> right (step two: D-> right = B) , The code snippet is as follows:

 if (!root->left) {
    
    
	// 对 root进行操作
	root = root->right;
	continue;
  }
  1. root = B, pre = B->left = D;
    This step is the same as the second step, but because D->right = B (the second step is assigned), there is an extra judgment pre- in the loop code of step 1 > right = root;! prevent the cycle of death;
    but also the difference between the second step when the D-> right == nullptr, so we can judge, root-> left (D) have already visited, and in accordance with the left and right root traversal Method, operate on root node B , and then return to traverse B->right(E), as follows:
		if(pre->right){
    
    
			pre->right = nullptr;
			// 对 root进行操作
			root = root->right;
		}

5.root = E; repeat the previous 4 steps. .

3. Subject realization:

Print a binary search tree, the order of printing is ascending, the code is as follows:

#include<iostream>
// 二叉树结构
struct TreeNode {
    
    
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int v) :val(v), left(NULL), right(NULL) {
    
    };
	TreeNode(int v, TreeNode * l, TreeNode * r) :val(v), left(l), right(r) {
    
    };
};
//构建二叉树:
TreeNode* arrayToTreeNode(vector<int> &arr, int index)
{
    
    
	if (arr.size() <= index || arr[index] == INT_MIN) {
    
    
		return nullptr;
	}
	TreeNode * cur = new TreeNode(arr[index], arrayToTreeNode(arr, index * 2 + 1), arrayToTreeNode(arr, index * 2 + 2));
	return cur;
}

// 打印代码:
void printTree(TreeNode* root) {
    
    
	if (!root)
		return;
	TreeNode* pre;
	while (root) {
    
    
		if (!root->left) {
    
    
			cout<<root->val<<",";
			root = root->right;
			continue;
		}
		pre = root->left;
		while (pre->right && pre->right != root) {
    
    
			pre = pre->right;
		}
		if (!pre->right) {
    
    
			pre->right = root;
			root = root->left;
		}
		else {
    
    
			pre->right = nullptr;
			cout<<root->val<<",";
			root = root->right;
		}
	}
}
int main(){
    
    
	vector<int> arr = {
    
    4, 2, 6, 1, 3, 5, 7};
	TreeNode *root = arrayToTreeNode(arr, 0);
	printTree(root);
	return 0;
}

Four. End:

It’s the first time to write an explanation so carefully, and please give me a compliment. If you don’t understand, you can leave a message, I will reply when I see it.

Guess you like

Origin blog.csdn.net/h799710/article/details/108775882