写点什么

Qz 学算法 - 数据结构篇 (非线性结构、树)

作者:浅辄
  • 2023-04-28
    吉林
  • 本文字数:2659 字

    阅读完需:约 9 分钟

非线性结构

非线性结构包括:二维数组,多维数组,广义表,树结构,图结构树

树结构

为什么需要树结构

  • 数组存储方式的分析

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

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

  • 链式存储方式的分析

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

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

  • 树存储方式的分析

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

1.二叉树

树的示意图


树的常用术语(结合示意图理解):


  • 节点

  • 根节点 父节点

  • 子子节

  • 叶子节点(没有子节点的节点)

  • 节点的权(节点值)

  • 路径(从 root 节点找到该节点的路线)

  • 子树

  • 树的高度(最大层数)

  • 森林:多颗子树构成森林

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

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



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

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



二叉树的前序、中序、后序遍历

前序遍历:先输出父节点,再遍历左子树和右子树 中序遍历:先遍历左子树,再输出父节点,再遍历右子树 后序遍历:先遍历左子树,再遍历右子树,最后输出父节点


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


前序遍历


步骤


创建一个二叉树


1.1 先输出当前节点(初始的时候是 root 节点) 1.2 如果左子节点不为空,则递归继续前序遍历 1.3 如果右子节点不为空,则递归继续前序遍历


中序遍历


2.1 先输出当前节点(初始的时候是 root 节点) 2.2 如果左子节点不为空,则递归继续前序遍历 2.3 如果右子节点不为空,则递归继续前序遍历


后序遍历


3.1 如果当前节点的左子节点不为空,则递归后序遍历, 3.2 如果当前节点的右子节点不为空,则递归后序遍历 3.3 输出当前节点


代码实现


package tree;
/** * @author LeeZhi * @version 1.0 */public class BinaryTreeDemo { public static void main(String[] args) { //先创建一个二叉树 BinaryTree binaryTree = new BinaryTree(); //创建需要的节点 HeroNode root = new HeroNode(1, "宋江"); HeroNode node2 = new HeroNode(2, "吴用"); HeroNode node3 = new HeroNode(3, "卢俊义"); HeroNode node4 = new HeroNode(4, "李逵"); HeroNode node5 = new HeroNode(5, "武松");
//说明,我们先手动创建该二叉树,后面我们学习递归的方式创建二叉树 root.setLeft(node2); root.setRight(node3); node3.setRight(node4); node3.setLeft(node5); binaryTree.setRoot(root); //测试,前序遍历 System.out.println("前序遍历"); binaryTree.preOrder();
System.out.println("中序遍历"); binaryTree.infixOrder();
System.out.println("后续遍历"); binaryTree.postOrder();
}}
//定义 BinaryTree 二叉树class BinaryTree{ private HeroNode root;
public void setRoot(HeroNode root) { this.root = root; }
//前序遍历 public void preOrder(){ if (this.root!=null){ this.root.preOrder(); }else{ System.out.println("二叉树为空,无法遍历"); } }
//中序遍历 public void infixOrder(){ if (this.root!=null){ this.root.infixOrder(); }else{ System.out.println("二叉树为空,无法遍历"); } }
//后序遍历 public void postOrder(){ if (this.root!=null){ this.root.postOrder(); }else{ System.out.println("二叉树为空,无法遍历"); } }}

class HeroNode{ private int no; private String name; private HeroNode left; //默认null private HeroNode right; //默认null
public HeroNode(int no, String name) { super(); this.no = no; this.name = name; }
public int getNo() { return no; }
public void setNo(int no) { this.no = no; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public HeroNode getLeft() { return left; }
public void setLeft(HeroNode left) { this.left = left; }
public HeroNode getRight() { return right; }
public void setRight(HeroNode right) { this.right = right; }
@Override public String toString() { return "HeroNode{" + "no=" + no + ", name='" + name + ''' + '}'; }
//编写前序遍历的方法 public void preOrder(){ System.out.println(this);//先输出父节点 //递归想左子树前序遍历 if (this.left!=null){ this.left.preOrder(); } //递归向右子树前序遍历 if (this.right!=null){ this.right.preOrder(); } } //中序遍历 public void infixOrder(){ //先递归向左子树中序遍历 if (this.left!=null){ this.left.infixOrder(); } //输出父节点 System.out.println(this); //递归向右子树中序遍历 if (this.right!=null){ this.right.infixOrder(); } } //后序遍历 public void postOrder(){ if (this.left!=null){ this.left.postOrder(); } if (this.right!=null){ this.right.postOrder(); } System.out.println(this); }}
复制代码


发布于: 刚刚阅读数: 3
用户头像

浅辄

关注

大丈夫生于天地之间,岂能郁郁久居人之下 2022-11-08 加入

Java、Spider、Go

评论

发布
暂无评论
Qz学算法-数据结构篇(非线性结构、树)_数据结构_浅辄_InfoQ写作社区