1, Title Description
Description
The preorder traversal and inorder traversal of a binary tree are given, and the number of leaf nodes of the corresponding binary tree is counted. This question requires the use of a binary linked list, otherwise even if it passes, points will be deducted as appropriate.
Input
Input two lines of string composed of only uppercase letters, representing the preorder traversal and inorder traversal of binary tree respectively.
Output
Output a number per line, indicating the number of leaf nodes of the tree.
example:
input:
ABCD
ABCD
output:
1
2, Problem solving ideas
1. Build tree
Given the pre order and middle order, a unique binary tree can be established.
The overall implementation idea is through recursive partition,
Specific ideas:
(1) Priority can determine the root node
(2) If you find the root node in the middle order, you can divide the left and right subtrees (the left is the left subtree and the right is the right subtree)
(3) Treat the left and right subtrees as a new tree and call recursively again
(4) If the start subscript of the input substring > end subscript, the substring is empty and NUL is returned
Function implementation:
//Create tree //pre is the starting subscript of the preorder prea the ending subscript of the preorder preb the ending subscript of the preorder mid the middle order mida the beginning of the middle order midb the ending of the middle order TreeNode* BuildTree(string pre, string mid, int prea, int preb, int mida, int midb) { if (prea > preb)//The substring is empty { return NULL; } else { TreeNode* root = new TreeNode;//Set root node root->data = pre[prea];//The first is the root node int tag = mida;//Find the position of the root node in the middle order arrangement while (mid[tag] != root->data) { tag++; } int llength;//Calculate the length of the left substring llength = tag - mida; root->lchild = BuildTree(pre, mid, prea + 1, prea + llength, mida, tag - 1); root->rchild = BuildTree(pre, mid, prea + llength + 1, preb, tag + 1, midb); return root; } }
(in order to look more intuitive, I deleted the debug output statement compared with the complete code posted at the end)
Several explanations:
(1) Parameters of function
pre is the start subscript of the preamble prea and the end subscript of the preamble preb mid order mida middle order start End of midb sequence
(2) Parameters in recursive call
Left substring:
Preamble start = old prea+1 (the first is marked as the root node) End = old PREA + length (left substring length)
("end" can be understood as "start + left substring length - 1")
Middle sequence start = old mida End = tag (root) - 1
Right substring:
Preamble start = old PREA + length (left substring length) + 1 End = old preb
Middle order start = tag (root) + 1 End = old midb
If you don't quite understand it, start painting, it's easy to understand.
2. Calculate the number of leaf nodes
Idea:
Recursive implementation of preorder traversal, in which the judgment of leaf nodes is added.
Function implementation:
int CountLeaf(TreeNode* root)//Calculating the number of leaf nodes and tail recursion saves space { if (root == NULL) return 0; else if (root->lchild == NULL && root->rchild == NULL) { cout << root->data << " "; return 1; } else { cout << root->data << " "; return CountLeaf(root->lchild) + CountLeaf(root->rchild); } }
The idea is very simple, but one thing to note is that this function uses tail recursion,
I didn't do that at first, which resulted in timeout.
int CountLeaf(TreeNode* root,int& count) { if (root == NULL) return 0; else { if (root->lchild != NULL) CountLeaf(root->lchild, count); if(root->rchild!=NULL) CountLeaf(root->rchild, count); else if (root->lchild == NULL && root->rchild == NULL) count++; } }
3, Complete code
#include<iostream> #include<string> using namespace std; //Node definition struct TreeNode { char data; TreeNode* lchild,* rchild; }; //Create tree TreeNode* BuildTree(string pre, string mid, int prea, int preb, int mida, int midb) { if (prea > preb)//The substring is empty { cout << "The substring is empty" << endl; return NULL; } else { TreeNode* root = new TreeNode;//Set root node root->data = pre[prea];//The first is the root node int tag = mida;//Find the position of the root node in the middle order arrangement while (mid[tag] != root->data) { tag++; } int llength;//Calculate the length of the left substring llength = tag - mida; printf("Now in%c Node, left substring length is%d\n", root->data, llength);//For debug ging convenience printf("establish%c Left subtree of:\n", root->data); printf("prea=%d,preb=%d,mida=%d,midb=%d\n", prea + 1, prea + llength, mida, tag - 1); root->lchild = BuildTree(pre, mid, prea + 1, prea + llength, mida, tag - 1); printf("establish%c Right subtree of:\n", root->data); printf("prea=%d,preb=%d,mida=%d,midb=%d\n", prea + llength + 1, preb, tag + 1, midb); root->rchild = BuildTree(pre, mid, prea + llength + 1, preb, tag + 1, midb); return root; } } int CountLeaf(TreeNode* root)//Calculating leaf node tail recursively saves space { if (root == NULL) return 0; else if (root->lchild == NULL && root->rchild == NULL) { cout << root->data << " "; return 1; } else { cout << root->data << " "; return CountLeaf(root->lchild) + CountLeaf(root->rchild); } } int main() { string pre,mid; cin >> pre;//Preorder cin >> mid;//Middle order printf("pre.length()=%d,mid.length()=%d", pre.length(), mid.length()); TreeNode* root= BuildTree(pre, mid, 0, pre.length()-1, 0, mid.length()-1); cout << CountLeaf(root); return 0; }
In fact, there is another point to pay attention to in the main function, that is, when calling the BuildTree function,
BuildTree(pre, mid, 0, pre.length()-1, 0, mid.length()-1);
Remember - 1. Although it was a small point, I had to look for it for a long time to find the problem orz
In the complete code, I mix cin, cout and printf, which is not recommended!!!! Don't do this!!!
(but I'm too lazy to change... Mainly because scanf is very bad)