菜鸟笔记之数据结构(9)


声明:以下是学的尚硅谷网课并结合网上资料所记的笔记。可能会有一些错误,发现了会修改。

树的介绍

概念

树是一种数据结构,它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:每个节点有零个或多个子节点;没有父节点的节点称为根节点;每一个非根节点有且只有一个父节点;除了根节点外,每个子节点可以分为多个不相交的子树。

注: 每个节点是一个对象,可以放id,name等信息。

种类

  • 无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树;
  • 有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树;
  • 二叉树:每个节点最多含有两个子节点的树称为二叉树;
  • 满二叉树:所有叶子节点在最后一层,且节点总数为 2k-1 ,k为层数;
  • 完全二叉树:二叉树的所有叶子节点在最后一层或倒数第二层,最后一层的叶子节点在左边连续,倒数第二层叶子节点在右边连续;
  • 哈夫曼树(最优二叉树):带权路径最短的二叉树称为哈夫曼树或最优二叉树;

作用

可提高数据存储、读取的效率。比如二叉排序树,既可以保证数据的检索速度,也保证数据的增删改速度。其查找有点像二分查找,添加和删除时效率高,找到父节点对其left或right指针操作即可。

二叉树

二叉树:每个节点最多只能有两个子节点的一种形式的树,二叉树子节点可分为左节点和右节点。如图1所示为一个二叉树。在这里插入图片描述
H,E,F,G没有子节点,为叶子节点。C是F、G的父节点,是A的子节点。

常用术语:

  1. 节点,根节点,父节点,子节点,叶子节点(没有子节点的节点);
  2. 节点的权(节点的值);
  3. 路径(从root节点找到某个节点的路线);
  4. 层,子树;
  5. 树的高度(最大层数);
  6. 森林(多颗子树构成森林)。

前序、中序、后序遍历

前序遍历: (1)先输出当前节点(初始为root节点);(2)如果左子节点不为空,则继续前序遍历;(3)如果右子节点不为空,则递归继续前序遍历。图一的前序遍历结果为: A->B->D->H->E->C->F->G。代码如下:

public void preOrder(){ 
	//先输出父节点
	System.out.println(this);
	//递归向左子树前序遍历
	if(this.left != null){
		this.left.preOrder();
	}
	//递归向右子树前序遍历
	if(this.right != null){ 
		this.right.preOrder();
	}
}

中序遍历:(1)如果当前节点的左子节点不为空,则递归中序遍历;(2)输出当前节点;(3)如果当前节点的右子节点不为空,则递归中序遍历。图一的中序遍历结果为: D->H->B->E->A->F->C->G。代码如下:

public void infixOrder(){ 
	//递归向左子树中序遍历
	if(this.left != null){
		this.left.infixOrder();
	}
	//输出父节点
	System.out.println(this); 
	//递归向右子树中序遍历
	if(this.right != null){ 
		this.right.infixOrder();
	}
}

后序遍历:(1)如果当前节点的左子节点不为空,则递归后序遍历;(2)如果当前节点的右子节点不为空,则递归后序遍历;(3)输出当前节点。图一的后序遍历结果为: H->D->E->B->F->G->C->A。代码如下:

public void postOrder(){ 
	//递归向左子树后序遍历
	if(this.left != null){
		this.left.postOrder();
	}
	//递归向右子树后序遍历
	if(this.right != null){ 
		this.right.postOrder();
	}
	//输出父节点
	System.out.println(this); 
}

前序、中序还是后序遍历可以根据父节点的输出位置来判断。

前序、中序、后序查找

前序查找思路:(1)先判断当前节点的值是否为要查找的,如果相等,返回当前节点;(2)如果不相等,判断当前节点的左子节点是否为空,不为空,则递归前序查找;(3)如果左递归查找没有找到节点,则判断当前节点的右子节点是否为空,不为空,则递归向右前序查找。

public Node preOrderSearch(int no){ 
	if(this.no == no){ //比较当前节点是否为要查找的节点
		return this;
	}
	Node resNode = null;
	if(this.left != null){ //向左查找
		resNode = this.left.preOrderSearch(no); 
	}
	if(resNode != null){ //找到了
		return resNode;
	}
	if(this.right != null){ //向右查找
		resNode = this.right.preOrderSearch(no); 
	}
	return resNode;
}

中序、后序查找类似,只是顺序不同。

节点的删除

思路:

  1. 如果只有root,等价于将二叉树置空。还要考虑树是否为空树。(首先处理)
  2. 判断当前节点的子节点是否为需要删除的节点,而不是判断当前节点;
  3. 如果当前节点的左子节点不为空,且为要删除的节点,将this.left == null,并返回(结束递归);
  4. 如果当前节点的右子节点不为空,且为要删除的节点,将this.right == null,并返回(结束递归);
  5. 第2,3步都没有删除节点,需要向左子树递归删除;
  6. 如果第4步也没有完成,则应向右子树递归删除;

--------------------------------------- 个人学习笔记----------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值