数据结构(七)——树结构(Tree) 之二叉树的常用操作

一.链式存储的二叉树的操作

1.遍历二叉树

  • 先序遍历:根-->左-->右
  • 中序遍历:左-->根-->右
  • 后序遍历:左-->右-->根

2.二叉树结点的查找 

结点的查找也可以分为先序查找,中序查找和后序查找。方式和遍历方式相似。

3.删除二叉树结点

  • 二叉树抽象类代码
package cn.kimtian.tree;

/**
 * 链式存储的二叉树
 *
 * @author kimtian
 */
public class BinaryTree {
    /**
     * 根结点
     */
    TreeNode root;

    /**
     * 设置根结点
     *
     * @param root 根结点
     */
    public void setRoot(TreeNode root) {
        this.root = root;
    }

    /**
     * 获取根结点
     *
     * @return TreeNode 根结点
     */
    public TreeNode getRoot() {
        return root;
    }

    /**
     * 先序遍历
     */
    public void frontShow() {
        if (root != null) {
            root.frontShow();
        }
    }

    /**
     * 中序遍历
     */
    public void middleShow() {
        if (root != null) {
            root.middleShow();
        }
    }

    /**
     * 后序遍历
     */
    public void behindShow() {
        if (root != null) {
            root.behindShow();
        }
    }

    /**
     * 查找二叉树的结点--先序查找
     *
     * @param i 查找的结点的值
     */
    public TreeNode frontSearch(int i) {
        return root.frontSearch(i);
    }

    /**
     * 查找二叉树的结点--中序查找
     *
     * @param i 查找的结点的值
     */
    public TreeNode middleSearch(int i) {
        return root.middleSearch(i);
    }

    /**
     * 查找二叉树的结点--后序查找
     *
     * @param i 查找的结点的值
     */
    public TreeNode behindSearch(int i) {
        return root.behindSearch(i);
    }

    /**
     * 删除二叉树的结点/子树
     *
     * @param i 查找的结点的值
     */
    public void deleteTreeNode(int i) {
        if (root.value == i) {
            root = null;
        } else {
            root.deleteTreeNode(i);
        }
    }
}
  • 二叉树的结点
package cn.kimtian.tree;

/**
 * 树里面的结点
 *
 * @author kimtian
 */
public class TreeNode {
    /**
     * 树里面的值,结点的权
     */
    int value;
    /**
     * 左儿子
     */
    TreeNode leftNode;
    /**
     * 右儿子
     */
    TreeNode rightNode;

    public TreeNode(int value) {
        this.value = value;
    }

    public void setLeftNode(TreeNode leftNode) {
        this.leftNode = leftNode;
    }

    public void setRightNode(TreeNode rightNode) {
        this.rightNode = rightNode;
    }

    /**
     * 先序遍历--递归思想
     */
    public void frontShow() {
        //先遍历当前结点的内容
        System.out.print(value + " ");
        //左结点
        if (leftNode != null) {
            leftNode.frontShow();
        }
        //右结点
        if (rightNode != null) {
            rightNode.frontShow();
        }
    }

    /**
     * 中序遍历
     */
    public void middleShow() {
        //左结点
        if (leftNode != null) {
            leftNode.middleShow();
        }
        System.out.print(value + " ");
        //右结点
        if (rightNode != null) {
            rightNode.middleShow();
        }
    }

    /**
     * 后序遍历
     */
    public void behindShow() {
        //左结点
        if (leftNode != null) {
            leftNode.behindShow();
        }
        //右结点
        if (rightNode != null) {
            rightNode.behindShow();
        }
        System.out.print(value + " ");
    }

    /**
     * 先序查找
     *
     * @param i 查找的结点的值
     */
    public TreeNode frontSearch(int i) {
        TreeNode target = null;
        //对比当前结点的值
        if (value == i) {
            return this;
        }
        //当前结点的值不是要查找的结点
        else {
            //查找左儿子
            if (leftNode != null) {
                target = leftNode.frontSearch(i);
            }
            if (target != null) {
                return target;
            }
            //查找右儿子
            if (rightNode != null) {
                target = rightNode.frontSearch(i);
            }
            if (target != null) {
                return target;
            }
        }
        return target;
    }

    /**
     * 中序查找
     *
     * @param i 查找的结点的值
     */
    public TreeNode middleSearch(int i) {
        TreeNode target = null;
        //对比左儿子的值
        if (leftNode != null) {
            target = leftNode.middleSearch(i);
        }
        if (target != null) {
            return target;
        }
        //对比当前结点的值
        if (value == i) {
            return this;
        }
        //查找右儿子
        if (rightNode != null) {
            target = rightNode.middleSearch(i);
        }
        if (target != null) {
            return target;
        }

        return target;
    }

    /**
     * 后序查找
     *
     * @param i 查找的结点的值
     */
    public TreeNode behindSearch(int i) {
        TreeNode target = null;
        //对比左儿子的值
        if (leftNode != null) {
            target = leftNode.behindSearch(i);
        }
        if (target != null) {
            return target;
        }
        //查找右儿子
        if (rightNode != null) {
            target = rightNode.behindSearch(i);
        }
        if (target != null) {
            return target;
        }

        //对比当前结点的值
        if (value == i) {
            return this;
        }
        return target;
    }

    /**
     * 删除二叉树的结点/子树
     *
     * @param i 要删除的结点的值
     */
    public void deleteTreeNode(int i) {
        TreeNode parent = this;
        //判断左儿子
        if (parent.leftNode != null && parent.leftNode.value == i) {
            parent.leftNode = null;
            return;
        }
        //判断右边儿子
        if (parent.rightNode != null && parent.rightNode.value == i) {
            parent.rightNode = null;
            return;
        }
        //递归检查并删除左儿子
        parent = leftNode;
        if (parent != null) {
            parent.deleteTreeNode(i);
        }
        //递归检查并删除右儿子
        parent = rightNode;
        if (parent != null) {
            parent.deleteTreeNode(i);
        }

    }
}

(3)测试类。

package cn.kimtian.tree;

/**
 * 测试链式存储的二叉树
 *
 * @author kimtian
 */
public class TestBinaryTree {
    public static void main(String[] args) {
        //创建一棵树
        BinaryTree binaryTree = new BinaryTree();
        //创建一个根结点
        TreeNode root = new TreeNode(1);
        //将根结点赋给树
        binaryTree.setRoot(root);
        //创建一个子左结点
        TreeNode leftTwo = new TreeNode(2);
        //创建一个子右结点
        TreeNode rightTwo = new TreeNode(3);
        //给根的左结点赋值
        root.setLeftNode(leftTwo);
        //给根的右结点赋值
        root.setRightNode(rightTwo);
        //第三层结点
        TreeNode llThree = new TreeNode(4);
        TreeNode lrThree = new TreeNode(5);
        TreeNode rlThree = new TreeNode(6);
        TreeNode rrThree = new TreeNode(7);
        leftTwo.setLeftNode(llThree);
        leftTwo.setRightNode(lrThree);
        rightTwo.setLeftNode(rlThree);
        rightTwo.setRightNode(rrThree);
        //先序遍历
        binaryTree.frontShow();
        System.out.println();
        //中序遍历
        binaryTree.middleShow();
        System.out.println();
        //后序遍历
        binaryTree.behindShow();
        System.out.println();
        System.out.println("====================");
        //先序查找
        TreeNode result = binaryTree.frontSearch(5);
        System.out.println(result);
        System.out.println(result == lrThree);
        TreeNode result1 = binaryTree.frontSearch(10);
        System.out.println(result1);

        System.out.println();
        System.out.println("====================");
        //中序查找
        TreeNode result2 = binaryTree.middleSearch(5);
        System.out.println(result2);
        System.out.println(result2 == lrThree);
        TreeNode result3 = binaryTree.middleSearch(10);
        System.out.println(result3);
        System.out.println();
        System.out.println("====================");

        //后序查找
        TreeNode result4 = binaryTree.behindSearch(5);
        System.out.println(result4);
        System.out.println(result4 == lrThree);
        TreeNode result5 = binaryTree.behindSearch(10);
        System.out.println(result5);
        //先序遍历
        binaryTree.frontShow();
        System.out.println();
        //删除一个子树
        binaryTree.deleteTreeNode(1);
        //先序遍历
        binaryTree.frontShow();
        System.out.println();

    }
}

二.顺序存储的二叉树的操作

顺序存储的二叉树通常情况只考虑完全二叉树。

  • 第n个元素的左子结点是2*n+1
  • 第n个元素的右子结点是2*n+2
  • 第n个元素的父结点是(n-1)/2

1.遍历二叉树

  • 先序遍历:根-->左-->右
  • 中序遍历:左-->根-->右
  • 后序遍历:左-->右-->根
package cn.kimtian.tree.arraybinarytree;

/**
 * 顺序存储的二叉树
 *
 * @author kimtian
 */
public class ArrayBinaryTree {
    /**
     * 一个存储树的数组
     */
    int[] data;

    public ArrayBinaryTree(int[] data) {
        this.data = data;
    }

    /**
     * 前序遍历
     *
     * @param index 从哪个结点开始遍历
     */
    public void frontShow(int index) {
        if (data == null || data.length == 0) {
            return;
        }
        //先遍历当前结点的内容
        System.out.print(data[index] + " ");
        //处理左子结点
        if (2 * index + 1 < data.length) {
            frontShow(2 * index + 1);
        }
        //处理右子结点
        if (2 * index + 2 < data.length) {
            frontShow(2 * index + 2);
        }
    }

    /**
     * 前序遍历 重载方法
     */
    public void frontShow() {
        frontShow(0);
    }

    /**
     * 中序遍历
     *
     * @param index 从哪个结点开始遍历
     */
    public void middleShow(int index) {
        if (data == null || data.length == 0) {
            return;
        }
        //处理左子结点
        if (2 * index + 1 < data.length) {
            middleShow(2 * index + 1);
        }
        //先遍历当前结点的内容
        System.out.print(data[index] + " ");
        //处理右子结点
        if (2 * index + 2 < data.length) {
            middleShow(2 * index + 2);
        }
    }

    /**
     * 中序遍历
     */
    public void middleShow() {
        middleShow(0);
    }

    /**
     * 后序遍历
     *
     * @param index 从哪个结点开始遍历
     */
    public void behindShow(int index) {
        if (data == null || data.length == 0) {
            return;
        }
        //处理左子结点
        if (2 * index + 1 < data.length) {
            behindShow(2 * index + 1);
        }
        //处理右子结点
        if (2 * index + 2 < data.length) {
            behindShow(2 * index + 2);
        }
        //先遍历当前结点的内容
        System.out.print(data[index] + " ");
    }

    /**
     * 后序遍历
     */
    public void behindShow() {
        behindShow(0);
    }
}

猜你喜欢

转载自blog.csdn.net/third_/article/details/85878954