Sword finger offer_ Print set of binary tree (C + + up and down printing, line feed printing, zigzag printing _bfs + stack and queue + simulating stack queue operation with table)

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.

operationValues in the queue
Print 1Node 2, node 3
Print 2Node 3
Print 3Node 4, node 5
Print 4Node 5
Print 5empty

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:

operationQueue dataPreNumNexNum
Initial value 8810
Out 8 in 6 in 106,1002
Out 6 in 5 in 710,5,712
Out 10 in 9 in 105,7,9,1104
Out 57,9,1130
Out 79,1120
Out 91110
Out 11empty00

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

operationStack dataOut of stack
Initial value 111
1 out of stack 2 into stack first 3 into stack later2 33
3 out of stack 4 into stack 5 and then into stack2 4 55

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

operationpopTreepushTreeOut of stack element
Initial value 11empty1
1 exit the stack 2 enter the pushTree first 3 then the pushTreeempty2 3
Exchange popTree and pushTre2 3empty3
3. Out of stack 4. Enter pushTree 5 first and then pushTree24 52
2. No data is input into pushTree when out of stackempty4 5
Exchange popTree and pushTree4 5empty5
5 out of stack no data in stack4empty4
4 out of stack no data in stackemptyempty

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.

operationpopTreepushTreeOut of stack element
Initial value 11empty1
1 exit the stack 2 enter the pushTree first 3 then the pushTreeempty2 3
Exchange popTree and pushTree, indicating the next line, and the stacking order changes2 3empty3
3 out of stack 5 in pushTree 4 in pushTree25 42
2. No data is input into pushTree when out of stackempty5 4
Exchange popTree and pushTree, indicating that the stacking order of the next line changes5 4empty4
4 out of stack no data in stack5empty5
5 out of stack no data in stackemptyempty

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;
    }
    
};

Tags: C++ Algorithm data structure leetcode

Posted on Wed, 06 Oct 2021 08:34:55 -0400 by leenoble_uk