线索二叉树实现 数据结构

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        BinaryThreadTree tree = new BinaryThreadTree();
        System.out.println("Welcome to the threading tree system!\n");
        Scanner sc = new Scanner(System.in);
        int menu;
        boolean active = true;
        while (active) {
            System.out.println("**********************************************************************************************");
            System.out.println("1.Create a binary tree \t 2.Levelorder traversal \t 3.Preorder threading traversal \n" +
                    "4.Inorder threading traversal \t 5.Postorder threading traversal \t 6.The binary tree deepth \n" +
                    "7.Destroy the binary tree \t 8.Exit");
            System.out.println("**********************************************************************************************");
            System.out.print("----------Please type the menu number:");
            menu = sc.nextInt();
            sc.nextLine();
            switch (menu) {
                case 1:
                    System.out.println("Please enter several numbers as the tree items:");
                    String str = sc.nextLine();
                    String[] strs = str.split(" ");
                    int[] items = new int[strs.length];
                    for (int i = 0; i < strs.length; i++) {
                        items[i] = Integer.parseInt(strs[i]);
                    }
                    tree.createBinaryThreadTree(items);
                    System.out.println("The binary tree has been created!");
                    break;
                case 2:
                    tree.levelorderTraversal();
                    break;
                case 3:
                    tree.preorderThreadingTree();
                    tree.preorderTraversal();
                    tree.clearThreadingNode();
                    break;
                case 4:
                    tree.inorderThreadingTree();
                    tree.inorderTraversal();
                    tree.clearThreadingNode();
                    break;
                case 5:
                    tree.postorderThreadingTree();
                    tree.postorderTraversal();
                    tree.clearThreadingNode();
                    break;
                case 7:
                    tree.destroyTree();
                    System.out.println("Destroy binary tree successfully!");
                    break;
                case 6:
                    tree.printTreeDeepth();
                    break;
                case 8:
                    System.out.println("Bye!");
                    active = false;
                    break;
                default:
                    System.out.println("Please retype menu number!");
            }
        }
    }
}
class BinaryThreadTreeNode {
    public int leftTag;
    public int rightTag;
    public BinaryThreadTreeNode leftChild;
    public BinaryThreadTreeNode rightChild;
    public int data;
    public BinaryThreadTreeNode(int data, BinaryThreadTreeNode leftChild, BinaryThreadTreeNode rightChild) {
        this.data = data;
        this.leftChild = leftChild;
        this.rightChild = rightChild;
        this.leftTag = 0;
        this.rightTag = 0;
    }
}
class BinaryThreadTree {
    private BinaryThreadTreeNode root;
    public BinaryThreadTree() {
        root = null;
    }
    public void createBinaryThreadTree(int ... elements) {
        BinaryThreadTreeNode p = null;
        BinaryThreadTreeNode q = null;
        Deque<BinaryThreadTreeNode> deque = new ArrayDeque<>();
        for (int elem : elements) {
            p = new BinaryThreadTreeNode(elem, null, null);
            if (root == null) {
                root = p;
            } else {
                deque.addLast(root);
                while (!deque.isEmpty()) {
                    q = deque.pollFirst();
                    if (q.leftChild == null) {
                        q.leftChild = p;
                        break;
                    } else {
                        deque.addLast(q.leftChild);
                    }
                    if (q.rightChild == null) {
                        q.rightChild = p;
                        break;
                    } else {
                        deque.addLast(q.rightChild);
                    }
                }
                deque.clear();
            }
        }
    }
    private boolean checkTreeNull() {
        if (root == null) {
            System.out.println("The thread tree is empty!");
            return true;
        }
        return false;
    }
    public void preorderThreadingTree() {
        if (checkTreeNull()) {
            return;
        }
        Deque<BinaryThreadTreeNode> deque = new ArrayDeque<>();
        Deque<BinaryThreadTreeNode> dequeThreadNode = new ArrayDeque<>();
        BinaryThreadTreeNode p = root;
        BinaryThreadTreeNode q;
        while (p != null || !deque.isEmpty()) {
            while (p != null) {
                deque.push(p);
                if (!dequeThreadNode.isEmpty()) {
                    q = dequeThreadNode.pop();
                    q.rightTag = 1;
                    q.rightChild = p;
                    if (p.leftChild == null) {
                        p.leftChild = q;
                        p.leftTag = 1;
                    }
                }
                if (p.leftChild == null) {
                    p.leftChild = deque.getLast();
                    p.leftTag = 1;
                }
                if (p.rightChild == null) {
                    dequeThreadNode.push(p);
                }
                if (p.leftTag == 0) {
                    p = p.leftChild;
                } else {
                    p = null;
                }
            }
            p = deque.pop();
            if (p.rightTag == 0) {
                p = p.rightChild;
            } else {
                p = null;
            }
        }
    }
    private void threadingTree(Deque<BinaryThreadTreeNode> deque) {
        if (deque.isEmpty()) {
            return;
        }
        BinaryThreadTreeNode p;
        BinaryThreadTreeNode q;
        q = deque.pollFirst();
        while (!deque.isEmpty()) {
            p = deque.pollFirst();
            if (q.rightChild == null) {
                q.rightChild = p;
                q.rightTag = 1;
            }
            if (p.leftChild == null) {
                p.leftChild = q;
                p.leftTag = 1;
            }
            q = p;
        }
    }
    public void inorderThreadingTree() {
        if (checkTreeNull()) {
            return;
        }
        Deque<BinaryThreadTreeNode> deque = new ArrayDeque<>();
        Deque<BinaryThreadTreeNode> dequeThreadNode = new ArrayDeque<>();
        BinaryThreadTreeNode p = root;
        while (p != null || !deque.isEmpty()) {
            while (p != null) {
                deque.push(p);
                p = p.leftChild;
            }
            p = deque.pop();
            dequeThreadNode.addLast(p);
            p = p.rightChild;
        }
        threadingTree(dequeThreadNode);
    }
    public void postorderThreadingTree() {
        if (checkTreeNull()) {
            return;
        }
        Deque<BinaryThreadTreeNode> deque = new ArrayDeque<>();
        Deque<Integer> dequeThreadTag = new ArrayDeque<>();
        Deque<BinaryThreadTreeNode> dequeThreadNode = new ArrayDeque<>();
        BinaryThreadTreeNode p = root;
        while (p != null || !deque.isEmpty()) {
            while (p != null) {
                deque.push(p);
                dequeThreadTag.push(0);
                p = p.leftChild;
            }
            p = deque.pop();
            if (dequeThreadTag.pop() == 0) {
                dequeThreadTag.push(1);
                deque.push(p);
            } else {
                dequeThreadNode.addLast(p);
                p = null;
                continue;
            }
            p = p.rightChild;
        }
        threadingTree(dequeThreadNode);
    }
    public void preorderTraversal() {
        if (checkTreeNull()) {
            return;
        }
        System.out.println("----------------------------------------------------------------");
        BinaryThreadTreeNode p = root;
        while ((p.leftChild != null && p.leftTag == 0) || p.rightTag == 1) {
            printNodePlain(p);
            if (p.rightTag == 1) {
                p = p.rightChild;
            } else {
                p = p.leftChild;
            }
            if (p.leftTag == 1 && p.rightTag == 0) {
                printNodePlain(p);
            }
        }
        System.out.println("\n----------------------------------------------------------------");
    }
    public void inorderTraversal() {
        if (checkTreeNull()) {
            return;
        }
        System.out.println("----------------------------------------------------------------");
        BinaryThreadTreeNode p = root;
        boolean tag = true;
        while (true) {
            while (p.leftChild != null && p.leftTag == 0 && tag) {
                p = p.leftChild;
            }
            printNodePlain(p);
            if (p.rightChild != null) {
                tag = p.rightTag == 1 ? false : true;
                p = p.rightChild;
            } else {
                break;
            }
        }
        System.out.println("\n----------------------------------------------------------------");
    }
    public void postorderTraversal() {
        if (checkTreeNull()) {
            return;
        }
        System.out.println("---------------------------------------------------------------");
        Deque<BinaryThreadTreeNode> deque = new ArrayDeque<>();
        Deque<Integer> dequeTag = new ArrayDeque<>();
        BinaryThreadTreeNode p = root;
        boolean find = true;
        while (true) {
            while (p.leftChild != null && p.leftTag != 1 && find) {
                if (p.leftTag == 0 && p.rightTag == 0 && p.leftChild.leftTag == 0 && p.leftChild.rightTag == 0) {
                    deque.push(p);
                    dequeTag.push(0);
                }
                p = p.leftChild;
            }
            printNodePlain(p);
            if (p == root) {
                break;
            }
            if (p.rightTag == 1) {
                p = p.rightChild;
                if (p == deque.peekFirst()) {
                    deque.pop();
                    dequeTag.pop();
                }
                find = false;
            } else {
                p = deque.pop();
                find = false;
                if (dequeTag.pop() == 0) {
                    dequeTag.push(1);
                    deque.push(p);
                    p = p.rightChild;
                    find = true;
                }
            }
        }
        System.out.println("\n----------------------------------------------------------------");
    }
    private int getPreSpace(int level) {
        int deepth = getTreeDeepth(root);
        return (int)(deepth - (level + 1) < 0 ? -1 : Math.pow(2.0, (double)deepth - (level + 1)));
    }
    private int getSpace(int level) {
        return (int)Math.pow(2.0, (double)getTreeDeepth(root) - level);
    }
    private int getLevel(BinaryThreadTreeNode root, BinaryThreadTreeNode node, int level) {
        if (root == node) {
            return level;
        }
        int findL = -1, findR = -1;
        if (root.leftChild != null) {
            findL = getLevel(root.leftChild, node, level + 1);
        }
        if (root.rightChild != null) {
            findR = getLevel(root.rightChild, node, level + 1);
        }
        return findL == -1 ? (findR == -1 ? -1 : findR) : findL;
    }
    public void levelorderTraversal() {
        if (checkTreeNull()) {
            return;
        }
        System.out.println("----------------------------------------------------------------");
        Deque<BinaryThreadTreeNode> deque = new ArrayDeque<>();
        BinaryThreadTreeNode p = null;
        int curLevel = -1, preSpace, space, level;
        deque.addLast(root);
        while (!deque.isEmpty()) {
            p = deque.pollFirst();
            level = getLevel(root, p, 1);
            if (level != curLevel) {
                if (curLevel != -1) {
                    System.out.println("\n");
                }
                curLevel = level;
                preSpace = getPreSpace(curLevel);
                if (preSpace == -1) {
                    System.out.print("  ");
                } else {
                    for (int i = 0; i < preSpace; i++) {
                        System.out.print("\t");
                    }
                }
            }
            space = getSpace(curLevel);
            System.out.print(p.data);
            for (int i = 0; i < space; i++) {
                System.out.print("\t");
                if (curLevel == getTreeDeepth(root)) {
                    System.out.print("  ");
                }
            }
            if (p.leftChild != null && p.leftTag == 0) {
                deque.addLast(p.leftChild);
            }
            if (p.rightChild != null && p.rightTag == 0) {
                deque.addLast(p.rightChild);
            }
        }
        System.out.println("\n----------------------------------------------------------------");
    }
    public void clearThreadingNode() {
        Deque<BinaryThreadTreeNode> deque = new ArrayDeque<>();
        BinaryThreadTreeNode p = null;
        deque.addLast(root);
        while (!deque.isEmpty()) {
            p = deque.pollFirst();
            if (p.leftTag != 0) {
                p.leftTag = 0;
                p.leftChild = null;
            }
            if (p.rightTag != 0) {
                p.rightTag = 0;
                p.rightChild = null;
            }
            if (p.leftChild != null) {
                deque.addLast(p.leftChild);
            }
            if (p.rightChild != null) {
                deque.addLast(p.rightChild);
            }
        }
    }
    private void printNode(BinaryThreadTreeNode node) {
        System.out.println(node.data + "\t" + node.leftTag + "\t" + node.rightTag);
    }
    private void printNodePlain(BinaryThreadTreeNode node) {
        System.out.print(node.data + "\t");
    }
    private int getTreeDeepth(BinaryThreadTreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftCount, rightCount;
        leftCount = getTreeDeepth(root.leftChild) + 1;
        rightCount = getTreeDeepth(root.rightChild) + 1;
        return leftCount > rightCount ? leftCount : rightCount;
    }
    public void printTreeDeepth() {
        int deepth = getTreeDeepth(root);
        System.out.println("The tree deepth is : " + deepth + " !");
    }
    public void destroyTree() {
        this.root = null;
    }
}
点赞