二叉树的建立和遍历C++

1.二叉树知识点复习
二叉树是不存在度大于2的结点的树,且结点的子树有左右之分
⑴主要性质:
①二叉树的第i层最多有2^(i-1)个结点。
②一颗深度为k的二叉树最多有2^k-1个结点。
③设一颗二叉树的结点数为n,其中度为0,1,2的结点分别为n0,n1,n2,则有n0=n2+1.
(树枝数=n-1=n1+2*n2)
④具有n的结点的完全二叉树,其深度k为logn取下整+1。

⑵满二叉树:一颗k层的具有最多结点数的二叉树。

⑶完全二叉树:一颗k层的二叉树,其中前k-1层是满二叉树,最后一层的结点从左向右依次排列的树。

⑷二叉链表:一种包含三个域的结构体组成的链表,其中包含指向左子树的结点、数据域、指向右子树的结点。另外,一颗具有n的结点的二叉链表,有n+1个空链域 (树枝数=非空链域数=n-1)

⑸线索二叉树:将二叉树的空链域利用起来,存储二叉树在某种遍历次序下,该结点的前驱结点和后继结点的指针。所以,按照遍历方法,线索二叉树可分为前序、中序、后序线索二叉树。

线索二叉树的结点结构是:lchild+ltag+data+rtag+rchild
tag标记为0时,表示两个链域指向孩子
tag标记为1时,对于lchild,指向前驱结点;对于rchild,指向后继结点。

2.二叉树的建立和遍历代码
建立用前序遍历的方法输入二叉树的各个结点值,对于空结点可以指定一个字符来代表,我用的是数字0.

遍历主要有前中后序遍历和层次遍历。
前中后序遍历包含了递归和非递归方法,层次遍历使用队列。

⑴结点结构和二叉树类

struct Node
{
	int data;
	Node *lchild;
	Node *rchild;
};

class BiTree
{
private:
	Node* root;
public:
	BiTree();
	Node* getRoot();
	Node* buildTree();
	void visit(Node* t);

	void pre_traverse_recursion(Node *pos);
	void pre_traverse_non_recursion();
	void in_traverse_recursion(Node *pos);
	void in_traverse_non_recursion();
	void post_traverse_recursion(Node *pos);
	void post_traverse_non_recursion();
	void level_traverse_queue();


};

⑵二叉树的建立

BiTree::BiTree()
{
	root = buildTree();
}

Node* BiTree::buildTree()
{
	Node *cur;
	int data;
	cin >> data;
	if (data==0)
	{
		cur= NULL;
	}
	else
	{
		cur = new Node;  //这里要不放在一开始就new 否则会有异常
		cur->data = data;
		cur->lchild = buildTree();
		cur->rchild = buildTree();
	}
	return cur;
}

⑶前序遍历

void BiTree::visit(Node* t)
{
	cout << t->data << " ";
}

void BiTree::pre_traverse_recursion(Node *pos)
{
	if (pos)
	{
		visit(pos);
		pre_traverse_recursion(pos->lchild);
		pre_traverse_recursion(pos->rchild);
	}		
}

void BiTree::pre_traverse_non_recursion()
{
	/*
	①访问节点数据 ②结点入栈 ③访问左子树,重复①②③直至当前结点左子树为空
	④弹出栈顶结点,其右子树作为当前结点,回到①
	*/
	stack<Node*> s;
	s.push(root);
	Node*pos = root;
	while (!s.empty())
	{
		while (pos)
		{
			visit(pos);
			pos = pos->lchild;
			if(pos)
				s.push(pos);
		}

		pos = s.top();
		s.pop();
		pos = pos->rchild;
		if (pos)
			s.push(pos);
	}
}

⑷中序遍历

void BiTree::in_traverse_recursion(Node *pos)
{
	if (pos)
	{
		in_traverse_recursion(pos->lchild);
		visit(pos);
		in_traverse_recursion(pos->rchild);
	}
}

void BiTree::in_traverse_non_recursion()
{
	/*
	①将当前结点入栈 ②访问当前结点的左子树,重复①②直至当前结点左子树为空
	③弹出栈顶结点为当前结点,访问结点数据 ④访问当前结点右子树,回到①
	*/
	Node* pos = root;
	stack<Node*> s;
	s.push(root);
	
	while (!s.empty())
	{
		while (pos)
		{
			pos = pos->lchild;
			if(pos)
				s.push(pos);
		}
		pos = s.top();
		s.pop();
		visit(pos);
		pos = pos->rchild;
		if (pos)
			s.push(pos);
	}
}

⑸后序遍历

void BiTree::post_traverse_recursion(Node *pos)
{
	if (pos)
	{
		in_traverse_recursion(pos->lchild);
		in_traverse_recursion(pos->rchild);
		visit(pos);
	}
}

void BiTree::post_traverse_non_recursion()
{
	/*
	双栈法:
	①根节点入栈1
	②当栈1非空时,进行以下操作:弹出栈1顶点压入栈2->当前顶点左子树若非空入栈1->当前结点右子树若非空入栈1
	③依次弹出栈2结点并访问
	*/
	Node* pos = root;
	stack<Node*> s1, s2;
	s1.push(pos);
	while (!s1.empty())
	{
		pos = s1.top();
		s1.pop();
		s2.push(pos);
		if (pos->lchild)
			s1.push(pos->lchild);
		if (pos->rchild)
			s1.push(pos->rchild);
	}
	while (!s2.empty())
	{
		pos = s2.top();
		s2.pop();
		visit(pos);
	}
}

⑹层次遍历

void BiTree::level_traverse_queue()
{
	/*
	队列
	①根节点入队
	②当队列非空时:访问队首结点并出队->结点的左子树(若非空)入队->结点的右子树(若非空)入队
	*/
	queue<Node*> q;
	Node* pos = root;
	q.push(pos);
	while (!q.empty())
	{
		pos = q.front();
		q.pop();
		visit(pos);
		if (pos->lchild)
			q.push(pos->lchild);
		if (pos->rchild)
			q.push(pos->rchild);
	}
}

⑺测试

int main()
{
	cout << "请按前序遍历的方式输入二叉树,空结点用0表示:" << endl;
	BiTree myTree;  

	cout << "前序遍历(递归)";
	myTree.pre_traverse_recursion(myTree.getRoot());
	cout << endl;

	cout << "前序遍历(非递归)";
	myTree.pre_traverse_non_recursion();
	cout << endl;

	cout << "中序遍历(递归)";
	myTree.in_traverse_recursion(myTree.getRoot());
	cout << endl;

	cout << "中序遍历(非递归)";
	myTree.in_traverse_non_recursion();
	cout << endl;

	cout << "后序遍历(递归)";
	myTree.post_traverse_recursion(myTree.getRoot());
	cout << endl;

	cout << "后序遍历(非递归)";
	myTree.post_traverse_non_recursion();
	cout << endl;

	cout << "层次遍历";
	myTree.level_traverse_queue();
	cout << endl;
	return 0;
}

在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值