《C/C++数据结构与算法》第二讲——二叉树

第1节    二叉树的概念及其性质

2.1.1  二叉树的概念

        什么是二叉树?顾名思义,它是每个非叶子结点最多只能有两个儿子的树结构。为了方便研究,我们对结点的两个儿子进行命名和编号,将左边的结点称为左儿子(left child,简写为lchild或lc),右边的结点称为右儿子(right child,简写为rchild或rc),那么以左右儿子为根的子树分别称为“左子树”(left subtree,简写为ltree)和“右子树”(right subtree,简写为rtree)。

        一般情况下左右儿子有序,不能相互颠倒。

2.1.2  二叉树的性质

        由于二叉树结构的优美性,因此具有很好的性质。

        性质1:若二叉树的叶子数为n_0,度为2的结点数为n_2,则n_0=n_2+1

        这个性质表明在二叉树中,叶子结点的个数与度为1的结点个数无关。

        性质2:深度为k的二叉树,最多只有2^k-1个结点。 

        特别地,深度为k,且有2^{k-1}个结点的二叉树,称为满二叉树。这种树的特点是每一层上的结点数都是最大结点数。而在一棵二叉树中,除最后一层外,其余层都是满的,并且最后一层要么是满的,要么是在右边缺少连续若干结点,此二叉树称为完全二叉树。显然,深度为k的完全二叉树,至少有2^{k-1}个结点,至多有2^k-1个结点。   

        性质3:具有n个结点的完全二叉树的深度为log_2n+1

        性质4:若将完全二叉树的每个结点从上至下,从左至右进行编号,那么,对于标号为x的点,若x存在左儿子,则左儿子的编号为2x;若x存在右儿子,则右儿子的编号为2x+1。反之,若x有父亲,则父亲的编号为\left\lfloor\frac{x}{2}\right\rfloor。     

第2节    二叉树的存储方法

2.2.1  二叉树的儿子表示法

        对每一个结点,存储该结点的左右儿子。

struct node
{
	node *lc,*rc;
	node()
	{
		lc=rc=NULL;
	}
};

2.2.2  二叉树的数组表示法

int ch[MAXN][2];//ch[x][0]表示x的左儿子,ch[x][1]表示x的右儿子

2.2.3  完全二叉树的数组表示法

        根据之前所讲的完全二叉树的性质,只要确定了结点个数n,完全二叉树的形态也就确定了,对于结点x,它的左儿子是2x,右儿子是2x+1,父亲是\left\lfloor\frac{x}{2}\right\rfloor。因此无需存储任何和树的形态有关的信息,只需要用一个一维数组来表示每个结点上的信息。这种优美的存储方法在接下来“二叉堆”的内容中将非常有用。  

第3节    二叉树的遍历

        前序、中序、后序遍历是二叉树的三种遍历方式,本质上都属于DFS(深度优先搜索),它们之间的区别仅仅在于根在遍历中的出现顺序:
        前序遍历:根—左—右。

void preorder(node *now)
{
	if(now==NULL)
		return;
	std::cout<<now->val<<' ';
	preorder(now->lc);
	preorder(now->rc);
}

        中序遍历:左—根—右。

void inorder(node *now)
{
	if(now==NULL)
		return;
    inorder(now->lc);
	std::cout<<now->val<<' ';
	inorder(now->rc);
}

        后序遍历:左—右—根。

void postorder(node *now)
{
	if(now==NULL)
		return;
    postorder(now->lc);
	postorder(now->rc);
	std::cout<<now->val<<' ';
}

        除了以上三种遍历方式以外,还有一种被称为层序遍历的遍历方式,本质上属于BFS(广度优先搜索)。

void bfs(node *root)
{
	std::queue<node*> q;
	q.push(root);
	while(q.size())
	{
		node *now=q.front();
		q.pop();
		if(now==NULL)
			continue;
		std::cout<<now->val<<' ';
		q.push(now->lc);
		q.push(now->rc);
	}
}

        【例2.3.1】美国血统

        输入一棵二叉树的中序遍历和前序遍历,输出该树的后序遍历。

        【例2.3.2】新二叉树

        输入一棵二叉树,输出其前序遍历。

        【例2.3.3】求先序排列

        输入一棵二叉树的中序遍历和后序遍历,输出该树的前序遍历。

        【例2.3.4】二叉树深度

        输入一棵二叉树,输出其深度。

        【例2.3.5】遍历问题

        输入一棵二叉树的前序遍历和后序遍历,输出可能的中序遍历的总数。

第4节    树、森林与二叉树的转化

2.4.1  儿子兄弟表示法

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值