数据结构—树

一.树的基本概念和性质

树的基本概念

节点(Node)

树中的每个元素称为一个节点,每个节点包含一个值(或称为数据)和若干指向其子节点的引用。

根节点(Root)

树的最顶层的节点,没有父节点。

子节点(Child):

直接连接到另一个节点的节点。

父节点(Parent)

有一个或多个直接子节点的节点。

叶节点(Leaf)/终端节点(Terminal Node)

没有子节点的节点。

子树(Subtree)

任何一个节点及其所有后代构成的树。

兄弟节点(Sibling):

拥有相同父节点的节点。

边(Edge)

连接两个节点的线段,表示它们之间的父子关系。

路径(Path)

从一个节点到另一个节点经过的节点序列。

祖先(Ancestor):

从根节点到某个节点的路径上的所有节点。

后代(Descendant)

某个节点的所有子节点、子节点的子节点等。

森林(Forest)

由多棵树构成的集合。


树的性质

层次性(Hierarchical)

树是一种层次结构,每个节点都有一个父节点(除了根节点),可以有零个或多个子节点。

递归性(Recursive)

树的定义是递归的,即一棵树是由多棵子树构成的。

深度(Depth)

从根节点到某个节点的路径上的边数称为该节点的深度。

高度(Height)

从某个节点到最远叶节点的最长路径上的边数称为该节点的高度。树的高度是从根节点到最远叶节点的路径长度。

有序性(Ordering)

在某些特定类型的树(如二叉搜索树)中,节点的子树之间存在顺序关系。

节点数与边数的关系

在任何树中,节点数比边数多1。即如果树有n个节点,那么它有n-1条边。


树的常考性质

  • 常见考点1: 结点数 = 总度数 + 1

                 树的度——各结点的度的最大值     m叉树——每个结点最多只能有m个孩子的树

度为m的树m叉树
任意结点的度 ≤ m (最多m个孩子)任意结点的度 ≤ m (最多m个孩子)
至少有一个结点度 = m (有m个孩子)允许所有结点的度都<m
一定是非空树,至少有m+1个结点可以是空树
  • 常见考点2: 度为m的树, m叉树的区别
  • 常见考点3: 度为m的树第i层至多有 m^i-1 个结点( i ≥ 1 ) 
  •                    m叉树第i层至多有 m^i-1 个结点( i ≥ 1 ) 
  • 常见考点4: 高度为h的m叉树至多有mʰ-1 / m -1 个结点
  • 常见考点5: 高度为h的m叉树至少有h个结点。
  •                    高度为h、度为m的树至少有h+m+1个结点
  • 常见考点6: 具有n个结点的m叉树的最小高度为[log(n(m-1)+1)]


二.二叉树

基本概念

  • 节点(Node):二叉树中的每个元素称为一个节点,每个节点包含数据部分和两个指向其子节点的引用(通常称为左子节点和右子节点)。
  • 根节点(Root):二叉树的最顶层节点,没有父节点。
  • 叶节点(Leaf):没有子节点的节点。
  • 子树(Subtree):任何节点及其后代构成的树。
  • 深度(Depth):从根节点到某个节点的路径长度(边的数量)。
  • 高度(Height):从某个节点到最远叶节点的最长路径长度(边的数量)。

 是n个结点的有限集合 可为空二叉树 也可由一个根结点和两个互不相交的左子树右子树组成 

 特点: 1.每个结点至多只能有两棵子树 2.左右子树不能颠倒(二叉树是有序树) 

 二叉树的五种状态:    空二叉树    只有左子树    只有右子树     只有根节点    左右子树皆有


二叉树的常考性质

二叉树

  • 常见考点1:非空二叉树中度为0,1,2的结点数分别为n0,n1,n2。则n0=n2+1(叶子结点比二分支结点多一个)
  • 常见考点2:二叉树第i层至多有2^i-1个结点
  •                   m叉树第i层至多有m^i-1个结点
  • 常见考点3:高度为h的二叉树至多有 2ʰ - 1 (满二叉树)

       (树的常考性质4) 高度为h的m叉树至多有mʰ-1 / m -1 个结点 (m=2得上)

完全二叉树

  • 常见考点1:具有n个(n>0)结点的完全二叉树的高度h为[[log(n+1)] 或 [[logn]+1

几种特殊的二叉树

满二叉树

  • 不存在度为1的结点
  • 只有最后一层有叶子结点
  • 结点i的左孩子为2i,右孩子为2i+1父节点为[i / 2]   (以下i均从1开始)

完全二叉树

  • 除了最后一层外,每一层都被完全填满,且所有节点都尽可能地向左。
  • 最多只有一个度为1的结点
  • i ≤ [n/2]为分支结点 ,i ≥ [n/2]为叶子结点

二叉排序树

  • 左子树上的所有结点的关键字小于根结点的关键字
  • 右子树上的所有结点的关键字大于根结点的关键字
  • 左右子树又各是一颗二叉排序树

平衡二叉树

  • 树上任意结点的左子树,右子树的高度/深度差都不超过 1。
  •  AVL 树和红黑树是最常见的平衡二叉树。

二叉树的存储结构

  • 顺序存储

   一定要把二叉树的结点编号与完全二叉树对应起来

   最坏的情况:高度为h且只有h个结点的单支树(所有结点只有右孩子),也至少需要2ʰ-1个存储     单元

#define MaxSize 100
struct TreeNode
{
	int data;
	bool isEmpty;
};
void InitTreeNode(TreeNode* t)
{
	for (int i = 0; i < MaxSize; i++)
	{
		t->isEmpty = true;
	}
}
//几个重要的基本操作
//i的左孩子 2i
//i的右孩子 2i+1 
//i的父节点 [i/2]
//i所在的层次 [log2(n+1)]或[log2n]+1
int main()
{
	TreeNode t[MaxSize];
	InitTreeNode(t);

	return 0;
}
  • 链式存储
  • n个结点的二叉链表共有n+1个空链域

struct ElemType
{
	int value;
};
typedef struct BinTree
{
	ElemType data; //数据域
	struct BinTree* lchild;//左指针
	struct BinTree* rchild;//右指针
}BiTNode,*BiTree;
int main()
{	
	//定义一棵空树
	BiTree root = NULL;
	
	//插入根节点
	root = (BiTree)malloc(sizeof(BiTree));
	root->data = { 1 };
	root->lchild = NULL;
	root->rchild = NULL;

	//插入新结点
	BiTNode *p= (BiTNode*)malloc(sizeof(BiTNode));
	p->data = { 2 };
	p->lchild = NULL;
	p->rchild = NULL;
	root->lchild = p;
	return 0;
}

 二叉树的遍历

  • 先序

     

     嵌套使用  根 (根/左子树) (根/右子树)

           根 [ 根 (根/左子树) (根/右子树))  (根 (根/左子树) (根/右子树)) ...

    

struct ElemType
{
	int value;
};
typedef struct BinTree
{
	ElemType data; //数据域
	struct BinTree* lchild;//左指针
	struct BinTree* rchild;//右指针
}BiTNode,*BiTree;
void visit(BiTree t)
{

}
void PreOrder(BiTree T)
{
	if (T != NULL)
	{
		visit(T);
		PreOrder(T->lchild);
		PreOrder(T->rchild);
	}
}
  • 中序

     

     嵌套使用 (/左子树) 根  (/右子树)

           ((/左子树) 根  (/右子树)) 根  ((/左子树) 根  (/右子树)) ...

      

void InOrder(BiTree T)
{
	if (T != NULL)
	{
		PreOrder(T->lchild);
		visit(T);
		PreOrder(T->rchild);
	}
}
  • 后序

     

     嵌套使用 (/左子树)(/右子树)根

           ((/左子树)(/右子树)根)((/左子树)(/右子树)根)根...

void PostOrder(BiTree T)
{
	if (T != NULL)
	{
		PreOrder(T->lchild);
		PreOrder(T->rchild);
		visit(T);
	}
}
  • 层次遍历

   算法思想:

  1. 初始化一个辅助队列
  2. 根结点入队
  3. 若队列非空,则队头结点出队,访问该结点并将其左右孩子插入队尾
  4. 重复3直至队列为空
void LevelOrder(BiTree T)
{
	LinkQueue Q;
	InitQueue(Q);
	BiTree p;
	EnQueue(Q, T);
	while (!isEmpty(Q))
	{
		DeQueue(Q, p);
		visit(p);
		if (p->lchild != NULL)
		{
			EnQueue(Q, p->lchild);
		}
		if (p->rchild != NULL)
		{
			EnQueue(Q, p->rchild);
		}
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值