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~
Table of contents
1. Preorder traversal of binary tree
1.2.1 Template class implementation stack
1.2.2 The template class realizes the optimization algorithm of the stack
2. Inorder traversal of a binary tree
2.2.1 Template class implementation stack
2.2.2 Template class implementation stack optimization algorithm
3. Postorder traversal of binary tree
5. Template class implementation stack complete code
6. STL implementation stack complete code
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~
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;
}