Wrap print link
Zigzag print link
1. Print binary tree ideas (queue) from top to bottom
As shown in the figure above, the binary tree is printed from top to bottom as:
1 2 3 4 5
If the binary tree is not empty, we should first print node 1, then print 2 and 3 through the pointer of node 1, that is, scan the second layer, and finally print 4 and 5 through node 3. This is actually a breadth first traversal (dfs) of a binary tree
We want to save the 2 and 3 pointed to by node 1. Because the final printing needs to be from left to right, we choose the first in first out data structure of queue. The queue stores the pointer of the tree node, and its type is TreeNode*
After printing this node, queue the left and right subtrees pointed to by this node in the queue, and then point this node out of the queue.
Be sure to join the team when there are left and right subtrees.
operation | Values in the queue |
---|---|
Print 1 | Node 2, node 3 |
Print 2 | Node 3 |
Print 3 | Node 4, node 5 |
Print 4 | Node 5 |
Print 5 | empty |
C/C + + code
struct TreeNode { int m_nValue; TreeNode* m_pLeft; TreeNode* m_pRight; }; void UpDownPrintTree(TreeNode*TreeRoot) { if(TreeRoot==NULL) return; queue<TreeNode*>Tree; Tree.push(TreeRoot);//Queue the root node first while(Tree.empty()) { TreeNode* Node=Tree.front(); printf("%d",Node->m_nValue); Tree.pop(); if(Node->m_pLeft)//Join the team when there is a left subtree Tree.push(Node->m_pLeft); if(Node->m_pRight) Tree.push(Node->m_pRight); } }
2. Line feed printing binary tree
The idea of line feed printing is similar to that of the previous question, except that line feed is performed after one line is printed
As shown in the figure above, the line feed print result is
1
2 3
4 5
This time, you can choose to store the printing results in a two-dimensional array, or you can choose the printing method of the previous question.
The specific printing ideas are similar to those above.
Select two-dimensional array to return, and the array is stored in the form of one-dimensional array. Therefore, define a temporary one-dimensional array, put a row of data into the temporary one-dimensional array, and after printing the numbers of this row, give the array to the two-dimensional array to be returned in the form of tail interpolation. Then empty the temporary one-dimensional array and store the data of the second row.
Determine where to wrap lines:
In order to determine the position of line feed, we need to define two variables. One variable is that the current line has several nodes PreNum, and the other variable is that the next line has several nodes NexNum.
The initial value of PreNum is 1, because if the node is not empty, the node in the first row is the root node, and there must be only one node in a row. The initial value of NexNum is 0.
After the root node joins the queue, the left and right subtrees of the root node are joined to NexNum + + according to the pointer of the root node, and then the root node is dequeued from PreNum --
In this way, when the data of one row is out of the queue, NexNum is the number of nodes of the next row under the binary tree. When a row of data is out of the queue, PreNum is 0. At this time, PreNum=NexNum, NexNum=0. Start to count and process the next row of data.
eg:
operation | Queue data | PreNum | NexNum |
---|---|---|---|
Initial value 8 | 8 | 1 | 0 |
Out 8 in 6 in 10 | 6,10 | 0 | 2 |
Out 6 in 5 in 7 | 10,5,7 | 1 | 2 |
Out 10 in 9 in 10 | 5,7,9,11 | 0 | 4 |
Out 5 | 7,9,11 | 3 | 0 |
Out 7 | 9,11 | 2 | 0 |
Out 9 | 11 | 1 | 0 |
Out 11 | empty | 0 | 0 |
As shown in the above figure and the above table, when PreNum is 0, it indicates the next row. At this time, NexNum is assigned to PreNum. When the queue is empty, the cycle ends
C + + code
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: vector<vector<int> > Print(TreeNode* pRoot) { vector<vector<int>>ret; if(pRoot==nullptr) return ret; int PreNum=1; int NexNum=0; queue<TreeNode*>Tree; Tree.push(pRoot);//First put the root node into the queue, so that the initial value of PreNum is 1 vector<int>tmpvect; while(!Tree.empty()) { TreeNode*tmp=Tree.front(); tmpvect.push_back(tmp->val); if(tmp->left)//Join the team when there is a left sub tree. { ++NexNum;//Record the number of nodes in the next row Tree.push(tmp->left); } if(tmp->right) { ++NexNum; Tree.push(tmp->right); } Tree.pop(); --PreNum; if(PreNum==0) { PreNum=NexNum; NexNum=0; ret.push_back(tmpvect); tmpvect.clear();//Remember to empty the temporary array } } return ret; } };
3. Zigzag printing binary tree idea (stack)
As shown in the figure above, the result of zigzag printing binary tree is
1
3 2
4 5
The printing order changes from left to right
Thinking to continue the previous question, let's save the results in a two-dimensional array
We first thought of using queue to realize this printing, but because the queue is first in first out, we must print 2 nodes first and then 3 nodes according to the above idea. So rule out this idea
If you still follow the above idea, if you want to print 3 and 2 from the left subtree and then the right subtree, you need a last in first out data structure stack. Compared with 2, 3 is put on the stack later, so 3 takes precedence over 2. Let's write down the simulation table according to the idea
operation | Stack data | Out of stack |
---|---|---|
Initial value 1 | 1 | 1 |
1 out of stack 2 into stack first 3 into stack later | 2 3 | 3 |
3 out of stack 4 into stack 5 and then into stack | 2 4 5 | 5 |
At this time, it is found that the next element out of the stack becomes 5, but we want 2 out of the stack. Therefore, it is realized that when a node is out of the stack, the left and right nodes cannot be in the same stack, otherwise the data in the same row cannot be out of the stack, as shown in the figure above
So we design two stacks, and the table analysis is as follows
The stack to be printed is set as popTree, and the stack that saves the left and right subtrees of the stack node is set as pushTree
When the popTree is empty, it indicates that one line ends, and the pushTree saves the data of the next line
operation | popTree | pushTree | Out of stack element |
---|---|---|---|
Initial value 1 | 1 | empty | 1 |
1 exit the stack 2 enter the pushTree first 3 then the pushTree | empty | 2 3 | |
Exchange popTree and pushTre | 2 3 | empty | 3 |
3. Out of stack 4. Enter pushTree 5 first and then pushTree | 2 | 4 5 | 2 |
2. No data is input into pushTree when out of stack | empty | 4 5 | |
Exchange popTree and pushTree | 4 5 | empty | 5 |
5 out of stack no data in stack | 4 | empty | 4 |
4 out of stack no data in stack | empty | empty |
It is found that the loop ends when both stacks are empty, but it is found that the printing order is
1
3 2
5 4
The third line is printed as 5 4, which is inconsistent with our expected 4 5, just the opposite. At this time, we realized that if we want to realize the different printing order of each line, it is related to the order of data stacking. If the data of the third line is the right subtree first and the left subtree later, it is correct.
operation | popTree | pushTree | Out of stack element |
---|---|---|---|
Initial value 1 | 1 | empty | 1 |
1 exit the stack 2 enter the pushTree first 3 then the pushTree | empty | 2 3 | |
Exchange popTree and pushTree, indicating the next line, and the stacking order changes | 2 3 | empty | 3 |
3 out of stack 5 in pushTree 4 in pushTree | 2 | 5 4 | 2 |
2. No data is input into pushTree when out of stack | empty | 5 4 | |
Exchange popTree and pushTree, indicating that the stacking order of the next line changes | 5 4 | empty | 4 |
4 out of stack no data in stack | 5 | empty | 5 |
5 out of stack no data in stack | empty | empty |
It can be seen from the above that the second line is left first and right first, the third line is right first and left first, and the fourth line is left first and right first.
How to express line feed: at this time, it is found that when popTree and pushTree are exchanged, it means line feed. When popTree is equal to the initial value, left priority and right stack. When popTree is different from the initial value, it becomes pushTree, which indicates line feed and changes the stacking mode
C + + code
/* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } }; */ class Solution { public: vector<vector<int>>ret; vector<vector<int> > Print(TreeNode* pRoot) { if(pRoot==nullptr) return ret; vector<int>tmp;//The idea of temporary shaping array is similar to that of line feed printing above stack<TreeNode*>Tree[2]; int pushTree=1;//Labels of two stacks are easy to exchange int popTree=0; Tree[popTree].push(pRoot); //The loop ends when both stacks are empty while(!Tree[pushTree].empty()||!Tree[popTree].empty()) { TreeNode*tmpNode=Tree[popTree].top(); tmp.push_back(tmpNode->val); Tree[popTree].pop(); if(popTree==0)//Start to stack from left to right. After line feed exchange, popTree changes to 0 to change the stacking order { if(tmpNode->left!=nullptr) Tree[pushTree].push(tmpNode->left); if(tmpNode->right!=nullptr) Tree[pushTree].push(tmpNode->right); } else { if(tmpNode->right!=nullptr) Tree[pushTree].push(tmpNode->right); if(tmpNode->left!=nullptr) Tree[pushTree].push(tmpNode->left); } if(Tree[popTree].empty())//When the pop stack is found to be empty, it indicates that it needs to wrap { ret.push_back(tmp);//Insert the end of the temporary array onto the two-dimensional array swap(pushTree,popTree);//Swap two arrays tmp.clear();//Empty temporary array } } return ret; } };