算法思路
- 找出最后一个节点的父节点
- 如果该父节点没有右子节点,则新节点就添加为它的右子节点
- 如果该父节点有右子节点,则新节点添加为该父节点下一个节点的左子节点
- 只有该父节点是根节点的情况下才可能出现没有左子节点的情况,此时新节点添加到根节点左子节点
算法实现
二叉树的实现
- 节点类
- 左右子节点的引用
Node<T> left
Node<T> right
- 保存的数据
T data
- 重写
toString()
方便查看输出结果
- 左右子节点的引用
class Node<T> {
T data;
Node<T> left = null;
Node<T> right = null;
public Node(T data) {
this.data = data;
}
@Override
public String toString() {
return "" + data;
}
}
- 二叉树类
- 根节点
Node<T> root
- 判断是否为空的方法
isEmpty()
List<Node<T>> nodes
模拟数组储存节点数据,方便索引找到节点breadthFirstTravel()
广度优先遍历方法,方便检查是否添加成功- 关于广度优先遍历查看二叉树广度优先遍历
- 根节点
public class CompleteBinaryTree<T> {
Node<T> root;
// nodes集合按添加顺序储存树的节点
List<Node<T>> nodes = new ArrayList<>();
public boolean isEmpty() {
return root == null;
}
public void breadthFirstTravel() {
if (isEmpty()) {
System.out.println("树为空");
return;
}
Queue<Node<T>> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
Node<T> cur = queue.remove();
System.out.println(cur.data);
if (cur.left != null) {
queue.add(cur.left);
}
if (cur.right != null) {
queue.add(cur.right);
}
}
}
}
具体步骤
- 判断树是否为空,是则根节点赋值为该新节点并结束方法
- 得到最后一个节点的父节点索引
int index = (nodes.size() - 1 - 1) / 2;
nodes.size()
是节点数组长度长度-1
是最后一个节点的索引(节点索引 - 1) / 2
是该节点的父节点索引
- 如果父节点有右子节点
nodes.get(index).right != null
则新节点添加到该父节点下一节点的左子节点nodes.get(index + 1).left = node
- 如果父节点有左子节点
nodes.get(index).left != null
则新节点添加到该父节点的右子节点nodes.get(index).right = node
- 特殊情况就是树只有根节点(上面已经分析过),直接添加到根节点左子节点
nodes.get(index).left = node
/**
* 添加节点
*
* @param data 节点储存数据
* @return void
*/
public void add(T data) {
Node<T> node = new Node<>(data);
nodes.add(node);
if (isEmpty()) { // 树空时添加根节点
root = node;
return;
}
// 得到最后一个节点的父节点索引
int index = (nodes.size() - 1 - 1) / 2;
// 如果该父节点有右子节点
if (nodes.get(index).right != null) {
// 则新节点的父节点是当前父节点在广度优先上的下一个节点
nodes.get(index + 1).left = node;
// 如果该父节点有左子节点(并且没有右子节点)
} else if (nodes.get(index).left != null) {
// 则新节点是该父节点的右子节点
nodes.get(index).right = node;
// 最后一种情况: 该父节点没有左子节点
} else {
nodes.get(index).left = node;
}
}
测试
- 循环添加1-9保存到树节点中
- 广度优先遍历
public static void main(String[] args) {
CompleteBinaryTree<Integer> tree = new CompleteBinaryTree<>();
for (int i = 1; i < 10; i++) {
tree.add(i);
}
tree.breadthFirstTravel();
}
输出结果:1 2 3 4 5 6 7 8 9
完整代码
class Node<T> {
T data;
Node<T> left = null;
Node<T> right = null;
public Node(T data) {
this.data = data;
}
@Override
public String toString() {
return "" + data;
}
}
public class CompleteBinaryTree<T> {
Node<T> root;
// nodes集合按添加顺序储存树的节点
List<Node<T>> nodes = new ArrayList<>();
public boolean isEmpty() {
return root == null;
}
public void breadthFirstTravel() {
if (isEmpty()) {
System.out.println("树为空");
return;
}
Queue<Node<T>> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
Node<T> cur = queue.remove();
System.out.println(cur.data);
if (cur.left != null) {
queue.add(cur.left);
}
if (cur.right != null) {
queue.add(cur.right);
}
}
}
/**
* 添加节点
*
* @param data 节点储存数据
* @return void
*/
public void add(T data) {
Node<T> node = new Node<>(data);
nodes.add(node);
if (isEmpty()) { // 树空时添加根节点
root = node;
return;
}
// 得到最后一个节点的父节点索引
int index = (nodes.size() - 1 - 1) / 2;
// 如果该父节点有右子节点
if (nodes.get(index).right != null) {
// 则新节点的父节点是当前父节点在广度优先上的下一个节点
nodes.get(index + 1).left = node;
// 如果该父节点有左子节点(并且没有右子节点)
} else if (nodes.get(index).left != null) {
// 则新节点是该父节点的右子节点
nodes.get(index).right = node;
// 最后一种情况: 该父节点没有左子节点
} else {
nodes.get(index).left = node;
}
}
public static void main(String[] args) {
CompleteBinaryTree<Integer> tree = new CompleteBinaryTree<>();
for (int i = 1; i < 10; i++) {
tree.add(i);
}
tree.breadthFirstTravel();
}
}