一、树的基本知识

1、定义:有且只有一个称为根的结点,有若干个互不相交的子树,这些子树本身也是树。

2、其组成:

  • 树是由节点和边组成
  • 每个节点只有一个父节点,但可以有多个子节点
  • 根节点没有父节点
  • 深度:从根节点到最底层节点的层数,根节点为第一层。
  • 叶子节点:没有子节点的节点
  • 度:子节点的个数

3、树的分类

  • 一般树:任意一个节点的子节点个数都不受限制。
  • 二叉树:任意一个节点的子节点个数最多两个,且子节点位置不可以更改
  • 森林:n个互不相交的树的集合

4、二叉树的分类(如下分类的前提是二叉树)

  • 一般二叉树
  • 满二叉树在不增加树的层数的情况下,无法再添加一个节点

             

  • 完全二叉树如果只是删除了满二叉树最底层最右边的连续若干个节点,这样形成的树就是完全二叉树。(必须是连续的)
  • 二叉搜索树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

         

【注】:完全二叉树的优缺点:方便查到该节点的深度、父节点、是否有子节点等;缺点是比较耗内存。

5、树的存储

(1)、二叉树的存储

  • 连续存储(即完全二叉树):以数组的方式来组织。要以数组的方式来存储,必须先将其转换成满二叉树,再转换成完全二叉树。
  • 链式存储:是用链表的形式,用指针来保存对应的节点地址。形式如下

(2)、一般树的存储

  • 双亲表示法(求父节点容易)
  • 孩子表示法(求子节点容易)
  • 双亲孩子表示法
  • 二叉树表示法

(3)、森林的存储

先将森林转化成二叉树,再进行存储。

6、树的应用

  • 树是数据库中数据组织的一种重要形式
  • 操作系统子父进程的关系本身是一棵树

二、树的操作(常常指二叉树)

1、二叉树的遍历:先序遍历、中序遍历、后序遍历

(1)、先序遍历:

  • 先访问根节点
  • 再先序访问左子树
  • 再先序访问右子树

(2)、中序遍历:

  • 先中序遍历左子树
  • 再访问根节点
  • 再中序遍历右子树

(3)、后序遍历:

  • 先中序遍历左子树
  • 再中序遍历右子树
  • 再访问根节点

2、已知二叉树的先序遍历、中序遍历、后续遍历中的任意一种,都无法还原二叉树的原始结构。但知道其中的两种序列(除掉 “先序+后序” 这种组合),即可求出该二叉树。【先序+中序、中序+后序 这两种组合可以唯一确定一个二叉树

(1)、已知二叉树的先序+中序。

(1-1)、先序:ABCDEFGH,中序:BDCEAFHG,求该二叉树及后序。

二叉树如下,后序为:DECB HGFA

(1-2)、先序:ABDGHCEFI,中序:GDHBAECIF,求该二叉树及后序

二叉树如下,后序为:GHDBEIFCA

(2)、已知二叉树的中序+后序

(2-1)、中序:BDCEAFHG,后序:DECBHGFA

二叉树如下。先序为:ABCDEFGH


三、链式二叉树的操作

1、如下图所示的链式二叉树的结构,对其进行创建和遍历

 

2、代码如下

#include<iostream>
#include<string>

using namespace std;

struct BTreeNode
{
	string data;
	BTreeNode* pLChild;
	BTreeNode* pRChild;
};


// 生成静态的二叉树链表
BTreeNode* CreateBTree()
{
	BTreeNode*  pA = new BTreeNode();
	BTreeNode*  pB = new BTreeNode();
	BTreeNode*  pC = new BTreeNode();
	BTreeNode*  pD = new BTreeNode();
	BTreeNode*  pE = new BTreeNode();

	pA->data = "A";
	pB->data = "B";
	pC->data = "C";
	pD->data = "D";
	pE->data = "E";

	pA->pLChild = pB;
	pA->pRChild = pC;

	pB->pLChild = pB->pRChild = NULL;

	pC->pLChild = pD;
	pC->pRChild = NULL;

	pD->pLChild = NULL;
	pD->pRChild = pE;

	pE->pLChild = pE->pRChild = NULL;

	return pA;
}

// 二叉树的三种遍历方式:先序、中序、后序

// 先序遍历二叉树 :ABCDE
void PreTraverseBTree(BTreeNode* pRNode)
{
	if (pRNode!=NULL)
	{
		cout << pRNode->data << endl;
		if (pRNode->pLChild!=NULL)
		{
			PreTraverseBTree(pRNode->pLChild);
		}
		if (pRNode->pRChild!=NULL)
		{
			PreTraverseBTree(pRNode->pRChild);
		}
		
	}
	/*   伪算法:
	
	if(根节点不为空)
	{
		先访问根节点
		if(左子树不为空)
		{
			再先序访问左子树
		}
		if(右子树不为空)
		{
			再先序访问右子树
		}			
	}
	*/
}

// 中序遍历二叉树:BADEC
void InterTraverseBTree(BTreeNode* pRNode)
{
	if (pRNode!=NULL)
	{
		if (pRNode->pLChild!=NULL)
		{
			InterTraverseBTree(pRNode->pLChild);
		}		
		cout << pRNode->data << endl;
		if (pRNode->pRChild!=NULL)
		{
			InterTraverseBTree(pRNode->pRChild);
		}
		
	}


	/*   伪算法:

	if(根节点不为空)
	{
		if(左子树不为空)
		{
			先中序遍历左子树
		}

		再访问根节点

		if(右子树不为空)
		{
			再中序遍历右子树
		}
	}
	*/

}


// 后序遍历二叉树:BEDCA
void PostTraverseBTree(BTreeNode* pRNode)
{
	if (pRNode!=NULL)
	{
		if (pRNode->pLChild!=NULL)
		{
			PostTraverseBTree(pRNode->pLChild);
		}
		if (pRNode->pRChild!=NULL)
		{
			PostTraverseBTree(pRNode->pRChild);
		}
		
		cout << pRNode->data << endl;
	}

	/*   伪算法:

	if(根节点不为空)
	{
		if(左子树不为空)
		{
			先中序遍历左子树
		}

		if(右子树不为空)
		{
			再中序遍历右子树
		}

		再访问根节点
	}
	*/

}

int main()
{
	BTreeNode* p = CreateBTree();

	cout << "先序遍历--------------\n";
	PreTraverseBTree(p);

	cout << "中序遍历----------------\n";
	InterTraverseBTree(p);

	cout << "后序遍历------------------\n";
	PostTraverseBTree(p);

	system("pause");
}

运行结果如下

  

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值