"Algorithm Notes" learning diary-9.1 tree and binary tree & 9.2 binary tree traversal

9.1 Trees and Binary Trees

Codeup Contest ID: 100000610
PS : This section is about the concept of binary tree, there are no related exercises.

9.2 Traversal of Binary Tree

Codeup Contest ID:100000611

Problem A: Restoring a binary tree

Title Description
Xiaoming is doing data structure assignments. One of the questions is to give you the results of the preorder traversal and midorder traversal of a binary tree, and requires you to write the results of the traversal of the binary tree.
Input The
input contains multiple sets of test data. Each set of inputs contains two character strings, which represent the results of the preorder traversal and midorder traversal of the binary tree. Each string consists of unique capital letters.
Output
For each set of inputs, output the subsequent traversal results of the corresponding binary tree.
Sample input

DBACEGF ABCDEFG
BCAD CBAD

Sample output

ACBFGED
CDAB

Idea
This question is very conventional, and there is also a specific code in the book, which is to know the pre-order sequence + mid-order sequence, first reconstruct the binary tree, and then find the post-order sequence.
Code

#include<cstdio>
#include<math.h>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
struct node{
	char data;//数据域是一个字母
	node* lchild;
	node* rchild; 
};
string pre;
string in;
node* create(int preL, int preR, int inL, int inR){
	if(preL>preR){
		return NULL;
	}
	node* root = new node;
	root->data = pre[preL];//确定根节点
	int k;
	for(k=inL;k<=inR;k++){//遍历中序序列区间 
		if(in[k]==pre[preL]) break;//在中序序列中找到根节点了,break 
	}
	int numLeft = k-inL;//左子树的长度 
	root->lchild = create(preL+1, preL+numLeft, inL, k-1);
	root->rchild = create(preL+numLeft+1, preR, k+1, inR);
	return root;
}
void postorder(node* root){//后续遍历 
	if(root==NULL){
		return;
	}
	postorder(root->lchild);
	postorder(root->rchild);
	cout<<root->data;
}
int main(){
	while(cin>>pre>>in){
		node* root = create(0, pre.length()-1, 0, in.length()-1);//都是闭区间
		postorder(root);
		cout<<'\n';
		pre.clear();
		in.clear(); 
	}
	return 0;
}

Question B: Binary tree

Title description
Insert picture description here
As shown above, a special binary tree is formed by positive integers 1, 2, 3 ... We know that the last node of this binary tree is n. The question now is how many nodes are included in the subtree where node m is located.

For example, if n = 12, m = 3, then the nodes 13, 14, 15 and the following nodes in the above figure do not exist. The nodes included in the sub-tree where the node m is located include 3, 6, 7, 12, so there are 4 nodes in the subtree where node m is located.
Input The
input data includes multiple lines, each line gives a set of test data, including two integers m, n (1 <= m <= n <= 1000000000). The last set of test data includes two zeros, indicating the end of the input, and this set of data does not need to be processed.
Output
For each set of test data, output a row, which contains an integer, giving the number of nodes included in the subtree where node m is located.
Sample input

3 7
142 6574
2 754
0 0

Sample output

3
63
498

Thinking
I use recursion to write this question, almost time out ... For the sake of insurance, let's change the recursion to a loop.

The idea is also very simple. According to the meaning of the title, it is to give a complete binary tree, and then let you calculate the summary points of the subtree where a certain node is located (including yourself), because the label in the title has been directly given (that is, press (Layer by layer), then you can use a conclusion from the book. If the label of the current node is x, then its left child is 2x, and its right child is 2x + 1.

So this problem can be solved with dfs: as long as there is a left child, it recurs in that direction; as long as there is a right child, it recurs in that direction. The recursive boundary is: if the calculated 2x or 2x + 1 is already greater than the last node n given, it means that the corresponding left or right child does not exist, and return is just fine.
Code

#include<cstdio>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
void cnt(int m, int n, int &sum){//m是要求的结点,n是树的最后一个结点,sum是所求的结点m的子树包含的总结点 
	if(m>n) return ;
	if(2*m<=n){
		sum++;
		cnt(2*m, n, sum);
	}
	if(2*m+1<=n){
		sum++;
		cnt(2*m+1, n, sum);
	}
}
int main(){
	int m, n;
	while(scanf("%d%d", &m, &n) != EOF){
		if(m==0&&n==0) break;
		int sum = 1;//先算上结点本身 
		cnt(m, n, sum);
		printf("%d\n", sum);
	}
	return 0;
}

Problem C: Binary tree traversal

Topic description
Definition of pre-order, middle-order and post-order traversal of binary tree:
pre-order traversal: for any sub-tree, visit the first, then traverse its left sub-tree, and finally traverse its right sub-tree;
mid-order traversal: For a subtree, first traverse its left subtree, then visit the root, and finally traverse its right subtree;
postorder traversal: for any subtree, first traverse its left subtree, then traverse its right subtree, and finally visit the root.
Given the pre-order traversal and mid-order traversal of a binary tree, find the post-order traversal (hint: the given pre-order traversal and mid-order traversal can uniquely determine the post-order traversal).
Enter
two character strings whose length n is less than or equal to 26.
The first line is pre-order traversal, and the second line is in-order traversal.
The names of the nodes in the binary tree are represented by capital letters: A, B, C ... up to 26 nodes.
There
may be multiple groups of input samples. For each group of test samples, a
line is output, which is a character string traversed in sequence.
Sample input

ABC
CBA
ABCDEFG
DCBAEFG

Sample output

CBA
DCBGFEA

Thinking
this problem and issue A as recommended to write its own independent function reconstruction and post-order traversal of a binary tree, after all, when the examination can not read ah ~
Code

#include<cstdio>
#include<math.h>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
struct node{
	char data;
	node* lchild;
	node* rchild;
};
string pre;
string in;
node* create(int preL, int preR, int inL, int inR){
	if(preL>preR) return NULL;
	node* root = new node;
	root->data = pre[preL];
	int k;
	for(k=inL;k<=inR;k++){
		if(in[k]==pre[preL]) break;
	}
	int numLeft = k-inL;
	root->lchild = create(preL+1, preL+numLeft, inL, k-1);
	root->rchild = create(preL+numLeft+1, preR, k+1, inR);
	return root;
}
void postorder(node* root){
	if(root==NULL) return;
	postorder(root->lchild);
	postorder(root->rchild);
	cout<<root->data;
}
int main(){
	while(cin>>pre>>in){
		node* root = create(0, pre.length()-1, 0, in.length()-1);
		postorder(root);
		cout<<'\n';
		pre.clear();
		in.clear();
	}
	return 0;
}

Question D: Binary tree traversal

Topic description
Compile a program to read a string of pre-ordered traversal strings entered by the user, and build a binary tree (stored as a pointer) based on this string.
For example, the following sequence traverses the string first:
ABC ## DE # G ## F ###
where "#" represents a space, and the space character represents an empty tree. After the binary tree is established, the binary tree is traversed in order, and the traversal result is output.
Input The
input consists of 1 line of character string with a length not exceeding 100.
The output
may have multiple sets of test data. For each set of data,
output the sequence in which the input string is traversed in order after the binary string is established, with a space after each character.
Each output is on a line.
Sample input

a#b#cdef#####
a##

Sample output

a b f e d c 
a 

Thinking about
this question because I was stupid for a while. O (╥﹏╥) o, in fact, the idea is very simple, I thought about it at the beginning, but the output of the middle sequence has been wrong, and then I changed the kind of left and right in the book The tree interval is written to build a tree, and the result has been stuck in the wrong answer 50. Later, I looked at the writing of the big guy [ 小鱼儿. ], And found that it was similar to my original idea, so I used single-step debugging to compare and find the problem ...

So to talk about the idea of ​​this question, if you draw a sample on paper, you will find that the method of building a tree through a sequence is simply DFS . First build a tree in the direction of the left subtree. The "dead end" is Encounter the character "#", then return to the previous layer, and then build in the direction of the right subtree. The particularly error-prone point here is thatNever write the current sequence position index in the function parameters! ! Because when we build a tree by hand, we always read the next digit of the string to judge. If the next digit is "#", then return to the previous layer and fill in the next digit of "#" in the other direction. In the example, because the first digit is not "#", it means that it is not an empty tree, so read a is the root, and then walk in the direction of its left subtree, read the next digit, the next digit is "#", yes An empty tree, indicating that the left subtree of a is empty, return to the previous layer, and then go to the right subtree of a, then read "b" (if index is written in the function parameter, then return the one of a Layer, when going to the direction of the right subtree of a, its index is still the next bit of a, that is, "#").
Code

#include<cstdio>
#include<math.h>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
struct node{
	char data;
	node* lchild;
	node* rchild;
};
string pre;
int index;//要用全局的 
node* create(){//index不要写在函数里 
	if(pre[index]=='#'){
		index++;
		return NULL;
	}
	node* root = new node;
	root->data = pre[index];
	index++;
	root->lchild = create();
	root->rchild = create();//否则左子树建立完回退到右子树这里的话,index也会回退
	//参照dfs,如果index是函数参数,那么会回退到上一个岔路口的状态,所以index会回退
	//但是我们需要的是index一直从字符串左端往右走 
	return root;
}
void inorder(node* root){
	if(root==NULL) return;
	inorder(root->lchild);
	cout<<root->data<<' ';//每个字符后面都有一个空格 
	inorder(root->rchild);
}
int main(){
	while(cin>>pre){
		index = 0;
		node* root = create();
		inorder(root);
		cout<<'\n';
		pre.clear();
	}
	return 0;
}

summary

The traversal of the binary tree is simple for other questions (obviously it is too conventional to have ready-made code in the book), the last question is slightly stuck, referring to the solutions of the big brothers and finding the problem through their single-step debugging , It can be said that it has a deeper understanding of DFS (after recursively returning to the previous layer, all states will be traced back, just like going back to the past hhh), so if you want to read the string all the way from the beginning to the end like the last question If you don't retreat, you still use the global variable ~

Published 54 original articles · won 27 · views 4979

Guess you like

Origin blog.csdn.net/weixin_42257812/article/details/105508391