数据结构 二叉树的建立和递归遍历
一、二叉树的建立
1.1 概念
每一个节点最多有两个节点的树
1.2 二叉树的建立
普通节点
节点的权值: int value
左子节点 : node Lnode;
右子节点 : node rnode;
package imitate_tree;
public class node {
int value;
node Lnode;
node Rnode;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public node getLnode() {
return Lnode;
}
public void setLnode(node Lnode) {
this.Lnode = Lnode;
}
public node getRnode() {
return Rnode;
}
public void setRnode(node Rnode) {
this.Rnode = Rnode;
}
public node(int value) {
this.value = value;
}
}
- 二叉树的建立是递归建立
public static TreeNode reConstructBinaryTree (int[] preOrder, int[] vinOrder) {
// write code here
if (preOrder.length == 0 || vinOrder.length == 0) {
return null;
}
int num = preOrder[0];
TreeNode treeNode = new TreeNode(num);
int index = 0;
for (int i = 0; i < vinOrder.length; i++) {
if (vinOrder[i] == num) {
index = i;
break;
}
}
treeNode.left = reConstructBinaryTree(Arrays.copyOfRange(preOrder, 1,
index + 1), Arrays.copyOfRange(vinOrder, 0, index));
treeNode.right = reConstructBinaryTree(Arrays.copyOfRange(preOrder, index + 1,
preOrder.length), Arrays.copyOfRange(vinOrder, index + 1, vinOrder.length));
return treeNode;
}
二、二叉树的遍历
2.1先序遍历
遍历顺序
根节点 左子节点 右子节点
public static void font_sort(node root){
if(root != null){
System.out.print(root.value + " ");
}
if(root.Lnode != null){
font_sort(root.Lnode);
}
if(root.Rnode != null){
font_sort(root.Rnode);
}
}
2.2 中序遍历
遍历顺序
左子节点 根节点 右子节点
public static void middle_sort(node root){
if(root.Lnode != null){
middle_sort(root.Lnode);
}
System.out.print(root.value + " ");
if(root.Rnode != null){
middle_sort(root.Rnode);
}
}
2.3 后序遍历
遍历顺序
左子节点 右子节点 根节点
public static void after_sort(node root){
if(root.Lnode != null){
after_sort(root.Lnode);
}
if(root.Rnode != null){
after_sort(root.Rnode);
}
System.out.print(root.value + " ");
}
2.4 测试
public static void main(String[] args) {
node root = new node(1);
root root1 = new root();
root1.setRoot(root);
node node = new node(3);
node node1 = new node(2);
node node2 = new node(4);
node node3 = new node(5);
node node4 = new node(6);
root.setLnode(node1);
root.setRnode(node);
node.setLnode(node2);
node1.setLnode(node3);
node1.setRnode(node4);
System.out.println("先序遍历结果:");
font_sort(root);
System.out.println();
System.out.println("中序遍历结果");
middle_sort(root);
System.out.println();
System.out.println("后序遍历结果");
after_sort(root);
}
结果:
先序遍历结果:
1 2 5 6 3 4
中序遍历结果
5 2 6 1 4 3
后序遍历结果
5 6 2 4 3 1
2.5 结论
二叉树的递归遍历比较难理解,先序遍历比较容易理解,中序和后续比较难理解,中序和后续遍历可以看成对叶子结点的操作,比如:中序遍历,先遍历该节点的左子节点,左子节点为空,输出该节点的值,再遍历右子节点。
三、二叉树的查找
3.1 难点
用递归查找,需要有递归出口。
3.2 先序查找
public node fontReserch(int i){
node flag = null;
//falg标志,默认值为null,表示未查到。
if(this.value == i){
return this;
}
//根节点的值符合要求就返回。
else{
if(Lnode != null){
flag = Lnode.fontReserch(i);
}
if(flag != null){
return flag;
//左子节点的值符合要求,返回
}
//再查看右子节点
if(Rnode != null){
flag = Rnode.fontReserch(i);
}
}
return flag;
}
示例:
System.out.println(root.fontReserch(3));
System.out.println(root.fontReserch(7));
结果:
imitate_tree.node@15db9742
null
3.3 中序查找
public node middleSearch(int value){
node flag = null;
if(this.Lnode != null){
//flag是判断的结果
flag = Lnode.middleSearch(value);
}
if(flag != null){
return flag;
}
else{
//this不是判断的结果,需要用值取比较
if(this.value == value){
return this;
}
if(Rnode != null){
//拿到判断的结果
flag = Rnode.middleSearch(value);
}
}
return flag;
}
测试:
System.out.println(root.middleSearch(3));
System.out.println(root.middleSearch(9));
结果:
imitate_tree.node@15db9742
null
3.4 后序查找
public node afterSearch(int value){
node flag = null;
if(this.Lnode != null){
flag = Lnode.afterSearch(value);
}
if(flag != null){
return flag;
}
else{
if(this.Rnode != null){
flag = Rnode.afterSearch(value);
}
if(flag != null){
return flag;
}
if(this.value == value){
return this;
}
}
return flag;
}
测试:
System.out.println(root.afterSearch(6));
System.out.println(root.afterSearch(7));
解果:
imitate_tree.node@6d06d69c
null
3.5 总结
设置一个标志,用来记录查找的结果,找到就返回找到的节点,未找见就返回空。
二叉树的查找还是用根节点来判断,其他的就是去拿根节点的返回值。
四、节点的删除
4.1 注意
节点的删除主要是在普通节点的方法里实现,由根节点去调用节点的删除方法,然后加上根节点的判空方法。
节点的删除和正常思路一样,判断左子节点,右子节点,判断左子树,判断右子树。
不用递归遍历的方法去做删除的原因是this 不能指向空。因为赋值式的左边必须是一个变量。
普通节点实现删除方法:
public void deleteNode(int value) {
node root = this;
// 判断左子树
if (root.Lnode != null && Lnode.value == value) {
Lnode = null;
return;
}
// 判断右子树
if (root.Rnode != null && Rnode.value == value) {
Rnode = null;
return;
}
// 递归判断左子树
root = Lnode;
if (Lnode != null) {
Lnode.deleteNode(value);
}
root = Rnode;
if (Rnode != null) {
Rnode.deleteNode(value);
}
}
}
根节点调用delete方法:
public void delete(int value){
if(root.value == value){
root = null;
return;
}
else
{
root.deleteNode(value);
}
}
4.2 测试
root1.delete(2);
root1.fontSort();
结果
1
3
4