数据结构 - 树及二叉树的应用

目录

1. 数组, 链表, 树存储方式分析

1.1 数组存储方式分析

1.2 链表存储方式分析

1.3 树存储方式分析

 2. 树示意图及常用术语

3. 二叉树概述

4. 二叉树图示

5. 二叉树遍历

5.1 说明

5.2 应用实例 

5.2.1 思维图解

5.2.2 要求

6. 二叉树查找

6.1 要求

6.2 思维分析示例图

7. 二叉树删除

7.1 要求

7.2 思路分析图解

8. 核心代码实现

8.1 节点类核心代码

8.2 二叉树类核心代码


1. 数组, 链表, 树存储方式分析

1.1 数组存储方式分析

        优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。

        缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低。

        操作示意图:

1.2 链表存储方式分析

        优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可, 删除效率也很好)。

        缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历)。

        操作示意图:

1.3 树存储方式分析

        能提高数据存储,读取的效率, 比如利用 二叉排序树(Binary Sort Tree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度。

        案例: [7, 3, 10, 1, 5, 9, 12]

        操作示意图:

 2. 树示意图及常用术语

3. 二叉树概述

  1. 树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树。

  2. 二叉树的子节点分为左节点和右节点。

  3. 如果该二叉树的所有叶子节点都在最后一层,并且结点总数= 2^n -1 , n 为层数,则我们称为满二叉树。

  4. 如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树。

4. 二叉树图示

5. 二叉树遍历

5.1 说明
  1. 使用前序,中序和后序对下面的二叉树进行遍历。

  2. 前序遍历: 先输出父节点,再遍历左子树和右子树【父 - 左 - 右】

  3. 中序遍历: 先遍历左子树,再输出父节点,再遍历右子树【左 - 父 - 右】

  4. 后序遍历: 先遍历左子树,再遍历右子树,最后输出父节点【左 - 右 - 父】

  5. 小结: 看输出父节点的顺序,就确定是前序,中序还是后序

5.2 应用实例 
5.2.1 思维图解

5.2.2 要求
  1. 前上图的 3号节点 "卢俊" , 增加一个左子节点 [5, 关胜]

  2. 使用前序,中序,后序遍历,请写出各自输出的顺序是什么

6. 二叉树查找

6.1 要求
  1. 请编写前序查找,中序查找和后序查找的方法。

  2. 并分别使用三种查找方式,查找 heroNO = 5 的节点

  3. 并分析各种查找方式,分别比较了多少次

6.2 思维分析示例图

7. 二叉树删除

7.1 要求
  1. 如果删除的节点是叶子节点,则删除该节点。

  2. 如果删除的节点是非叶子节点,则删除该子树。

  3. 测试,删除掉 5号叶子节点 和 3号子树。

7.2 思路分析图解

8. 核心代码实现

8.1 节点类核心代码
// 前序遍历
public void preOrder() {
	// 输出当前节点
	System.out.print(this + " ");
	// 如果左节点不为空
	if (Optional.ofNullable(this.getLeft()).isPresent()) {
		this.getLeft().preOrder();
	}
	// 如果右节点不为空
	if (Optional.ofNullable(this.getRight()).isPresent()) {
		this.getRight().preOrder();
	}
}
// 中序遍历
public void infixOrder() {
	// 如果左节点不为空
	if (Optional.ofNullable(this.getLeft()).isPresent()) {
		this.getLeft().infixOrder();
	}
	// 输出当前节点
	System.out.print(this + " ");
	// 如果右节点不为空
	if (Optional.ofNullable(this.getRight()).isPresent()) {
		this.getRight().infixOrder();
	}
}
// 后序遍历
public void afterOrder() {
	// 如果左节点不为空
	if (Optional.ofNullable(this.getLeft()).isPresent()) {
		this.getLeft().afterOrder();
	}
	// 如果右节点不为空
	if (Optional.ofNullable(this.getRight()).isPresent()) {
		this.getRight().afterOrder();
	}
	// 输出当前节点
	System.out.print(this + " ");
}
/**
*
* @Description 前序遍历查找
* @param no 查找的编号
* @return com.hui.data.struct.binaryTree.HeroNode
*/
public HeroNode preOrderSearch(int no) {
    System.out.println("前序遍历执行了~~~");
    if (no == this.getId()) {
       return this;
    }
    HeroNode curNode = null;
    if (Optional.ofNullable(this.left).isPresent()) {
       curNode = this.getLeft().preOrderSearch(no);
    }
    // 判断左子树是否存在查找的节点编号
    if (Optional.ofNullable(curNode).isPresent()) {
       return curNode;
    }
    if (Optional.ofNullable(this.right).isPresent()) {
       curNode = this.getRight().preOrderSearch(no);
    }
    return curNode;
}
/**
 *
 * @Description 中序遍历查找
 * @param no 查找的编号
 * @return com.hui.data.struct.binaryTree.HeroNode
 */
public HeroNode infixOrderSearch(int no) {
    HeroNode curNode = null;
    if (Optional.ofNullable(this.left).isPresent()) {
       curNode = this.getLeft().infixOrderSearch(no);
    }
    // 判断左子树是否存在查找的节点编号
    if (Optional.ofNullable(curNode).isPresent()) {
       return curNode;
    }
    System.out.println("中序遍历执行了~~~");
    if (no == this.getId()) {
       return this;
    }
    if (Optional.ofNullable(this.right).isPresent()) {
       curNode =  this.getRight().infixOrderSearch(no);
    }
    return curNode;
}
/**
 *
 * @Description 后序遍历查找
 * @param no 查找的编号
 * @return com.hui.data.struct.binaryTree.HeroNode
 */
public HeroNode postOrderSearch(int no) {
    HeroNode curNode = null;
    if (Optional.ofNullable(this.left).isPresent()) {
       curNode =  this.getLeft().postOrderSearch(no);
    }
    // 判断左子树是否存在查找的节点编号
    if (Optional.ofNullable(curNode).isPresent()) {
       return curNode;
    }
    if (Optional.ofNullable(this.right).isPresent()) {
       curNode =  this.getRight().postOrderSearch(no);
    }
    // 判断右子树是否存在查找的节点编号
    if (Optional.ofNullable(curNode).isPresent()) {
       return curNode;
    }
    System.out.println("后序遍历执行了~~~");
    if (no == this.getId()) {
       return this;
    }
    return null;
}
/**
*
* @Description 删除节点
* @param no 要删除节点的编号
*/
public void delNode(int no) {
    // 验证当前节点的左结点是否为空并且是否等于删除节点的编号, 是则将该左结点至 null
    if (Optional.ofNullable(this.getLeft()).isPresent() && this.getLeft().getId() == no) {
       this.setLeft(null);
       return;
    }
    // 验证当前节点的右结点是否为空并且是否等于删除节点的编号, 是则将该右结点至 null
    if (Optional.ofNullable(this.getRight()).isPresent() && this.getRight().getId() == no) {
       this.setRight(null);
       return;
    }
    // 左子树递归删除
    if (Optional.ofNullable(this.getLeft()).isPresent()) {
       this.getLeft().delNode(no);
    }
    // 右子树递归删除
    if (Optional.ofNullable(this.getRight()).isPresent()) {
       this.getRight().delNode(no);
    }
}
8.2 二叉树类核心代码
// 前序遍历
public void preOrder() {
	if (Optional.ofNullable(root).isPresent()) {
		root.preOrder();
	} else {
		System.out.println("二叉树为空, 不可遍历!!!");
	}
}
// 中序遍历
public void infixOrder() {
	if (Optional.ofNullable(root).isPresent()) {
		root.infixOrder();
	} else {
		System.out.println("二叉树为空, 不可遍历!!!");
	}
}
// 后序遍历
public void postOrder() {
	if (Optional.ofNullable(root).isPresent()) {
		root.afterOrder();
	} else {
		System.out.println("二叉树为空, 不可遍历!!!");
	}
}
// 前序遍历查找
public HeroNode preOrderSearch(int no) {
    if (Optional.ofNullable(root).isPresent()) {
       return root.preOrderSearch(no);
    }
    return null;
}
// 中序遍历查找
public HeroNode infixOrderSearch(int no) {
    if (Optional.ofNullable(root).isPresent()) {
       return root.infixOrderSearch(no);
    }
    return null;
}
// 后序遍历查找
public HeroNode postOrderSearch(int no) {
    if (Optional.ofNullable(root).isPresent()) {
       return root.postOrderSearch(no);
    }
    return null;
}
/**
 *
 * @Description 删除节点
 * @param no 要删除节点的编号
 */
public void delNode(int no) {
    if (Optional.ofNullable(root).isPresent()) {
       if (root.getId() == no) {
           root = null;
       } else {
           root.delNode(no);
       }
    } else {
       System.out.println("是空树, 不能删除!!!");
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值