数据结构笔记(五)树与二叉树

树形结构,主要弄懂计算树的深度、结点数的计算,还要弄清一些容易混淆的概念如深度与高度,树和森林与二叉树的转换等,因为在我刚开始学习时找到的教学都是概念为主,没有足够的图来辅助理解,所以今天主要整理树和二叉树的概念及遍历代码,前面介绍到的广义表也可以用二叉树表示。

叶子结点
没有子结点的结点称为叶子结点,如图中的3,5,6,7

树的度
结点的分支数称为该结点的度,如下图结点1的度为3,结点2的度为2. 树的度是所有结点中最大的度,这棵树的度为3

在这里插入图片描述

树的深度
从上往下,以根节点为第一层,往下能达到的最大层数称为树的深度,图片中树的深度为4,结点5的深度为3

树的高度
从下往上,叶子结点为第一层,最大层数称为树的高度。但相同深度的结点,其高度不一定相同。如图中结点5的深度为3,而高度为2



二叉树

普通二叉树:

在第 i 层至多2 i-1 个结点,至少1 个结点

深度为h的二叉树,至多有 2h - 1 个结点 ,至少有h个结点。

若有n0个叶子结点,n1个度为1的结点,n2个度为2的结点,则n0 = n2+1,
总结点数N = n0+n1+n2 或 N = n1+2n2+1

因为二叉树的左右结点不一样,因为结点放在不同位置的时候二叉树形态不同,3个结点便能有以下5中形态的二叉树

在这里插入图片描述

三种遍历方法

在这里插入图片描述

前序遍历:从根结点开始,遍历左孩子再遍历右孩子。若孩子是子树,则重复以上步骤。如图的遍历序列为1 2 4 3 6 8 9 7

中序遍历:从最左侧的结点开始,依次遍历左孩子、根结点、右孩子。若孩子是子树,则重复步骤。如图中序序列为4 2 1 8 6 9 3 7

后序遍历:从最左侧的结点开始,依次遍历左孩子、右孩子、根结点。若孩子是子树。重复步骤。图中后序序列为4 2 8 9 6 7 3 1

#include<stdlib.h>
#include<stdio.h>

typedef struct Bitree{//定义树的结构体
	char data;
	Bitree *lchild;
	Bitree *lchild;
}

Bitree* create(){//创建树
	char ch;
	Bitree *T;
	scanf("%c",&ch);
	if(ch == '#')//若输入#,则该结点为空
		T = NULL;
	else{//先序遍历创建
	T = (Bitree*)malloc(sizeof(Bitree));
	T->data = ch;//将元素赋值给数据域
	T->lchild = create();//左右子树递归上述操作
	T->rchild = create();
	}
	return T;
}

void Insert(Bitree *T,char x){//二叉树的插入
	if(T == NULL){//若树为空,直接插入
		T = (Bitree*)malloc(sizeof(Bitree));
		T->data = x;
		}
	else if(x<T->data){//若插入的数比根结点小,则插入左子树
		if(T->lchild!=NULL)//若非空,则递归调用函数
			Insert(T->lchild,x);
		else//若左子树空,直接插入
		T->lchild->data = x;
		}
	else if(x>T->data){//比根结点大,插入右子树
		if(T->rchild!=NULL)
			Insert(T->rchild,x);
		else
		T->rchild->data = x;
		}
	}

void pre(Bitree *T){//先序遍历打印结点
	if(T == NULL)
		printf("NULL\n");
	else{
		printf("%c",T->data);
		pre(T->lchild);
		pre(T->rchild);
		}
}

void mid(Bitree *T){//中序遍历打印结点
	if(T == NULL)
		printf("NULL\n");
	else{
		printf("%c",T->data);
		mid(T->lchild);
		mid(T->rchild);
		}
}
	
void post(Bitree *T){//后序遍历打印结点
	if(T == NULL)
		printf("NULL\n");
	else{
		printf("%c",T->data);
		ppst(T->lchild);
		post(T->rchild);
		}
}

前序遍历是 根、左、右
中序遍历是 左、根、右
后序遍历是 左、右、根
易得:

1.若前序和中序序列相同,则该二叉树是所有结点只有右子树;
2.若中序和后序序列相同,则所有结点只有左子树;
3.若前、中、后序都相同,则该二叉树只有根节点;
4.若前序和后序遍历正好相反,则为空或只有一个结点。
5.知道中序序列后,给出其他任意一种序列都能画出完整的二叉树
二叉线索树

二叉线索树利用了空指针域,提升了遍历速度,但插入和删除的难度加大。假设有n个结点,必有n+1个空指针域。二叉线索树通过利用这些空指针域指向该结点的前驱和后继。以下图的二叉树为例子,简单介绍中序和后序线索二叉树。

在这里插入图片描述
如图可得二叉树的遍历序列:
中序:5 2 1 7 4 3
后序:5 2 7 3 4 1
结点5 7 3是叶子结点,因此其左右指针域皆为空。左孩子为空,则其指向该遍历顺序的前驱右孩子为空,则指向该遍历的后继。无前驱或后继则指向空。

中序线索树
在这里插入图片描述

后序线索树
在这里插入图片描述

完全二叉树

一颗二叉树,从上到下,从左到右对结点进行编号,如果每个结点的编号都与满二叉树的该位置的编号相同,则其为完全二叉树。就是说,如果一个结点,它没有左子树,那它一定没有右子树。

深度为h的完全二叉树最多有2h - 1个结点,最少有2h-1个结点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值