IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构---与树相关的知识 -> 正文阅读

[数据结构与算法]数据结构---与树相关的知识

有些图是网上找的,没有自己画

一: 树(了解就行)

1.1 概念

树是一种非线性的数据结构,它是由n(n>=0)个有限节点组成的一个具有层次关系的集合.
叫成树的原因: 看起来像是一棵倒着的树,它的根朝上,而叶子是朝下的.
树的一些特点:
a. 有一个特殊的节点,称为根节点,根节点没有前驱节点.
b. 除根节点外,其余的节点被分成M(M>0)个互不相交的集合T,T2,T3…Tm,其中每一个集合又是一棵与树类似的子树.
c. 一棵n个节点的树有n-1条边.
d. 除根节点外,每个节点有且仅有一个父节点
e. 子树是不能相交的.
f. 树是递归定义的.
在这里插入图片描述

1.2 一些与树相关的重要概念

在这里插入图片描述

节点的度: 一个节点含有子树的个数称为该节点的度
比如:上图中节点A的度为2,节点D的度为3.

树的度: 一颗树中,所有节点度的最大值称为树的度
比如:上图中树的度为3

叶子节点或终端节点: 度为0的节点称为叶子节点或者终端节点
比如:上图中的叶子节点有:F,G,H,I,J.

双亲节点或父节点: 如果一个节点含有子节点,这个节点就称为子节点的父节点或者双亲节点.
比如:上图中的A是B,C的父节点.

孩子节点或子节点: 一个节点含有的子树的根节点称为该节点的子节点.
比如:上图中的B,C是A的孩子节点.

根节点: 树种没有双亲的节点.(位于食物链顶端的节点)
比如:上图中的A节点.

节点的层次: 从根开始定义起,根为第一层,根的子节点为第二层,依次类推

树的高度或深度: 树中节点的最大层次.
比如:上图中树的深度为4

非终端节点或分支节点: 度不为0的节点
比如:上图中的B,D节点

兄弟节点: 具有相同父节点的节点称为兄弟节点
比如:上图中的G,H,I节点

堂兄弟节点: 双亲在同一层的节点互为堂兄弟
比如:上图中的D,E节点

节点的祖先: 从根节点到该节点所经分支上的所有节点
比如:G节点的祖先节点是A,B,D节点.而A节点是所有节点的祖先节点.

子孙节点: 以某节点为根的子树中任一节点都称为该节点的子孙.
比如:上图中D节点的子孙节点是G,H,I.而所有节点都是A的子孙节点.

森林: 有m(m>0)棵互不相交的树组成的集合称为森林.

1.3 树的表示形式

树有很多种表现形式,但是最常用的是这里的孩子兄弟表示法
a.双亲表示法

节点既要存储值域,还必须表示其双亲的位置.
优点: 快速知道该节点的双亲.
缺点: 无法快速知道该节点的孩子.

class Node{
	int value;		//存储的数据
	Node parent;	//指向父节点
}

b.孩子表示法

节点既要存储值域,还要表示与孩子之间的关系.
优点: 快速知道该节点的孩子.
缺点: 无法快速知道该节点的双亲

class Node{
	int value;		//存储的数据
	Node left;		//指向左孩子,常常代表左孩子为根的整棵左子树
	Node right;		//指向右孩子,常常代表右孩子为根的整棵右子树
}

c.孩子双亲表示法

将孩子表示法和双亲表示法结合起来了.

class Node{
	int value;		//存储的数据
	Node left;		//指向左孩子,常常代表左孩子为根的整棵左子树
	Node right;		//指向右孩子,常常代表右孩子为根的整棵右子树
	Node parent;	//当前节点的父节点.
}

d.孩子兄弟表示法

在这个节点中,既要保存值域,还要保存下一个兄弟在哪一个位置.

class Node{
	int value;			//树中存储的数据
	Node firstChild;	//第一个孩子的引用
	Node nextBrother;	//下一个兄弟的引用
}

在这里插入图片描述

二: 二叉树(非常重要,重点掌握)

2.1 概念

满足: 1.为空树时,是二叉树 2.由根节点+左子树+右子树组成.

一棵二叉树是节点的一个有限集合:
a.集合可以为空: 表示这是一棵空树
b.不为空: 由一个根节点加上两棵分别称为左子树和右子树的二叉树组成
c.二叉树不存在度大于2的节点(此节点的孩子子节点个数只能<=2)
d.二叉树的子树有左右之分,次序不能颠倒,依次二叉树是有序树.
在这里插入图片描述

注意: 对于任意的二叉树都是由以下集中情况复合而成的.
在这里插入图片描述

2.2 两种特殊的二叉树

2.2.1 满二叉树

一棵二叉树,如果每层的节点数都能达到最大值,则这棵二叉树就是满二叉树.
如果一棵二叉树的层数为k,且它的节点数是(2^k)-1,则它也是满二叉树.
在这里插入图片描述

2.2.2 完全二叉树

完全二叉树是由满二叉树引出来的.满二叉树是一种特殊的完全二叉树.

设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到饱和(即1~h-1层为一个满二叉树),第 h 层所有的结点都从左往右依次排列,这样的树就是完全二叉树。

完全二叉树
在这里插入图片描述

我们来举一个例子:看下面这张图,就不是完全二叉树,因为E节点只有F一个子节点,但是F子节点没有排在E节点的左边
在这里插入图片描述

2.3 二叉树的性质

1.若规定根节点的层数为1,则一棵非空二叉树的第i层上最多有 2^(i-1) 个节点(i>0).
2.若规定只有根节点的二叉树的深度为1,则深度为k的文二叉树的最大节点数是 (2^k)-1(k>=0).
3.对任何一棵二叉树,如果其叶子几点个数为n0,度为2的非叶子节点个数为n2,则有n0=n2+1.
4.具有n个结点的完全二叉树的深度k为
在这里插入图片描述
向上取整
5.对于具有n个结点的完全二叉树,如果按照 从上至下从左至右 的顺序对所有节点从0开始编号,则对于序号为i的结点有:

  • 若i>0,双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
  • 若2i+1<n,左孩子序号:2i+1,否则无左孩子
  • 若2i+2<n,右孩子序号:2i+2,否则无右孩子

2.4 二叉树的基本操作

2.4.1手动快速创建一棵简单的二叉树

这段代码并不是创建二叉树的方式,真正创建二叉树方法后序会重点讲解.

//孩子表示法来表示二叉树.
public class BinaryTree{
	public static class BTNode{
		BTNode left;	//引用当前孩子的左孩子
		BTNode right;   //引用当前孩子的右孩子
		int value;		//值域
		//有参构造方法
		BTNode(int value){
			this.value = value;
		}
	}
	private BTNode root;	//二叉树的根节点
	public void createBinaryTree(){
		BTNode node1 = new BTNode(1);	//创建节点node1,它的值为1
		BTNode node1 = new BTNode(2);
		BTNode node1 = new BTNode(3);
		BTNode node1 = new BTNode(4);
		BTNode node1 = new BTNode(5);
		BTNode node1 = new BTNode(6);
		root = node1;		    //根节点就是node1节点
		node1.left = node2;		//node1的左孩子是node2
		node1.right = node4;	//node1的右孩子是node4
		node2.left = node3;		//node2的左孩子是node3
		node4.left = node5;		//node4的左孩子是node5
		node4.right = node6;	//node5的右孩子是node6
	}
}

由以上代码创建出来的二叉树为下图所示:

在这里插入图片描述

2.4.2 二叉树的遍历

例图:
在这里插入图片描述

a. 前中后序遍历(递归操作)

学习二叉树结构,最简单的方式就是遍历.

遍历: 所谓遍历是指沿着某条路径搜索路线,依次对树中每个节点均做一次且仅做一次访问.
用N代表根节点,L代表根的左子树,R代表根的右子树.则有以下遍历方式 (用上图演示)

指的是对节点中的值域进行打印.
NLR:前序遍历----------------根节点---->根的左子树---->根的右子树
1–>2–>3–>4–>5–>6

public void preOrder(BtNode reeRoot){
	//先判断是否为空
	if(treeRoot==null){
		return;
	}
	//1.先遍历根节点
	System.out.print(treeRoot.value+" ");
	//2.再遍历根节点的左子树----->根节点的左子树也是二叉树(遍历根的左子树与遍历原树的规则相同)
	preOrder(treeRoot.left);		//递归遍历根的左子树
	//3.最后遍历根节点的右子树----->根的右子树也是二叉树(遍历根的右子树与遍历原树的规则相同)
	preOrder(treeRoot.right);	//递归遍历根的右子树
}

LNR:中序遍历----------------根的左子树---->根节点---->根的右子树
3–>2–>1–>5–>4–>6

public void inOrder(BtNode reeRoot){
	if(treeRoot==null){
		return;
	}
	inOrder(treeRoot.left);		
	System.out.print(treeRoot.value+" ");
	inOrder(treeRoot.right);	
}

LRN:后序遍历----------------根的左子树---->根的右子树---->根节点
3–>2–>5–>6–>4–>1

public void postOrder(BtNode reeRoot){
	if(treeRoot==null){
		return;
	}
	postOrder(treeRoot.left);		
	postOrder(treeRoot.right);	
	System.out.print(treeRoot.value+" ");
}

b. 前中后序遍历(非递归)

前序遍历

public List<Integer> preorderTraversal(TreeNode root) {
     List<Integer> list=new ArrayList<>();
     Stack<TreeNode> s=new Stack<>();
     TreeNode cur=root;
     s.push(cur);
     while(!s.empty()){
         cur=s.pop();
         while(cur!=null){
              list.add(cur.val);
              if(cur.right!=null){
                  s.push(cur.right);
              }
              cur=cur.left;
         }
     }
     return list;
}

中序遍历

public List<Integer> inorderTraversal(TreeNode root) {
      List<Integer> list=new ArrayList<>();
      if(root==null){
          return list;
      }
      TreeNode cur=root;
      Stack<TreeNode> s=new Stack<>();
      while(!s.empty()||cur!=null){
          while(cur!=null){
              s.push(cur);
              cur=cur.left;
          }
          cur=s.pop();
          list.add(cur.val);
          cur=cur.right;
      }
      return list;
}

后序遍历

public List<Integer> postorderTraversal(TreeNode root) {
      List<Integer> list=new ArrayList<>();
      if(root==null){
          return list;
      }
      TreeNode cur=root;
      TreeNode prev=null;
      Stack<TreeNode> s=new Stack<>();
      while(!s.empty()||cur!=null){
          while(cur!=null){
              s.push(cur);
              cur=cur.left;
          }
          TreeNode top=s.peek();
          if(top.right==null || top.right==prev){
              list.add(top.val);
              prev=top;
              s.pop();
          }else{
              cur=top.right;
          }
      }
      return list;
 }

c. 层次遍历

从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左往右访问第二层的节点,接着是第三层,以此类推,自上而下,自作向右逐层访问树的节点的过程就是层序遍历.

比如上图经过层次遍历的结果就是:1--->2--->4--->3--->5--->6.

2.4.3 还原二叉树

a.通过前序和中序的结果还原二叉树

还原思想:

前序: 根 左子树 右子树—通过前序遍历结果可以找到二叉树或者其子树的根节点
中序: 右子树 根 左子树—在中序结果中找到根的位置,根左边的是左子树的节点,右边是右子树的节点.

来看个例题:

前序遍历结果: EFHIGJK,中序遍历结果: HFIEJKG,请还原二叉树

题解:

我们通过前序遍历的结果可以得出二叉树的根节点为E,通过中序遍历结果可知HFI是根的左子树,JKG是根的右子树.
在这里插入图片描述
再通过前序遍历可知左子树的根节点为F,所以HF的左节点,IF的右节点.
在这里插入图片描述
从前序结果当中可知,G是右子树的根节点,JG的左子树,然后从中序遍历可知,KJ的右子树.
最后还原后的图形为:
在这里插入图片描述

b.通过中序和后序的结果还原二叉树

还原思想:

后序: 左子树 右子树 根----在后序结果中确定二叉树的根节点.
中序: 右子树 根 左子树----在中序结果中找到根的位置,根左边的是左子树的节点,右边是右子树的节点.

来看个例题:

中序遍历结果为:badce,后序遍历结果为:bdeca

题解:

先从后序遍历结果中确定二叉树的根节点为a,再从中序结果中得知a的左子树是b,a的右子树是dce

在这里插入图片描述
从后序结果可知c是右子树的根节点.从中序结果可知,dc的左子树,ec的右子树.
在这里插入图片描述

注意:通过前序遍历结果和后序遍历结果不能还原出二叉树.
前序:根 左子树 右子树
后序:左子树 右子树 根
只能找到根节点,不能确定根节点的左右子树.

c.通过层次遍历的结果还原二叉树.

这个相对来说就很简单了,自上而下,自左向右进行还原就行.
比如层次遍历结果是abcde,还原二叉树.
我们直接给出图形就行:

在这里插入图片描述

2.4.4 二叉树的基本操作方法

方法名作用
int size(Node root)获取树中节点的个数
int getLeafNodeCount(Node root)获取叶子节点的个数
int getLevelNodeCount(Node root)获取第k层节点的个数
int getHeight(Node root)获取二叉树的高度
Node find(Node root,int value)检测值为value的元素是否存在
boolean is CompleteTree(Node root)判断一棵树是不是完全二叉树
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 22:03:13  更:2022-03-13 22:03:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:53:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码