从小白开始学习树,二叉树--(本文C++ )


在这里插入图片描述

  • 树的基本概念:由一个或多个(n>=0)结点组成的有限集合T,有且仅有一个结点称为根(root),当n>1 时,其余结点分为m(m>=0)个互不相交的有限集合T1,T2,…,Tm。每个集合本身又是棵树,被称为这个根的子树。

  • 树的结构特点:
    1.非线性结构,有一个直接前驱,但可能有多个直接后继(1:n);
    2.树的定义具有递归性,即树中有树;
    3.树可以为空,即节点个数为0;

  • 其他概念
    1.根->根节点(没有前驱);
    2.叶子->终节点(没有后继);
    3.森林->指m棵不相交的树的集合;
    4.节点的度->一个节点含有的子树个数;
    5.树的度->所有节点度的最大值;
    6.树的高度深度->树中节点的最大层次;
    7.有序树->节点各子树从左至右有序,不能互换(左为第一);
    8.无序树->节点各子树可以互换位置;

    上图中树的节点数=13,树的度=3,树的深度=4;

    树的表示方法:

  • 顺序存储 :双亲表示法

struct Node{
	int data;  //节点的值
	int parent; //能找到父节点,
}
  • 链式存储:孩子表示法
struct ChildNode{
	int data;  //节点的值
	ChildNode* c1,c2,...,cn;//此处是一个链表
}

ChildNode D;
D.ChildNode*链表
  • 左子右兄:把普通树转化成二叉树
    以上图为例:

在这里插入图片描述

1.A的左孩子为B,没有兄弟
在这里插入图片描述
2.B的左孩子为E,右兄弟为C
在这里插入图片描述
3.E的左孩子为K,右兄弟为F
在这里插入图片描述
以此类推得二叉树:
在这里插入图片描述

  • 定义:n(n>=0)个节点的有限集合,由一个根节点以及两棵互不相交的,分别称为左子树和右子树的二叉树组成;

  • 逻辑结构: 一对二(1:2);

  • 基本特征:
    1.每个节点最多只有两棵子树;
    2.左子树和右子树不能颠倒(有序树);

  • 样子:
    在这里插入图片描述

  • 性质:
    1.在二叉树的第i层上至多有2^(i-1)个节点(i>0);
    2.深度为k的二叉树至多有2^(k)-1个节点(k>0);
    3.对于任何一个二叉树,若度为2的节点数有n2个,则叶子数(n0)必定为n2+1(即n0=n2+1);(n0为度为0的节点)

  • 结构体:

typedef struct TreeNode {
	char val;  //该节点表示的值
	struct TreeNode* LChild;  //左孩子
	struct TreeNode* RChild;  //右孩子
}Node;
  • **满二叉树:**一棵深度为k且有2^k-1个节点的二叉树;
  • **完全二叉树:**除了最后一层,其他层上的节点都达到最大值,当最后一层未满时,节点全部靠左侧;
  • 具有n个节点的完全二叉树的深度必为[log2^n]+1
  • 对完全二叉树,若从上至下,从左至右编号,则编号为i的节点,其左孩子编号必为2i,其右孩子编号必为2i+1;其双亲的编号必为i/2(i=1 时为根除外)
    在这里插入图片描述

二叉树创建

  • 二叉树的创建可以用先序和中序创建

  • 通过(中,先)能确定一棵树

  • 通过(中,后)能确定一棵树

  • 通过(先,后)不能确定一棵树

    例:
    先序遍历结果:A,D,E,B,C,F
    中序遍历结果:D,E,A,C,F,B
    可得树为
    在这里插入图片描述

  • 下面重点的#号创建法:

在这里插入图片描述
其中#表示NULL
如果先序遍历,结果为:124###3##

//递归的创建
Node* CreateTree()
{
	Node* root ;    //节点
	char ch;			//节点的值
	cin >> ch;		//输入节点的值
	if (ch == '#') {		//判断节点的值是否为#
		root= NULL;	//若是则是空节点
	}
	else {
	    root = new Node;
		root->c = ch;			//先序创建       根
		root->LChild = CreateTree();//        左
		root->RChild = CreateTree();//       右
	}
	return root;
}

既然我们已经创建出一棵属于自己的二叉树了,那我们就要看看它长什么样子

二叉树的遍历

在这里插入图片描述
以此图为例

  • 先序遍历 根->左->右
    ABCDEFGH

  • 中序遍历 左->根->右
    BDCEAFHG

  • 后序遍历 左->右->根
    DECBHGFA
    以先序为例:

//递归遍历
void Show(Node* root)
{
	if (root == NULL)
	{
		return;
	}
		cout << root->c;//     	  根
		Show(root->LChild);//     左
		Show(root->RChild);//     右
}

调换上面代码的顺序就可以达到不同类型的遍历
中序:

void Show(Node* root)
{
	if (root == NULL)
	{
		return;
	}
		Show(root->LChild); //    左
		cout << root->c; //		  根
		Show(root->RChild);//     右
}

树的非递归遍历

  • 树的非递归遍历是通过栈来实现的,这里先不接受

求叶子节点:

上面已经说过叶子节点是:终节点(没有后继);

在这里插入图片描述
大家很显然就能看得出这棵树的叶子节点是3

那么我们就**递归判断节点的左右子节点是否为空**就ok

void GetLeafNode(Node* root,int* count)     // count用来计数
{
	if (root == NULL)
	{
		return;
	}
	if (root->LChild == NULL && root->RChild == NULL)
	{
		(*count)++;
	}
	GetLeafNode(root->LChild,count);
	GetLeafNode(root->RChild,count);
}

求树的深度:

高度和深度是相反的表示,深度是从上到下数的,而高度是从下往上数

我们先来看看高度和深度的定义,某节点的深度是指从根节点到该节点的最长简单路径边的条数,而高度是指从该节点到叶子节点的最长简单路径边的条数。

注意:这里边的条数是规定根节点的深度和叶子节点的高度是0;

所以树的深度和高度是相等的,而对其他节点来说深度和高度不一定相等。

很多教材或者书对深度的起点有不同的说法,有的说法是从0,开始,有的是从1开始
这里我们从1开始

在这里插入图片描述
可以看出次树的深度和高度为4

int GetDepth(Node* root)
{
	if (root == NULL)
	{
		return -1;
	}
	return 1 + max(GetDepth(root->LChild), GetDepth(root->RChild));
}

线索二叉树:https://blog.csdn.net/alzzw/article/details/97423394
哈夫曼树:https://blog.csdn.net/alzzw/article/details/97809047
二叉搜索(排序)树;https://blog.csdn.net/alzzw/article/details/97563011
平衡二叉树:https://blog.csdn.net/alzzw/article/details/97613193
B树~B+树:https://blog.csdn.net/alzzw/article/details/97633941
红黑树:https://blog.csdn.net/alzzw/article/details/97770753

到这里有关树的一些基础知识就讲解完了,如果喜欢请收藏关注博主,你的支持是我继续的动力,谢谢了!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿尔兹

如果觉得有用就推荐给你的朋友吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值