二叉树的存储

顺序存储二叉树

1.基本说明

从数据存储来看,数据存储方式和数的存储方式可以相互转换。

2.特点

1)顺序二叉树通常只考虑完全二叉树;

2)第n个元素的左子节点为2 * n + 1;

3)第n个元素的右子节点为2 * n + 2;

4)第n个元素的父节点为(n-1)/2;

  1. n为下标,从0开始。

package com.sratct.tree;

public class ArrBinaryTreeDemo {
    public static void main(String[] args) {
      int[] arr = {1,2,3,4,5,6,7};
        ArrBinaryTree arrBinaryTree = new ArrBinaryTree(arr);
        arrBinaryTree.getList();
    }
}

class ArrBinaryTree {
    private int[] arr;

    public ArrBinaryTree(int[] arr) {
        this.arr = arr;
    }
     public void getList() {
        getList(0);
     }
     // 顺序存储二叉树的前序遍历
    public void getList(int n) {
        if (arr == null || arr.length ==0) {
            System.out.println("链表为空");
            return;
        }
        System.out.println(arr[n]);
        // 左递归:2*n+1为当前节点的左子节点的下标
        if ((2 * n + 1) < arr.length) {
            getList(2*n+1);
        }
        if ((2 * n + 2) < arr.length) {
            getList(2*n+2);
        }
    }
}

线索二叉树

1.基本介绍

1)n个结点二叉链表中含有n+1个空指针域(公式:2n - (n - 1))。利用二叉链表中的空指针域,存放指向结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为‘线索’)。

2)这种加了线索的二叉链表为线索链表,相应的二叉树为线索二叉树。
2.创建以及遍历线索二叉树

package com.sratct.tree;

public class ThreadTreeDemo {
    public static void main(String[] args) {

        ThreadTree threadTree = new ThreadTree();
        TNode root = new TNode(1);
        TNode node1 = new TNode(3);
        TNode node2 = new TNode(6);
        TNode node3 = new TNode(8);
        TNode node4 = new TNode(10);
        TNode node5 = new TNode(14);
        root.left = node1;
        root.right = node2;
        node1.left = node3;
        node1.right = node4;
        node2.left = node5;
      threadTree.zThread(root);
      threadTree.threadList(root);
    }
}

class ThreadTree {

    private TNode pre = null; //指向当前节点的前驱结点的指针


    // 对二叉树中序线索化的方法
    public void zThread(TNode root) {
        if (root == null) {
            System.out.println("二叉树为空");
            return;
        }
        // 线索化左子树
        if (root.left != null) {
            zThread(root.left);
        }
        // 线索化当前元素
        // 处理当前结点的前驱结点
        if (root.left == null) {
            // 当前节点的做指针指向前序结点
            root.left = pre;
            root.leftType = 1;
        }
        // 处理当前结点的后继结点,需要到下一个结点
        if (pre != null && pre.right == null) {
            // 让前驱结点的右指针指向当前节点
            pre.right = root;
            pre.rightType = 1;
        }
        // pre后移到下一个
        pre = root;

        // 线索化右子树
        if (root.right != null) {
            zThread(root.right);
        }
    }

    // 遍历线索二叉树
    public void threadList(TNode root) {
        TNode node = root;
        while (node != null) {
            // 找到第一个leftType=1的结点为处理后的有效结点,就是8
            while (node.leftType == 0) {
                node = node.left;
            }
           // 输出当前结点
            System.out.println(node.no);
           // 找到第一个有效结点后(rightType ==1),判断右指针是否为后继结点,是就输出
            while (node.rightType ==1) {
                node = node.right;
                System.out.println(node.no);
            }
            // rightType == 0,则直接向后移
            node = node.right;
        }
    }
}
class TNode {
    public int no;
    public TNode left;
    public TNode right;
    public int leftType; // 如果leftType = 0指向左子树,为1则指向前驱结点
    public int rightType; // 如果rightType = 0 指向右子树,为1时则指向后继结点
    public TNode(int no) {
        this.no = no;
    }


}

原文地址:https://www.cnblogs.com/cqyp/p/14741330.html