UVA122 traverses Trees on the level

Posted by henrygao on Sat, 19 Feb 2022 13:08:37 +0100

Title Description

input

```(11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) ()
(3,L) (4,R) ()
```

output

```5 4 8 11 13 4 7 2 1
not complete
```

Idea 1: implement binary tree in pointer mode (chain storage)
First define a structure, and then define a structure pointer root as the root node of the whole tree. If the left and right nodes need to be used, apply for a space, that is, do not apply for those that cannot be used, so as to save space.

The traversal method is breadth first traversal (BFS), which expands the child nodes from the root node in turn. If there are child nodes, they will join the team, and then the root node will leave the team. Continue to expand until the queue is empty, that is, traverse the whole tree.

Because the loss of pointer will cause memory leakage, the memory applied by the previous tree must be released before reading the binary tree every time, and the deletion of binary tree is also recursive.

Reference code

```#include<bits/stdc++.h>
using namespace std;
const int maxn = 256+10;
bool failed;

char s[maxn];
struct Node{
bool have_value;//Whether the tag has been assigned a value
int v;
Node *left,*right;
Node():have_value(false),left(NULL),right(NULL){} ;//Construct a method for initialization

};
Node *root;//Root node

void remove_tree(Node *u){
if(u==NULL){
return;
}
remove_tree(u->left);
remove_tree(u->right);
delete u;
}

Node *newnode(){//Create a new node

return new Node();//Can I create a local variable here and return the address No, because this is a function. Once it is executed, all local variables in it will be destroyed
//Therefore, if you need a pointer type structure variable, you should dynamically allocate memory
}

int n = strlen(s);
Node* u = root;
for(int i = 0; i < n; i++){//Constructing binary tree
if(s[i]=='L'){
if(u->left==NULL){
u->left = newnode();
}
u = u->left;//Auxiliary variable backward
}else if(s[i]=='R'){
if(u->right==NULL){
u->right= newnode();
}
u = u->right;
}
}
if(u->have_value){//If a value has been assigned, the tag changes
failed = true;
}
u->v = v;//Assign a value to the current node
u->have_value = true;//The marking changes
}

failed = false;
remove_tree(root);//Because there are multiple cases, release the memory of the last root node first
root = newnode();
while(1){
//gets(s);
if(scanf("%s",&s)!=1){
return false;
}
if(!strcmp(s,"()"))
break;
int v;
sscanf(&s[1],"%d",&v);//Extracts an integer from a string If (11,LL), put 11 into v
addnode(v,strchr(s,',')+1);// strchr(s, '' '): returns the pointer that appears for the first time from left to right; For example, (11, ll) strchr(s, ',') + 1: "ll)"
}
return true;
}

bool bfs(vector<int> &ans){
queue<Node*> q;
ans.clear();
q.push(root);
while(!q.empty()){
Node* u = q.front();
q.pop();
if(!u->have_value){//Judge whether to assign multiple values
return false;
}
ans.push_back(u->v);//Put the nodes accessed each time into the array
if(u->left!=NULL){
q.push(u->left);
}
if(u->right!=NULL){
q.push(u->right);
}
}
return true;
}
int main(){
vector<int> ans;
if(!bfs(ans))
failed = 1;
if(failed){
printf("not complete\n");
} else{
for(int i = 0; i < ans.size(); i++){
if(i!=0){
cout<<" ";
}
cout<<ans[i];
}
cout<<endl;
}
}
return 0;

}
```

Idea 2: implement binary tree in array mode (corresponding to sequential storage)
The counter cnt increases by 1 for each new node

```#include<bits/stdc++.h>
using namespace std;
const int maxn = 300;
const int root = 1;
char s[maxn];
bool have_value[maxn], failed;
int L[maxn], R[maxn], val[maxn], cnt;
vector<int> ans;

void newtree() {//New tree
L[root] = R[root] = 0;
have_value[root] = false;
cnt = root;
}

int newnode()//Create a new node
{
int u = ++cnt;
L[u] = R[u] = 0;
have_value[u] = false;
return u;
}

void addnode(int v, char* s) {
int u = root;//Auxiliary variable
for (int i = 0; i < strlen(s); i++) {
if (s[i] == 'L') {
if (L[u] == 0)
L[u] = newnode();
u = L[u];
}
else if (s[i] == 'R') {
if (R[u] == 0) {
R[u] = newnode();
}
u = R[u];
}
}
if (have_value[u])//If a node has multiple assignments, it is marked
failed = true;
val[u] = v;
have_value[u] = true;
}

{
failed = false;
newtree();
while (1) {
//scanf("%s",s);
if(scanf("%s", s) != 1)//It should be judged here. If "()" is not reached by the end of the file, the program will be ended Avoid falling into a dead circle
{
//cout<<"hahahhh"<<endl;
return false;
}

if(!strcmp(s,"()")){
break;
}
int v;
sscanf(&s[1], "%d", &v);
}

return true;
}

bool BFS() {
queue<int> q;//Breadth first essential queue hahaha storage node index
ans.clear();
q.push(root);
while (!q.empty()) {
int u = q.front();
q.pop();
if (!have_value[u]) {//If multiple assignments are made, the binary tree does not meet the meaning of the question and ends directly
return false;
}
ans.push_back(val[u]); //Put in the value corresponding to the index
if (L[u] != 0) {
q.push(L[u]);//
}
if (R[u] != 0) {
q.push(R[u]);
}
}
return true;
}

int main()
{
if (failed || !BFS()) {
cout << "not complete" << endl;
}
else {
cout << ans[0];
for (int i = 1; i < ans.size(); i++) {
cout << " " << ans[i];
}
cout << endl;
}
}
return 0;
}

```

be careful:

1. There are two ways to store binary trees It involves the general order of querying node positions, and the general chain of inserting and deleting nodes
2. For scanf input, it's best to judge the return value to prevent the program from stopping after the file is read
3. String and character array can be used for reading string. When using character array, the parameter passes the character pointer Moreover, using character array will be more efficient, while using string is difficult to read with scanf Then choose according to your needs

Finally, I modified it slightly with string, but it will submit TLE, so it's best to use character array, and then scanf can not only judge but also improve efficiency

```#include<bits/stdc++.h>
using namespace std;
const int maxn = 300;
const int root = 1;
string s;

bool have_value[maxn], failed;
int L[maxn], R[maxn], val[maxn], cnt;
vector<int> ans;

void newtree() {//New tree
L[root] = R[root] = 0;
have_value[root] = false;
cnt = root;
}

int newnode()//Create a new node
{
int u = ++cnt;
L[u] = R[u] = 0;
have_value[u] = false;
return u;
}

void addnode(int v, string& s) {
int u = root;//Auxiliary variable
for (int i = 0; i < s.size(); i++) {
if (s[i] == 'L') {
if (L[u] == 0)
L[u] = newnode();
u = L[u];
}
else if (s[i] == 'R') {
if (R[u] == 0) {
R[u] = newnode();
}
u = R[u];
}
}
if (have_value[u])//If a node has multiple assignments, it is marked
failed = true;
val[u] = v;
have_value[u] = true;
}

{
failed = false;
newtree();
while (1) {
cin>>s;
if (s.compare("()")==0) {//The return value of this function is an integer, so the judgment conditions should be written clearly
break;
}
int v;
sscanf(&s[1], "%d", &v);
addnode(v, s);//String interception cannot be used here, because the temporary variable does not exist after the function is executed
}
return true;
}

bool BFS() {
queue<int> q;//Breadth first essential queue hahaha storage node index
ans.clear();
q.push(root);
while (!q.empty()) {
int u = q.front();
q.pop();
if (!have_value[u]) {//If multiple assignments are made, the binary tree does not meet the meaning of the question and ends directly
return false;
}
ans.push_back(val[u]); //Put in the value corresponding to the index
if (L[u] != 0) {
q.push(L[u]);//
}
if (R[u] != 0) {
q.push(R[u]);
}
}
return true;
}

int main()
{
if (failed || !BFS()) {
cout << "not complete" << endl;
}
else {
cout << ans[0];
for (int i = 1; i < ans.size(); i++) {
cout << " " << ans[i];
}
cout << endl;
}
}
return 0;
}

```

Topics: Java Algorithm Binary tree