Beiyou 22 Xintong: Summary of all common algorithms for binary tree traversal

A Beiyou 22 Xintong~   

Code and articles on data structures and algorithms are updated weekly following the progress of the course 

Continue to pay attention to the author to unlock more exclusive codes of Youyuan Xintong~

For more articles, please visit the column~

Beiyou 22 Letters and Communications_The green hills are like ink and the rain is picturesque blog-CSDN blog

Table of contents

1. Preorder traversal of binary tree

1.1 Recursive algorithm

1.2 Non-recursive algorithm

1.2.1 Template class implementation stack  

1.2.2 The template class realizes the optimization algorithm of the stack

 1.2.3 STL stack

2. Inorder traversal of a binary tree

2.1 Recursive algorithm

2.2 Non-recursive algorithm

2.2.1 Template class implementation stack

2.2.2 Template class implementation stack optimization algorithm

2.2.3 STL stack

3. Postorder traversal of binary tree

3.1 Recursive algorithm

3.2 Non-recursive algorithm

3.3 Description

4. Layer order traversal

5. Template class implementation stack complete code

5.1 Code part

5.2 Running results

 6. STL implementation stack complete code

6.1 Code part

6.2 Running results:


1. Preorder traversal of binary tree

1.1 Recursive algorithm

template<class temp>
void bintree<temp>::preorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		cout << r->data;
		preorder(r->leftchild);
		preorder(r->rightchild);
	}
}

1.2 Non-recursive algorithm

1.2.1 Template class implementation stack  

The top element of the stack is always the parent node of the current element, and r is the currently visited node, then

1. If r! =NULL, access r ( cout<<s[top].r->data; ) and put it on the stack ( s[++top].r=r; ), call r=r->leftchild; mark r as 1 ( s[top].tag=1; ) returns 1;

2. If r==NULL, reset r as the top element of the stack

        2.1 If r is marked as 2, it means that the right subtree returns; r pops out of the stack, resets r as the top element of the stack ( top--; ), and returns 2.1;

        2.2 If r is marked as 1, it means that the left subtree returns; call r=r->rightchild; mark r as 2 ( s[top].tag=2; ), return 1;

Execute repeatedly until the stack is empty ( top==-1 ), and the program ends.

if(r!=NULL)

{

cout<<r->data;入栈

}

if(r==NULL)

        1. Go out of the stack and change to the right branch

        2. Pop out

template<class temp>
void bintree<temp>::stackpreorder(binnode<temp>* r)
{
	linkstack<temp> s[100];//栈
	int top = -1;//栈顶指针
	do
	{
		while (r != NULL)//入栈并访问,设置为左子树
		{
			s[++top].r = r;
			s[top].tag = 1;
			cout << s[top].r->data;
			r = r->leftchild;
		}
		while ((top != -1) && s[top].tag == 2)//出栈
			top--;
		if ((top != -1) && (s[top].tag == 1))
		{
            //设置栈顶访问右子树
			r = s[top].r->rightchild;
			s[top].tag = 2;
		}
	} while (top != -1);
}

1.2.2 The template class realizes the optimization algorithm of the stack

        The current node, after visiting its left subtree, relies on the current node to find the right subtree. After that, the current node no longer provides information and waits to be popped; the current node can be popped from the stack in advance to simplify the recursive process.

Algorithm optimization:

if(r!=NULL)

{

        cout<<r->data;入栈

}

if(R==NULL)

        Pop out, change right branch

template<class temp>
void bintree<temp>::quickstackpreorder(binnode<temp>* r)
{
	linkstack<binnode<temp>*>s;
	while (!s.empty() || (r != NULL))
	{
		if (r != NULL)
		{
			cout << r->data;
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.pop();
			r = r->rightchild;
		}
	}
}

 1.2.3 STL stack

template<class temp>
void bintree<temp>::quickSTLpreorder(binnode<temp>* r)
{
	stack<binnode<temp>*>s;
	while (!s.empty() || (r != NULL))
	{
		if (r != NULL)
		{
			cout << r->data;
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.top();
			s.pop();
			r = r->rightchild;
		}
	}
}

2. Inorder traversal of a binary tree

2.1 Recursive algorithm

template<class temp>
void bintree<temp>::inorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		inorder(r->leftchild);
		cout << r->data;
		inorder(r->rightchild);
	}
}

2.2 Non-recursive algorithm

2.2.1 Template class implementation stack

The top element of the stack is always the parent node of the current element, and r is the currently visited node, then

1. If r! =NULL, r is pushed onto the stack ( s[++top].r=r; ), call r=r->leftchild; mark r as 1 ( s[top].tag=1; ), return 1;

2. If r==NULL, reset r as the top element of the stack

        2.1 If r is marked as 2, it means that the right subtree returns; r pops out of the stack, resets r as the top element of the stack ( top--; ), and returns 2.1;

        2.2 If r is marked as 1, it means that the left subtree returns; call r=r->rightchild; access r ( cout<<s[top].r->data; ) and mark r as 2 ( s[top]. tag=2; ), return 1;

Execute repeatedly until the stack is empty ( top==-1 ), and the program ends.

if(r!=NULL)

{

        stack;

}

if(r==NULL)

        1: cout<<r->data; out of the stack, change to the right branch;

        2: pop out

template<class temp>
void bintree<temp>::stackinorder(binnode<temp>* r)
{
	linkstack<temp> s[100];
	int top = -1;
	do
	{
		while (r != NULL)
		{
			s[++top].r = r;
			s[top].tag = 1;
			r = r->leftchild;
		}
		while ((top != -1) && (s[top].tag == 2))
			top--;
		if ((top != -1) && (s[top].tag == 1))
		{
			r = s[top].r->rightchild;
			cout << s[top].r->data;
			s[top].tag = 2;
		}
	} while (top != -1);
}

2.2.2 Template class implementation stack optimization algorithm

        The current node, after visiting its left subtree, relies on the current node to find the right subtree. After that, the current node no longer provides information and waits to be popped; the current node can be popped from the stack in advance to simplify the recursive process.

algorithm optimization

if(r!=NULL)

{

        stack;

}

if(r==NULL)

{

        cout<<r->data;

        Pop out the stack and change the right branch;

}

template<class temp>
void bintree<temp>::quickstackinorder(binnode<temp>* r)
{
	linkstack<binnode<temp>*>s;
	while (!s.empty() || r != NULL)
	{
		if (r != NULL)
		{
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.pop();
			cout << r->data;
			r = r->rightchild;
		}
	}
}

2.2.3 STL stack

template<class temp>
void bintree<temp>::quickSTLinorder(binnode<temp>* r)
{
	stack<binnode<temp>*>s;
	while (!s.empty() || (r != NULL))
	{
		if (r != NULL)
		{
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.top();
			s.pop();
			cout << r->data;
			r = r->rightchild;
		}
	}
}

3. Postorder traversal of binary tree

3.1 Recursive algorithm

template<class temp>
void bintree<temp>::postorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		postorder(r->leftchild);
		postorder(r->rightchild);
		cout << r->data;
	}
}

3.2 Non-recursive algorithm

The top element of the stack is always the parent node of the current element, and r is the currently visited node, then

1. If r! =NULL, r is pushed onto the stack ( s[++top].r=r; ), call r=r->leftchild; mark r as 1 ( s[top].tag=1; ), return 1;

2. If r==NULL, reset r as the top element of the stack

        2.1 If r is marked as 2, it means that the right subtree returns; access r ( cout<<s[top].r->data; ) r pops out of the stack, reset r as the top element of the stack ( top--; ), and return 2.1 ;

        2.2 If r is marked as 1, it means that the left subtree returns; call r=r->rightchild; mark r as 2 ( s[top].tag=2; ), return 1;

Execute repeatedly until the stack is empty ( top==-1 ), and the program ends.

if(r!=NULL)

{

        stack;

}

if(r==NULL)

        1: out of the stack, change to the right branch;

       2: cout<<r->data; out of the stack

template<class temp>
void bintree<temp>::stackpostorder(binnode<temp>* r)
{
	linkstack<temp> s[100];
	int top = -1;
	do
	{
		while (r != NULL)
		{
			s[++top].r = r;
			s[top].tag = 1;
			r = r->leftchild;
		}
		while ((top != -1) && (s[top].tag == 2))
		{
			cout << s[top].r->data;
			top--;
		}
		if ((top != -1) && (s[top].tag == 1))
		{
			r = s[top].r->rightchild;
			s[top].tag = 2;
		}
	} while (top != -1);
}

3.3 Description

The core of the optimization algorithm         for non-recursive traversal is: because the role of the root node is to index the left subtree , the root node is meaningless after visiting the left subtree, so you can skip the root node and directly access the right subtree, thereby reducing the time complexity. But in post-order traversal, the root node is visited last , so there is no corresponding optimization algorithm.

4. Layer order traversal

For layer order traversal, please see this article for a detailed explanation~

Beiyou 22 Xintong: Two methods of binary tree layer order traversal && first template class interaction

5. Template class implementation stack complete code

The complete code of the template class implementing the stack is given below .

5.1 Code part

#include<iostream>
using namespace std;
#define MAXSIZE 100005

class student
{
private:
	int ID;
	string name;
public:
	int existence;
	student()
	{
		this->ID = 0;
		this->name = "unknown name";
		this->existence = 0;
	}
	student(int ID, string name)
	{
		this->ID = ID;
		this->name = name;
		this->existence = 1;
	}
	friend ostream& operator<<(ostream& output, student& s)
	{
		output << s.ID << " " << s.name << endl;
		return output;
	}
};

template<class temp>
struct binnode;
//栈
template <class temp>
struct node
{
	temp data;
	node<temp>* next;
};

template <class temp>
class linkstack
{
public:
	binnode<temp>* r;
	int tag;
	linkstack() { top = NULL; }
	~linkstack();
	void push(temp x);
	temp pop();
	temp gettop();
	bool empty()
	{
		return top == NULL ? true : false;
	}
private:
	node<temp>* top;
};

template <class temp>
void linkstack<temp>::push(temp x)
{
	node<temp>* p = new node<temp>;
	p->data = x;
	p->next = this->top;
	this->top = p;
}

template<class temp>
temp linkstack<temp>::pop()
{
	if (empty())throw "下溢";
	temp x = this->top->data;
	node<temp>* p = this->top;
	this->top = this->top->next;
	delete p;
	return x;
}

template<class temp>
linkstack<temp>::~linkstack()
{
	while (this->top != NULL)
	{
		node<temp>* p = this->top;
		this->top = this->top->next;
		delete p;
	}
}

template<class temp>
temp linkstack<temp>::gettop()
{
	if (empty())throw"下溢";
	return this->top->data;
}

//二叉树
template<class temp>
struct binnode
{
	temp data;
	binnode<temp>* leftchild;
	binnode<temp>* rightchild;
};

template<class temp>
class bintree
{
private:
	void create(binnode<temp>*& r, temp data[], int i, int n);
	void release(binnode<temp>* r);
public:
	binnode<temp>* root;
	bintree(temp data[], int n);
	void preorder(binnode<temp>* r);
	void stackpreorder(binnode<temp>* r);
	void quickstackpreorder(binnode<temp>* r);
	void inorder(binnode<temp>* r);
	void stackinorder(binnode<temp>* r);
	void quickstackinorder(binnode<temp>* r);
	void postorder(binnode<temp>* r);
	void stackpostorder(binnode<temp>* r);
	void levelorder(binnode<temp>* r);

	~bintree();
};

template<class temp>
void bintree<temp>::create(binnode<temp>*& r, temp data[], int i, int n)
{
	if (i <= n && data[i - 1].existence != 0)
	{
		r = new binnode<temp>;
		r->data = data[i - 1];
		r->leftchild = r->rightchild = NULL;
		create(r->leftchild, data, 2 * i, n);
		/*书上代码错误1:向函数传入实参时少传入一个n*/
		create(r->rightchild, data, 2 * i + 1, n);/*书上代码错误同上*/
	}
}

template<class temp>
bintree<temp>::bintree(temp data[], int n)
{
	create(this->root, data, 1, n);
}

template<class temp>
void bintree<temp>::preorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		cout << r->data;
		preorder(r->leftchild);
		preorder(r->rightchild);
	}
}

template<class temp>
void bintree<temp>::stackpreorder(binnode<temp>* r)
{
	linkstack<temp> s[100];
	int top = -1;
	do
	{
		while (r != NULL)
		{
			s[++top].r = r;
			s[top].tag = 1;
			cout << s[top].r->data;
			r = r->leftchild;
		}
		while ((top != -1) && s[top].tag == 2)
			top--;
		if ((top != -1) && (s[top].tag == 1))
		{
			r = s[top].r->rightchild;
			s[top].tag = 2;
		}
	} while (top != -1);
}

template<class temp>
void bintree<temp>::quickstackpreorder(binnode<temp>* r)
{
	linkstack<binnode<temp>*>s;
	while (!s.empty() || (r != NULL))
	{
		if (r != NULL)
		{
			cout << r->data;
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.pop();
			r = r->rightchild;
		}
	}
}

template<class temp>
void bintree<temp>::inorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		inorder(r->leftchild);
		cout << r->data;
		inorder(r->rightchild);
	}
}

template<class temp>
void bintree<temp>::stackinorder(binnode<temp>* r)
{
	linkstack<temp> s[100];
	int top = -1;
	do
	{
		while (r != NULL)
		{
			s[++top].r = r;
			s[top].tag = 1;
			r = r->leftchild;
		}
		while ((top != -1) && (s[top].tag == 2))
			top--;
		if ((top != -1) && (s[top].tag == 1))
		{
			r = s[top].r->rightchild;
			cout << s[top].r->data;
			s[top].tag = 2;
		}
	} while (top != -1);
}

template<class temp>
void bintree<temp>::quickstackinorder(binnode<temp>* r)
{
	linkstack<binnode<temp>*>s;
	while (!s.empty() || r != NULL)
	{
		if (r != NULL)
		{
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.pop();
			cout << r->data;
			r = r->rightchild;
		}
	}
}

template<class temp>
void bintree<temp>::postorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		postorder(r->leftchild);
		postorder(r->rightchild);
		cout << r->data;
	}
}

template<class temp>
void bintree<temp>::stackpostorder(binnode<temp>* r)
{
	linkstack<temp> s[100];
	int top = -1;
	do
	{
		while (r != NULL)
		{
			s[++top].r = r;
			s[top].tag = 1;
			r = r->leftchild;
		}
		while ((top != -1) && (s[top].tag == 2))
		{
			cout << s[top].r->data;
			top--;
		}
		if ((top != -1) && (s[top].tag == 1))
		{
			r = s[top].r->rightchild;
			s[top].tag = 2;
		}
	} while (top != -1);
}

template<class temp>
void bintree<temp>::levelorder(binnode<temp>* R)
{
	binnode<temp>* queue[MAXSIZE];
	int f = 0, r = 0;
	if (R != NULL)
		queue[++r] = R;//根节点入队
	while (f != r)
	{
		binnode<temp>* p = queue[++f];//队头元素入队
		cout << p->data;//出队打印
		if (p->leftchild != NULL)
			queue[++r] = p->leftchild;//左孩子入队
		if (p->rightchild != NULL)
			queue[++r] = p->rightchild;//右孩子入队
	}
}

template <class temp>
void bintree<temp>::release(binnode<temp>* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}

template<class temp>
bintree<temp>::~bintree()
{
	release(this->root);
}

int main()
{

	system("color 0A");
	student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
	bintree<student>bintreee(stu, 5);
	cout << "前序遍历:" << endl;
	bintreee.preorder(bintreee.root);
	cout << endl << "模板类实现栈前序遍历:" << endl;
	bintreee.stackpreorder(bintreee.root);
	cout << endl << "栈快排前序遍历:" << endl;
	bintreee.quickstackpreorder(bintreee.root);

	cout << endl << "中序遍历:" << endl;
	bintreee.inorder(bintreee.root);
	cout << endl << "模板类实现栈中序遍历:" << endl;
	bintreee.stackinorder(bintreee.root);
	cout << endl << "栈快排中序遍历" << endl;
	bintreee.quickstackinorder(bintreee.root);

	cout << endl << "后序遍历:" << endl;
	bintreee.postorder(bintreee.root);
	cout << endl << "模板类实现栈后序遍历:" << endl;
	bintreee.stackpostorder(bintreee.root);

	cout << endl << "层序遍历:" << endl;
	bintreee.levelorder(bintreee.root);
	cout << endl;
	return 0;
}

5.2 Running results

5.2.1 Code effect diagram:

 5.2.2 Running results:

 6. STL implementation stack complete code

6.1 Code part

#include<iostream>
#include<stack>
using namespace std;
#define MAXSIZE 100005

class student
{
private:
	int ID;
	string name;
public:
	int existence;
	student()
	{
		this->ID = 0;
		this->name = "unknown name";
		this->existence = 0;
	}
	student(int ID, string name)
	{
		this->ID = ID;
		this->name = name;
		this->existence = 1;
	}
	friend ostream& operator<<(ostream& output, student& s)
	{
		output << s.ID << " " << s.name << endl;
		return output;
	}
};

//二叉树
template<class temp>
struct binnode
{
	temp data;
	binnode<temp>* leftchild;
	binnode<temp>* rightchild;
};

template<class temp>
class bintree
{
private:
	void create(binnode<temp>*& r, temp data[], int i, int n);
	void release(binnode<temp>* r);
public:
	binnode<temp>* root;
	bintree(temp data[], int n);
	void preorder(binnode<temp>* r);
	void quickSTLpreorder(binnode<temp>* r);
	void inorder(binnode<temp>* r);
	void quickSTLinorder(binnode<temp>* r);
	void postorder(binnode<temp>* r);
	void levelorder(binnode<temp>* r);

	~bintree();
};

template<class temp>
void bintree<temp>::create(binnode<temp>*& r, temp data[], int i, int n)
{
	if (i <= n && data[i - 1].existence != 0)
	{
		r = new binnode<temp>;
		r->data = data[i - 1];
		r->leftchild = r->rightchild = NULL;
		create(r->leftchild, data, 2 * i, n);
		/*书上代码错误1:向函数传入实参时少传入一个n*/
		create(r->rightchild, data, 2 * i + 1, n);/*书上代码错误同上*/
	}
}

template<class temp>
bintree<temp>::bintree(temp data[], int n)
{
	create(this->root, data, 1, n);
}

template<class temp>
void bintree<temp>::preorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		cout << r->data;
		preorder(r->leftchild);
		preorder(r->rightchild);
	}
}

template<class temp>
void bintree<temp>::quickSTLpreorder(binnode<temp>* r)
{
	stack<binnode<temp>*>s;
	while (!s.empty() || (r != NULL))
	{
		if (r != NULL)
		{
			cout << r->data;
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.top();
			s.pop();
			r = r->rightchild;
		}
	}
}

template<class temp>
void bintree<temp>::inorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		inorder(r->leftchild);
		cout << r->data;
		inorder(r->rightchild);
	}
}

template<class temp>
void bintree<temp>::quickSTLinorder(binnode<temp>* r)
{
	stack<binnode<temp>*>s;
	while (!s.empty() || (r != NULL))
	{
		if (r != NULL)
		{
			s.push(r);
			r = r->leftchild;
		}
		else
		{
			r = s.top();
			s.pop();
			cout << r->data;
			r = r->rightchild;
		}
	}
}

template<class temp>
void bintree<temp>::postorder(binnode<temp>* r)
{
	if (r != NULL)
	{
		postorder(r->leftchild);
		postorder(r->rightchild);
		cout << r->data;
	}
}

template<class temp>
void bintree<temp>::levelorder(binnode<temp>* R)
{
	binnode<temp>* queue[MAXSIZE];
	int f = 0, r = 0;
	if (R != NULL)
		queue[++r] = R;//根节点入队
	while (f != r)
	{
		binnode<temp>* p = queue[++f];//队头元素入队
		cout << p->data;//出队打印
		if (p->leftchild != NULL)
			queue[++r] = p->leftchild;//左孩子入队
		if (p->rightchild != NULL)
			queue[++r] = p->rightchild;//右孩子入队
	}
}

template <class temp>
void bintree<temp>::release(binnode<temp>* r)
{
	if (r != NULL)
	{
		release(r->leftchild);
		release(r->rightchild);
		delete r;
	}
}

template<class temp>
bintree<temp>::~bintree()
{
	release(this->root);
}

int main()
{

	system("color 0A");
	student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
	bintree<student>bintreee(stu, 5);
	cout << "前序遍历:" << endl;
	bintreee.preorder(bintreee.root);
	cout << endl << "STL前序遍历:" << endl;
	bintreee.quickSTLpreorder(bintreee.root);

	cout << endl << "中序遍历:" << endl;
	bintreee.inorder(bintreee.root);
	cout << endl << "STL中序遍历" << endl;
	bintreee.quickSTLinorder(bintreee.root);

	cout << endl << "后序遍历:" << endl;
	bintreee.postorder(bintreee.root);

	cout << endl << "层序遍历:" << endl;
	bintreee.levelorder(bintreee.root);
	cout << endl;
	return 0;
}

6.2 Running results:

Guess you like

Origin blog.csdn.net/bc202205/article/details/130347397