平时我们也会经常见到二叉树这样的数据结构,这里就对二叉树的基本操作简单的实现:
1.二叉树的创建
2.二叉树的插入数据(遵循left<root<=right)
3.打印二叉树所有结点(中序遍历,有序的)
4.打印二叉树的深度
5.打印指定层级的所有结点.
6.使用示例
这里简单的举个例子:
例如,顺序插入数组中的数据:
int[] array = new int[]{50, 23, 45, 70, 63, 36, 80, 99, 12};
插入的时候,保证left<root<=right.
最后的效果为:

打印结果:
中序遍历:[12,23,36,45,50,63,70,80,99]
第3层所有结点:[12,45,63,80]
深度:4
如果有误还请大家给指点迷津.
1.创建二叉树
这个创建二叉树,就是创建指定的数据结构.
二叉树结点:
class TreeNode {
public int value;//当前结点值
TreeNode left;//左子树
TreeNode right;//右子树
public TreeNode(int value) {
this.value = value;
}
public TreeNode(int value, TreeNode left, TreeNode right) {
this.value = value;
this.left = left;
this.right = right;
}
}
二叉树:
class TwoBranchTree {
private TreeNode root;//根结点
private int mTreeDepth;//深度
}
2.二叉树的插入数据
2.1:插入使用的是有序插入(值比较):保证左子树<根结点<=右子树
2.2.插入顺序
(1)插入50.
(2)插入23.
23<50,则放在50的左子树
(3)插入45.
45<50,则查看其左子树,45大于了23,所以要插入23的右子树.
(4)插入70.
70大于50,所以要插入到50的右子树
(5)插入63,36,80,99,12
后面就不一一的插入了,遵循以上的插入规则,插入后面所有结点,最终形成的二叉树为:
下面对二叉树的所有操作方法:都封装到TwoBranchTree类.
/**
* 有序插入结点:左中右, 左子树<根结点<=右节点
* 如果是有序遍历打印出,那么就要调用:中序遍历
*
* @param v 插入的结点的值
*/
public void insertOrderByLmr(int v) {
//1.先查看root结点是否为null
if (root == null) {
TreeNode node = new TreeNode(v, null, null);
root = node;
} else {
TreeNode temp = root;
//2.先找到插入的位置
while (temp != null) {
if (v < temp.value) {
//3.如果插入的结点值小于比较的结点,那么就查找其左子树
if (temp.left == null) {
//3.1.找到为空的,则将结点插入到当前结点left
temp.left = new TreeNode(v, null, null);
break;
}
//3.2继续往下找
temp = temp.left;
} else if (v >= temp.value) {
//4.如果插入的结点值大于等于比较的结点,那么就查找其右子树
if (temp.right == null) {
//4.1.找到为空的,则将结点插入到当前结点left
temp.right = new TreeNode(v, null, null);
break;
}
//4.2继续往下找
temp = temp.right;
}
}
}
}
3.打印二叉树所有结点
因为插入的时候规则left<root<=right,所以要使用打印出的是有序的,则需要使用中序遍历:
中序遍历:
先打印left,打印root,打印right.
下面是遍历过程:先从树的根结点遍历.
先请忽略手画图的遍历过程,暂时还没找到合适的画曲线的工具.以后找到合适工具再补充上,如果大家有推荐的工具,还请留言,谢谢了.
12->23->36->45->50->63->70->80->99
/**
* 打印:中序遍历
*/
public void printlnMiddleOrder() {
//存储排序的结果
StringBuilder middlerResult = new StringBuilder();
//现将root赋给临时变量,防止改变root结点
TreeNode temp = root;
//开始中序遍历
middleOrder(temp, middlerResult);
//打印遍历的结果
int length = middlerResult.toString().length();
if (length > 0) {
//去掉最后一个逗号(,)
middlerResult.deleteCharAt(length - 1);
}
//组装打印格式,使用[]包起来
middlerResult.insert(0, "[");
middlerResult.append("]");
System.out.println("中序遍历:" + middlerResult.toString());
}
/**
* 中序遍历
*
* @param node 作为开始遍历的结点
* @param result 存储遍历的所有结点的值
*/
private void middleOrder(TreeNode node, StringBuilder result) {
if (node != null) {
//先遍历起左子树
middleOrder(node.left, result);
//打印根结点
result.append(node.value).append(",");
//遍历右子树
middleOrder(node.right, result);
}
}
4.打印二叉树的深度
找到结点的层级,其中最深的那个就是树的深度.
/**
* 打印深度,从1开始的
*/
public int printTreeDepth() {
TreeNode r = root;
calDepth(r, 0);
System.out.println("深度:" + mTreeDepth);
return mTreeDepth;
}
/**
* 计算深度
* 使用的是递归办法寻找最深的结点的层级,最深的层级,就是树的结点深度
*
* @param node 开始遍历的开始结点
* @param depth 当前结点的所在的层级
*/
private void calDepth(TreeNode node, int depth) {
if (node != null) {
int d = depth;
d++;
//开始比较,当前的结点
if (mTreeDepth < d) {
mTreeDepth = d;
}
//遍历左子树
calDepth(node.left, d);
//遍历右子树
calDepth(node.right, d);
}
}
非递归方法获取树的深度:
这是一个按照层级遍历树,每遍历一层,深度变量+1.
/**
* 非递归获取树的深度
*
* @return
*/
public int getDepth() {
int depth = 0;
//1.先拿到根结点
TreeNode temp = root;
//2.存储同层的结点队列,尾插入
Queue<TreeNode> queue = new LinkedList();
//队尾:入队
queue.offer(temp);
//3.遍历队列
while (!queue.isEmpty()) {
//当前层级结点数
int len = queue.size();
//层级+1
depth++;
while ((len--) > 0) {
//队头:出队列
TreeNode node = queue.poll();
if (node != null && node.left != null) {
//队尾:入队
queue.offer(node.left);
}
if (node != null && node.right != null) {
//队尾:入队
queue.offer(node.right);
}
}
}
return depth;
}
5.打印指定层级的所有结点.
遍历找到指定层级结点,然后打印,我这里是先放在stringbuilder中,然后到最后才打印.
/**
* 打印指定高度的结点
*
* @param level 指定的层级
*/
public void printNodesByLevel(int level) {
TreeNode r = root;
StringBuilder sb = new StringBuilder();
//开始查找指定层的结点
calAllNodeByLevel(r, 0, level, sb);
int length = sb.toString().length();
if (length > 0) {
sb.deleteCharAt(length - 1);
}
sb.insert(0, "[");
sb.append("]");
System.out.println("第" + level + "层所有结点:" + sb.toString());
}
/**
* 计算指定层的所有结点
* 使用递归方法找到指定深度的节点,然后存储到字符串中
*
* @param node
* @param depth
* @param level
* @param sb
*/
private void calAllNodeByLevel(TreeNode node, int depth, int level, StringBuilder sb) {
if (node != null) {
int d = depth;
d++;
//找到了指定层级的结点,然后存储到sb中
if (d == level) {
sb.append(node.value).append(",");
}
calAllNodeByLevel(node.left, d, level, sb);
calAllNodeByLevel(node.right, d, level, sb);
}
}
6.使用示例
lass Demo {
public static void main(String[] agrs) {
TwoBranchTree tree = new TwoBranchTree();
int[] array = new int[]{50, 23, 45, 70, 63, 36, 80, 99, 12};
//插入数据
for (int i = 0, size = array.length; i < size; i++) {
tree.insertOrderByLmr(array[i]);
}
//中序遍历
tree.printlnMiddleOrder();
//打印指定层的结点
tree.printNodesByLevel(3);
//打印深度
tree.printTreeDepth();
}
}
中序遍历:[12,23,36,45,50,63,70,80,99]
第3层所有结点:[12,45,63,80]
深度:4
7.扩展
1.这里是插入结点时按照(left<root<=right)规则插入,那么要想有序打印出,那么则要使用中序遍历.(left->root->right)
2.大家也可以根据例子,自己编写:
根据(left<right<=root)插入,若要有序打印出,则要使用后序遍历.
根据(root<left<=right)插入,若要有序打印出,则要使用前序遍历.