赞
踩
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多种表示方式,如:双亲表示法,孩子表示法、孩子双亲表示法、孩子兄弟表示法等等。我们这里就简单的了解其中最常用的孩子兄弟表示法。下图中,c代表child,b代表brother.
一棵二叉树是结点的一个有限集合,该集合:
注意:对于任意的二叉树都是由以下几种情况复合而成的:
在这里,我们使用类似与链表的链式存储.
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有**二叉(找不到父节点,类似与单向列表)和三叉(可以找到父节点,类似与双向链表)**表示方式,具体如下:
// 孩子表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
}
// 孩子双亲表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用,常常代表右孩子为根的整棵右子树
Node parent; // 当前节点的父节点
}
前置说明:我们这里使用非常简单的方法来创建一棵二叉树,此二叉树是孩子表示法,其实真正创建二叉树的方法不是这样的,我们后边介绍.我们创建下面这棵二叉树:
public class BinaryTree { static class Node{ public int value; public Node left; public Node right; public Node(int value) { this.value = value; } } public int treeSize; /** * 创建一棵默认的树 * @return */ public Node createTree(){//注意:真正创建二叉树的方法不是这这样的,我们后面介绍 Node a = new Node(1); Node b = new Node(2); Node c = new Node(3); Node d = new Node(4); Node e = new Node(5); Node f = new Node(6); Node g = new Node(7); a.left = b; a.right = c; b.left = d; c.left = e; c.right = f; d.left = g; return a; } /** * 前序遍历 * @param root */ public void preOrder(Node root){ if (root == null){ return; } System.out.print(root.value+" "); preOrder(root.left); preOrder(root.right); } /** * 中序遍历 * @param root */ public void inOrder(Node root){ if (root == null){ return; } preOrder(root.left); System.out.print(root.value+" "); preOrder(root.right); } /** * 后序遍历 * @param root */ public void postOrder(Node root){ if (root == null){ return; } preOrder(root.left); preOrder(root.right); System.out.print(root.value+" "); } /** * 计算树的大小 * @param root * @return */ public int size(Node root) { if (root == null){ return 0; } treeSize++; size(root.left); size(root.right); return treeSize; } /** * 获取树叶子结点的个数 * @param root * @return */ public int getLeafNodeCount(Node root) { if (root == null){ return 0; } if (root.left == null && root.right == null){ return 1; } return getLeafNodeCount(root.left)+getLeafNodeCount(root.right); } /** * 获取该树的第k层有几个结点 * @param root * @param k * @return */ public int getKLevelNodeCount(Node root, int k) { if (root == null){ return 0; } if (k == 1){ return 1; } return getKLevelNodeCount(root.left,k-1) +getKLevelNodeCount(root.right,k-1);//每递归一层,k-1 //相对与根节点,第三层就是第三层,相对第二层,第三层是第二层,以此类推... } /** * 获取树的高度,取左子树和右子树的最大值+1(加上根节点所在的层) * @param root * @return */ public int getHeight(Node root) { if (root == null){ return 0; } return Math.max(getHeight(root.left),getHeight(root.right))+1; } /** * 在树中寻找val值是否存在 * @param root * @param val * @return */ public Node find(Node root, int val) { if (root == null){ return null; } if (root.value == val){ return root; } Node leftNode = find(root.left,val); if (leftNode != null){//写成判断地址的形,如果写成值的形式,可能会报空指针异常 return leftNode;//如果从左树中找到,直接返回,就不用遍历右树,以此来减小时间复杂度 } Node rightNode = find(root.right,val); if (rightNode != null){ return rightNode; } return null;//递归到底了,说明没找到,返回null } /* 层序遍历和判断是否为完全二叉树比较复杂,我们后续介绍 */ }
开始测试:
public class Test { public static void main(String[] args) { BinaryTree binaryTree = new BinaryTree(); BinaryTree.Node root = binaryTree.createTree(); binaryTree.preOrder(root); System.out.println(); binaryTree.inOrder(root); System.out.println(); binaryTree.postOrder(root); System.out.println(); System.out.println(binaryTree.size(root)); System.out.println(binaryTree.getLeafNodeCount(root)); System.out.println(binaryTree.getKLevelNodeCount(root,4)); System.out.println(binaryTree.getHeight(root)); System.out.println(binaryTree.find(root,7)); System.out.println(binaryTree.find(root,8)); } }
测试结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。