【数据结构】C++实现之二叉树结构(一)

1. 概念

1.1 二叉树的定义
二叉树( Binary Tree)是n(n≥0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成,且具有以下特点:

1.2 二叉树的特点
1)每个结点最多有两颗子树,结点度最大为二
2)左子树和右子树是有顺序的,次序不能颠倒
3)即使某结点只有一子树,也要区分左右子树
4)具有5种形态:空二叉树、只有一个根节点、根节点只有左子树、根节点只有右子树、根节点既有左子树也有右子树

1.3 特殊的二叉树
1)斜树:所有结点只有左子结点 或 只有右子结点
2)满二叉树:所有的分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样就是满二叉树。就是完美圆满的意思,关键在于树的平衡
在这里插入图片描述
3)完全二叉树:对一棵具有n个结点的二叉树按层序排号,如果编号为i的结点与同样深度的满二叉树编号为i结点在二叉树中位置完全相同,就是完全二叉树。满二叉树必须是完全二叉树,反过来不一定成立。 【看着树的示意图,心中默默给每个结点按照满二二叉树的结构逐层顺序编号,如果编号出现空档,就说明不是完全二叉树,否则就是】
在这里插入图片描述
https://www.cnblogs.com/polly333/p/4740355.html

2. 二叉树的性质

2.1 一般二叉树性质
1)在二叉树的i层上,至多有2^i-1个节点(i>=1)
2)深度为K的二叉树上最多有2^k-1个结点(k>=1)
3)对于任何一棵二叉树T,如果叶节点个数为n0,度数为2的节点个数为n2,则有: n0 = n2 + 1在这里插入图片描述
终端结点数其实就是叶子结点数,而一-棵二叉树,除了叶子结点外,剩下的就是度为1或2的结点数了,我们设n1为度是1的结点数。则树T结点总数n=no+n1+n2。

2.2 完全二叉树特有性质
1)具有n个结点的完全二叉树的深度为[log2 n]+1 ([x]表示不大于x的最大整数
2)如果有一颗有n个节点的完全二叉树的节点按层次序编号,对任一层的节点i(1<=i<=n)有:

1.如果i=1,则节点是二叉树的根,无双亲,如果i>1,则其双亲节点为[i/2],向下取整
2.如果2i>n那么节点i没有左孩子,否则其左孩子为2i
3.如果2i+1>n那么节点没有右孩子,否则右孩子为2i+1

在这里插入图片描述

3. 二叉树的存储结构

3.1 顺序存储
1)由于二叉树的特殊性,使用顺序结构也可以实现。但又对于另一些特殊二叉树,这种方式又有点浪费空间
在这里插入图片描述
3.2 链式二叉树
1)指针域 以及两个孩子域

在这里插入图片描述

#define MAXSIZE 100
typedef int ElemType;
struct BiTree{
	ElemType data;       //数据域
	BiTree *leftchild;   //左指针域
	BiTree *rightchild;  //右指针域
};

4. 二叉树的遍历

4.1 遍历分类及其原理
二叉树的遍历( traversing binary tree )是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问一次且仅被访问一次。
1)前序遍历:若二又树为空,则返回,否则先访问根结点,然后前序遍历左子树,再前序遍历右子树【根-左-右
2)中序遍历:若二又树为空,则返回,否则先中序遍历左子树,然后访问根结点,再中序遍历右子树【左-根-右
3)后序遍历:若二又树为空,则返回,否则先后序遍历左子树,然后后序遍历右子树,再访问根【左-右-根
4)层序遍历:自根结点开始,自上而下,逐层遍历
在这里插入图片描述

1、已知前序遍历序列和中序遍历序列, 可以唯一确定1棵二叉树
2、已知后序遍历序列和中序遍历序列, 可以唯一确定1棵二叉树

4.2 遍历二叉树的实现

#define MAXSIZE 100
typedef int ElemType;
struct BiTree{
	ElemType data;       //数据域
	BiTree *leftchild;   //左指针域
	BiTree *rightchild;  //右指针域
};
typedef BiTree  *BiTreeptr;

//二叉树前序遍历
void PreoderBiTree(BiTreeptr t)
{
	if (t == NULL)
		return;
	printf("%d ", (t->data));
	PreoderBiTree(t->leftchild); // 遍历左树
	PreoderBiTree(t->rightchild); // 遍历右树
}



//二叉树中序遍历
void InoderBiTree(BiTreeptr t)
{
	if (t == NULL)
		return;
	InoderBiTree(t->leftchild); // 遍历左树
	printf("%d ", (t->data));
	InoderBiTree(t->rightchild); // 遍历右树
}


//二叉树后序遍历
void PostoderBiTree(BiTreeptr t)
{
	if (t == NULL)
		return;
	PostoderBiTree(t->leftchild); // 遍历左树
	PostoderBiTree(t->rightchild); // 遍历右树
	printf("%d ", (t->data));
}

5. 二叉树的建立

1)那么我们如何在内存中生长一棵二叉链表的二叉树呢? 需要进行扩展
在这里插入图片描述

//以前序遍历方式生成二叉链的二叉树
void CreateBiTree(BiTreeptr *t)
{
	char ch;     
	cin >> ch;     //ch存储的是字符的ASCII码,以整形存储
	cout << ch << endl;
	if (ch == '#')
		*t = NULL;
	else
	{
		*t = new BiTree;
		if (!*t)
			exit(OVERFLOW);
		(*t)->data = ch;           //生成根节点
		CreateBiTree(&(*t)->leftchild);  //构造左子树
		CreateBiTree(&(*t)->rightchild); //构造右子树
	}
}
发布了30 篇原创文章 · 获赞 6 · 访问量 5690

猜你喜欢

转载自blog.csdn.net/qq_32643313/article/details/105414783