数据结构 第六章(学习笔记二(二叉树))

二叉树的定义

二叉树是有限的结点集合 (递归定义 )
① 这个集合或者是空;
② 或者由一个根结点和两颗互不相交的称为 左子树右子树 的二叉树组成。

二叉树的五种基本形态

二叉树和二次树区别

① 度不同

度为2的树要求每个结点最多只能有两棵子树,并且至少有一个结点有两棵子树。二叉树的要求是度不超过2,结点最多有两个叉,可以是1或者0。

② 分支不同

度为2的树有两个分支,但分支没有左右之分;一棵二叉树也有两个分支,但有左右之分,左右子树的次序不能随意颠倒。

③ 次序不同

度为2的树从形式上看与二叉树很相似,但它的子树是无序的,而二叉树是有序的。即在一般树中若某结点只有一个孩子,就无需区分其左右次序,而在二叉树中即使是一个孩子也有左右之分。

两种特殊的二叉树

满二叉树

在一棵二叉树中:
① 如果所有分支结点都有分支结点;
② 并且叶结点都集中在二叉树的最下一层。

完全二叉树

完全二叉树 实际上是对应的 满二叉树 删除叶结点层最右边若干个节点得到的。

二叉树的性质

性质1

在二叉树的第i层上至多有2^(i-1)个结点(i>=1)。

性质2

深度为k的二叉树至多有2^k-1个结点(k>=1)。

性质3

对任何一颗二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。

性质4

具有n个节点的完全二叉树的深度为

性质5

二叉树的存储结构

二叉树的顺序存储结构

① 对于 完全二叉树 来说,期顺序存储是十分合适的。
② 对于 一般的二叉树 ,特别是对于那些单分支结点较多的二叉树来说是很不合适的,因为可能只有少数的存储单元被利用,特别是对退化的二叉树(即每个结点都是单分支的),空间浪费更是惊人。
③ 在顺序存储结构中,找一个结点的双亲和孩子都很容易。

二叉树的链式存储结构

借鉴 树的孩子链存储结构 → 二叉树的链式存储结构

typedef struct{
	TElemType data;
	struct BiTNode * lchild,* rchild;
}BiTNode,*BiTree;

二叉链存储结构的特点

① 除了指针外,二叉链比较节省存储空间。占用的存储空间与树形没有关系,只与树中结点个数有关。
② 在二叉链中,找一个结点的孩子很容易,但找其双亲不方便。
一棵树采用孩子兄弟链存储结构表示 → 二叉链。

二叉树的遍历

二叉树遍历的概念

二叉树的遍历是指按照一定次序访问树中所有结点,并且每个结点仅被访问一次的过程。
遍历是二叉树最基本的运算,是二叉树其他运算的基础。
二叉树的组成:

1. 先序遍历过程

先序遍历NLR二叉树的过程是:
① 访问根结点;
② 先序遍历左子树;
③ 先序遍历右子树。

2. 中序遍历过程

中序遍历LNR二叉树的过程是:
① 中序遍历左子树;
② 访问根结点;
③ 中序遍历右子树。

3. 后序遍历过程

中序遍历LNR二叉树的过程是:
① 后序遍历左子树;
② 后序遍历右子树;
③ 访问根结点。

二叉树的建立与遍历完整代码

#include<iostream>
using namespace std;

#define OK 1
#define ERROR 0
typedef char TElemType;

typedef struct BiTNode {
	TElemType data;
	struct BiTNode* lchild;//左孩子指针
	struct BiTNode* rchild;//右孩子指针
}BiTNode,*BiTree;

//先序遍历生成二叉树
void CreateBiTree(BiTree* T) {
	TElemType ch;
	scanf_s("%c", &ch,1);
	if (ch == '#')
		*T = NULL;
	else {
		*T = (BiTree)malloc(sizeof(BiTNode));
		if (!*T)
			cout<<"内存分配失败!"<<endl;
		(*T)->data = ch;
		CreateBiTree(&(*T)->lchild);//左子树
		CreateBiTree(&(*T)->rchild);//右子树
	}
}

//先序遍历二叉树
void PreOrderTraverse(BiTree T) {
	if (T == NULL)
		return;
	printf("%c ", T->data);
	PreOrderTraverse(T->lchild);
	PreOrderTraverse(T->rchild);
}

//中序遍历二叉树
void InOrderTraverse(BiTree T) {
	if (T == NULL)
		return;
	InOrderTraverse(T->lchild);
	printf("%c ", T->data);
	InOrderTraverse(T->rchild);
}

//后序遍历二叉树
void PostOrderTraverse(BiTree T) {
	if (T == NULL)
		return;
	PostOrderTraverse(T->lchild);
	PostOrderTraverse(T->rchild);
	printf("%c ", T->data);
}

//求树的深度
int BiTreeDeep(BiTree T) {
	if (T == NULL)
		return 0;
	else {
		int m = BiTreeDeep(T->lchild);
		int n = BiTreeDeep(T->rchild);
		if (m > n)
			return (m + 1);
		else
			return (n + 1);
	}
}

//求树的结点数
int BiTreeNodeCount(BiTree T) {
	if (T == NULL)
		return 0;
	else
		return BiTreeNodeCount(T->lchild) + BiTreeNodeCount(T->rchild) + 1;
}

//求树的叶子点数
int BiTreeLeafCount(BiTree T) {
	if (!T)
		return 0;
	if (!T->lchild && !T->rchild)
		return 1;
	else
		return BiTreeLeafCount(T->lchild) + BiTreeLeafCount(T->rchild);
}

int main() {
	BiTree T = NULL;
	cout<<"先序遍历生成二叉树:"<<endl;
	CreateBiTree(&T);
	cout<<"先序遍历:"<<endl;
	PreOrderTraverse(T);
	cout << endl;
	cout<<"中序遍历:"<<endl;
	InOrderTraverse(T);
	cout<<endl;
	cout<<"后序遍历:"<<endl;
	PostOrderTraverse(T);
	cout<<endl;
	int m = BiTreeDeep(T);
	cout<<"树的深度为:"<<m<<endl;
	int n = BiTreeNodeCount(T);
	cout<<"树的结点数为:"<<n<<endl;
	int k = BiTreeLeafCount(T);
	cout<<"树的叶子点数为:"<<k<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值