什么是树?
树是n(n>=0)个结点的有限集。n=0时称为空树,在任意一棵非空树中,有且仅有一个特定的称为根(root)的结点, 当n>1时,其余结点可分为m个互不相交的有限集。 下图中第一张图就不是树, 因为d和e相交
树的存储结构?
树的存储结构一般有4种,
1)双亲表示法,就是在每个节点中标示出它的父节点
2)孩子表示法,每个节点携带指针位指向自己的孩子
这种方法中,每个节点除了数据域外,还要额外携带m个指针位(m为树的度)
3)双亲孩子表示法
4),孩子兄弟表示法
二叉树?
度<=2的树称为二叉树
二叉树的存储结构?
1)顺序存储
2, 链式存储(使用孩子表示法)
二叉树的遍历?
1)前序遍历(DLR), 规则是:若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树
代码实现:
1 public class BinaryTree<E>{ 2 /** 3 * 节点内部类 4 * 这里我们用孩子表示法 5 * 因此需要定义一个数据域和两个指针域 6 */ 7 class Node<E>{ 8 private E data; 9 private Node<E> leftChild; 10 private Node<E> rightChild; 11 12 public Node(E data, Node<E> leftChild, Node<E> rightChild) { 13 this.data = data; 14 this.leftChild = leftChild; 15 this.rightChild = rightChild; 16 } 17 } 18 19 //root节点 20 Node<E> root; 21 22 /** 23 * 为了便于测试,我们在构造方法里生成一颗二叉树 24 * @param root 25 */ 26 public BinaryTree(E root) { 27 this.root = new Node(root, null, null); 28 createBinaryTree(); 29 } 30 31 /** 32 * 创建一颗二叉树 33 */ 34 private void createBinaryTree() { 35 //创建节点 36 Node<E> nodeB = new Node("B",null, null ); 37 Node<E> nodeC = new Node("C",null, null ); 38 Node<E> nodeD = new Node("D",null, null ); 39 Node<E> nodeE = new Node("E",null, null ); 40 Node<E> nodeF = new Node("F",null, null ); 41 Node<E> nodeG = new Node("G",null, null ); 42 Node<E> nodeH = new Node("H",null, null ); 43 Node<E> nodeI = new Node("I",null, null ); 44 //声明节点间的关系,来构建树 45 root.leftChild = nodeB; 46 root.rightChild = nodeC; 47 nodeB.leftChild = nodeD; 48 nodeD.leftChild = nodeG; 49 nodeD.rightChild = nodeH; 50 nodeC.leftChild = nodeE; 51 nodeC.rightChild = nodeF; 52 nodeE.rightChild = nodeI; 53 } 54 55 /** 56 * 二叉树的前序遍历 57 * @param tree 58 */ 59 public void preErgodic(Node<E> root) { 60 //如果二叉树为空,则空操作返回 61 if(root == null) { 62 return; 63 }else { 64 //否则先访问根节点 65 System.out.println(root.data.toString()); 66 //再前序访问左子树 67 preErgodic(root.leftChild); 68 //再前序访问右子树 69 preErgodic(root.rightChild); 70 } 71 } 72 }
测试代码
1 public static void main(String[] args) { 2 BinaryTree tree = new BinaryTree("A"); 3 tree.preErgodic(tree.root); 4 }
输出结果:
2)相对于前序遍历(DLR)来说, 中序遍历(LDR)就是先访问左子树,再访问中间节点,再访问右子树
1 public void middleErgodic(Node<E> root) { 2 //如果二叉树为空,则空操作返回 3 if(root == null) { 4 return; 5 }else { 6 //否则从根节点开始,先访问左子树 7 middleErgodic(root.leftChild); 8 //再访问根节点 9 System.out.print(root.data.toString() + " "); 10 //再访问右子树 11 middleErgodic(root.rightChild); 12 } 13 }
输出结果:
3)后续遍历(LRD)
1 public void endErgodic(Node<E> root) { 2 //如果二叉树为空,则空操作返回 3 if(root == null) { 4 return; 5 }else { 6 //否则从根节点开始,先访问左子树 7 endErgodic(root.leftChild); 8 //再访问右子树 9 endErgodic(root.rightChild); 10 //再访问根节点 11 System.out.print(root.data.toString() + " "); 12 } 13 }
输出结果
小结: 所谓前序后序中序其实就是 访问根节点是在访问左右节点的前面、后面还是中间