当前位置:   article > 正文

二叉树的建立和遍历C++_binode* buildtree();

binode* buildtree();

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();


};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

⑵二叉树的建立

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

⑶前序遍历

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

⑷中序遍历

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);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

⑸后序遍历

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);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

⑹层次遍历

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);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

⑺测试

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/557755
推荐阅读
相关标签
  

闽ICP备14008679号