二叉树的前中后层次遍历(递归+非递归)、创建树(数组、前序+中序、中序加后序)

一、创建树

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;
}

总结:树的操作大多可以考虑递归,原因呢,是因为一棵大的二叉树就是由很多小的二叉树组成的,分治策略,解决小的,进而解决大的。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值