二叉樹——非遞歸法
建立樹時,按照左子樹小於樹根,右子樹大於樹根,這樣中序遍歷就是有序表
#include<iostream>
#include<queue> //層級遍歷時,用到了queue模板類
#include<stack> //前中後遍歷時,用到了stack模板類
using namespace std;
class node //樹節點定義
{
public:
int data; //元素值
node *parent; //父節點
node *left; //左子節點
node *right; //右子節點
int tag; //這個在後序遍歷中用到,作爲標誌位
public:
// node():data(-1),parent(NULL),left(NULL),right(NULL){};
node(int num):data(num),parent(NULL),left(NULL),right(NULL),tag(0){}; //構造函數,初始化類成員變量
};
class tree //樹定義
{
public:
tree(int num[],int len); //構造函數
void insertNode(int data); //安左低右高插入樹的節點
void preOrderTree(); //前序
void inOrderTree(); //中序
void postOrderTree(); //後序
void levelOrderTree(); //層級遍歷
private:
node *root; //樹的根節點
};
tree::tree(int num[],int len) //構造函數,插入樹節點
{
root=new node(num[0]);
for(int i=1;i<len;i++)
insertNode(num[i]);
}
void tree::insertNode(int data)
{
node *p,*par;
node *newnode=new node(data);
p=par=root;
while(p)
{
par=p;
if(data > p->data)
p=p->right;
else if(data < p->data)
p=p->left;
else if(data == p->data)
{
delete newnode;
return;
}
}
newnode->parent=par;
if(par->data > newnode->data)
par->left=newnode;
else
par->right=newnode;
}
void tree::preOrderTree() //先序遍歷
{
stack<node *> s;
node *p=root; //從根節點開始
while(p|| !s.empty()) //樹不爲空或棧不爲空
{
while(p) //遍歷左子樹,壓入棧,入棧前,輸出節點
{
cout<<p->data<<" ";
s.push(p);
p=p->left;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->right;
}
}
}
void tree::inOrderTree() //中序遍歷
{
stack<node *> s;
node *p=root; //從根節點開始
while(p|| !s.empty()) //樹不爲空或棧不爲空
{
while(p) //遍歷左子樹,壓入棧
{
s.push(p);
p=p->left;
}
if(!s.empty())
{
p=s.top(); //p指向棧頂
s.pop(); //出棧
cout<<p->data<<" ";
p=p->right; //指向這個節點的右子樹,遍歷右子樹做準備
}
}
}
void tree::postOrderTree() //後序遍歷
{
stack<node *> s;
node *p=root;
while(p|| !s.empty())
{
while(p)
{
s.push(p);
p=p->left;
}
if(!s.empty())
{
p=s.top();
if(p->tag) //tag爲0表示遍歷左子樹前的保護現場,tag爲1表示遍歷右子樹前的現場保護
{
cout<<p->data<<" ";
s.pop();
p=NULL;
}
else
{
p->tag=1;
p=p->right;
}
}
}
}
void tree::levelOrderTree() //層級遍歷
{
queue<node *> q; //定義一個隊列
node *ptr=NULL;
q.push(root);
while(!q.empty())
{
ptr=q.front(); //得到隊列的頭節點
q.pop(); //出隊列
cout<<ptr->data<<" ";
if(ptr->left!=NULL) //當前節點存在左節點,左節點入隊
q.push(ptr->left);
if(ptr->right!=NULL) //當前節點存在右節點,右節點入隊
q.push(ptr->right);
}
}
int main()
{
int num[8]={5,3,7,2,4,6,8,1};
tree t(num,8);
cout<<"前序遍歷: ";
t.preOrderTree();
cout<<endl<<endl;
cout<<"中序遍歷: ";
t.inOrderTree();
cout<<endl<<endl;
cout<<"後序遍歷: ";
t.postOrderTree();
cout<<endl<<endl;
cout<<"層級遍歷: ";
t.levelOrderTree();
cout<<endl;
return 0;
}