一、创建树
1、根据数组构造一棵树造成排序二叉树
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
struct Node
{
int value;
Node *left;
Node *right;
};
bool Insert(Node **ptree,int value);//函数声明
//**********************建立树*********************//
Node* CreateTree_1(int *arr,int len)
{
if(arr==NULL || len<=0)
{
return NULL;
}
Node *ptree = new Node;
ptree->value = arr[0];
ptree->left = NULL;
ptree->right = NULL;
for(int i=1;i<len;++i)
{
Insert(&ptree,arr[i]);
}
return ptree;
}
2、根据前序和中序构造一棵树 (根左右 和 左根右)
int FindIndex(int pre,int *in,int len) //查找所在位置
{
int index = -1;
if(in == NULL)
return index;
for(int i=0;i<len;++i)
{
if(in[i] ==pre)
{
index = i;
}
}
return index;
}
Node *CreateTree_2(int *pre,int *in,int n)
{
Node *s = NULL;
if(pre!=NULL&&in!=NULL&&n>=0)
{
s = new Node;
s->value = pre[0];
int pos = FindIndex(pre[0],in,n);
if(pos == -1)
{
return NULL;
}
s->left = CreateTree_2(pre+1,in,pos);
s->right = CreateTree_2(pre+pos+1,in+pos+1,n-pos-1);
}
return s;
}
3、根据中序和后序构造一棵树(左根右 和 左右根)
Node *CreateTree_3(int *in,int *past,int len)
{
Node *s = NULL;
if(in != NULL && past!=NULL && len>=0)
{
s = new Node;
s->value = past[len-1];
int pos = FindIndex(past[len-1],in,len);
if(pos == -1)
{
return NULL;
}
s->left = CreateTree_3 (in,past,pos);
s->right = CreateTree_3 (in+pos+1,past+pos,len-pos-1);
}
return s;
}
二、遍历树
1、前序遍历(递归)
void PreOrder(Node *root)
{
if(root != NULL)
{
cout<<root->value <<" ";
PreOrder(root->left);
PreOrder(root->right );
}
}
2、前序遍历(非递归)
void NicePreOrder(Node *root)
{
if(root == NULL)
{
return ;
}
stack<Node *> s;
Node *p = root;
while(!s.empty() || p)
{
while(p!=NULL) //先把左子树全部入栈并打印
{
cout<<p->value <<" ";
s.push (p);
p = p->left ;
}
p = s.top(); //出栈
s.pop();
p = p ->right ;//判断其右子树是否也有左子树
}
}
3、中序遍历(递归)
void InOrder(Node *root)
{
if(root != NULL)
{
InOrder(root->left);
cout<<root->value <<" ";
InOrder(root->right );
}
}
4、中序遍历(非递归)
void NiceInOrder(Node *root)
{
if(root == NULL)
{
return;
}
stack<Node *> s;
Node *p = root;
while(!s.empty() || p)
{
while(p != NULL)
{
s.push(p);
p = p->left ;
}
p = s.top();
cout<<p->value <<" ";
s.pop();
p = p->right ;
}
}
5、后序遍历(递归)
void PastOrder(Node *root)
{
if(root != NULL)
{
PastOrder(root->left );
PastOrder(root->right );
cout<<root->value <<" ";
}
}
6、后序遍历(非递归)
void NicePastOrder(Node *root)
{
if(root == NULL)
{
return;
}
stack<Node *> s;
Node *p = root;
Node *tagnode = NULL; //标记节点
while(p!=NULL) //先把左子树全部入栈
{
s.push (p);
p = p->left ;
}
while(!s.empty ())
{
p = s.top();
s.pop();
if(p->right == NULL || p->right == tagnode) //如果p的右子树等于空或者说右子树已被访问
{
cout<<p->value<<" "; //则进行打印
tagnode = p;
}
else //则证明有右子树且没被访问
{
s.push(p); //则把它再压进栈
p = p->right ;
while(p)
{
s.push(p);
p = p->left ;
}
}
}
}
7、层次遍历
void LevelOrder(Node *root)//利用队列
{
if(root == NULL)
{
return ;
}
queue<Node *> q;
Node *p = root;
q.push(p);
cout<<p ->value <<" ";
while(!q.empty())
{
p = q.front();
if(p->left != NULL)
{
cout<<p->left ->value <<" ";
q.push (p->left);
}
if(p->right != NULL)
{
cout<<p->right->value<<" ";
q.push(p->right);
}
q.pop();
}
}
三、操作树
1、查找数据(非递归)
Node *Search(Node *ptree,int value)
{
if(ptree == NULL)
{
return NULL;
}
Node *p = ptree;
while(p != NULL )
{
while(p!=NULL && p->value > value )
{
p = p->left ;
}
while(p!=NULL && p->value < value)
{
p = p->right ;
}
if(p!=NULL && p->value == value)
{
return p;
}
}
return NULL;
}
2、查找数据(递归)
Node* Find(Node *ptree,int value)
{
if(ptree == NULL || ptree->value == value)
{
return ptree;
}
else if(ptree->value < value)
{
return Find(ptree->right ,value);
}
else
{
return Find(ptree->left,value);
}
}
3、插入数据
bool Insert(Node **ptree,int value)
{
if(*ptree==NULL)
{
return false;
}
Node *p = Search(*ptree,value); //先查找这棵树中是否已经存在这个数据
if(p == NULL)//证明没有此数据,可以插入
{
Node *node = new Node; //构造一个新节点
node->value = value;
node->left = NULL;
node->right = NULL;
Node *q = *ptree; //遍历这棵树
Node *s;
while(q != NULL)
{
while(q!=NULL && q->value > value)
{
s = q; //时刻准备一个节点指向它的上一个,因为你出去的节点肯定在上一个节点的左或者右
q = q->left ;
}
while(q!=NULL && q->value < value )
{
s = q;
q = q->right ;
}
}
if(node->value > s->value)//如果插入的数据大,则放在这个节点的右子树
{
s->right = node;
}
else//如果插入的数据小,则放在这个节点的左子树
{
s->left = node;
}
return true;
}
else//证明已经有数据,无需插入
{
return false;
}
}
//测试函数
int main()
{
int arr[] = {50,45,46,19,60,79,99,11,0};
int len = sizeof(arr)/sizeof(arr[0]);
Node *root = CreateTree_1(arr,len);
cout<<"前序(递归):";
PreOrder(root);
cout<<endl;
cout<<"前序(非递归):";
NicePreOrder(root);
cout<<endl;
cout<<"中序(递归):";
InOrder(root);
cout<<endl;
cout<<"中序(非递归):";
NiceInOrder(root);
cout<<endl;
cout<<"后序(递归):";
PastOrder(root);
cout<<endl;
cout<<"后序(非递归):";
NicePastOrder(root);
cout<<endl;
cout<<"层次遍历:";
LevelOrder(root);
cout<<endl;
int pre[] = {1,2,3,4,5,6};
int in[] = {3,2,4,1,6,5};
int past[] = {3,4,2,6,5,1};
int len1 = sizeof(pre)/sizeof(pre[0]);
Node *s = CreateTree_2(pre,in,len1);
PastOrder (s);
cout<<endl;
Node *s2 = CreateTree_3(in,past,len1);
PreOrder(s2);
cout<<endl;
return 0;
}
总结:树的操作大多可以考虑递归,原因呢,是因为一棵大的二叉树就是由很多小的二叉树组成的,分治策略,解决小的,进而解决大的。