一. 递归方式
1. 前序查找
- 先判断当前节点是否要查找的节点
- 当前节点有左子树,向左递归,如果找到不为空的节点,说明查找成功
- 否则向右递归,当前节点有右子树,向右递归,如果找到不为空的节点,说明查找成功
- 否则返回null
public HeroNode preOrderSearch(int i) {
System.out.println("进入前序查找");
//比较当前结点是不是
if (this.id == i)
return this;
//1.则判断当前结点的左子节点是否为空,如果不为空,则递归前序查找
//2.如果左递归前序查找,找到结点,则返回
HeroNode node = null;
if (this.left != null) {
node = this.left.preOrderSearch(i);
}
if (node != null)
return node;
//2.当前的结点的右子节点是否为空,如果不空,则继续向右递归前序查找
if (this.right != null) {
node = this.right.preOrderSearch(i);
}
return node;
}
2. 中序查找
- 当前节点有左子树,向左递归,如果找到不为空的节点,说明查找成功
- 否则判断当前节点是否要查找的节点,如果是返回
- 否则向右递归,当前节点有右子树,向右递归,如果找到不为空的节点,说明查找成功
- 否则返回null
public HeroNode infixOrderSearch(int i) {
HeroNode node = null;
if (this.left != null) {
node = this.left.infixOrderSearch(i);
}
System.out.println("进入中序查找");
if (node != null)
return node;
//比较当前结点是不是
if (this.id == i)
return this;
if (this.right != null) {
node = this.right.infixOrderSearch(i);
}
return node;
}
3. 后序查找
- 当前节点有左子树,向左递归,如果找到不为空的节点,说明查找成功
- 否则向右递归,当前节点有右子树,向右递归,如果找到不为空的节点,说明查找成功
- 否则判断当前节点是否要查找的节点,如果是返回
- 否则返回null
public HeroNode postOrderSearch(int i) {
HeroNode node = null;
if (this.left != null) {
node = this.left.postOrderSearch(i);
}
if (node != null)
return node;
if (this.right != null) {
node = this.right.postOrderSearch(i);
}
if (node != null)
return node;
System.out.println("进入后序查找");
if (this.id == i)
return this;
return node;
}
二、非递归方式查找
1.前序查找
- 用一个栈储存当前节点
- 若栈不为空,弹出栈中一个节点,判断当前节点是否要查找的节点,如果是返回
- 否则若当前节点有右子树,右子树入栈
- 若当前节点有左子树,左子树入栈
- 栈为空,结束循环
- 否则返回null
public HeroNode preOrderSearch1(int i) {
System.out.println("前序非递归查找~~");
Stack<HeroNode> stack = new Stack<>();
stack.push(this);
while (!stack.isEmpty()) {
HeroNode node = stack.pop();
if (node.id == i)
return node;
if (node.right != null)
stack.push(node.right);
if (node.left != null)
stack.push(node.left);
}
return null;
}
2.中序查找
- 用一个临时变量代替当前节点,创建一个栈
- 若栈不为空或者当前节点不为空
- 若当前节点不为空,则循环至最左节点
- 若当前节点为空,栈弹出一个节点,判断当前节点是否为查找的节点,如果是返回
- 如果不是,若该节点有右节点,令节点等于右节点
- 否则返回null
public HeroNode infixOrderSearch1(int i) {
System.out.println("中序非递归查找~~");
Stack<HeroNode> stack = new Stack<>();
HeroNode node = this;
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.push(node);
node = node.left;
} else {
node = stack.pop();
if (node.id == i) return node;
node = node.right;
}
}
return null;
}
3.后续查找
- 用一个临时变量代替当前节点,创建两个栈s1,s2,
- 当前节点入栈S1
- 若栈s1不为空,则弹出一个节点
- 将当前节点入栈s2
- 如果当前节点有左节点,则入栈s1
- 如果当前节点有右节点,则入栈s1
- 若栈s2不为空,依次弹出元素判断是否为查找值,否则返回null
public HeroNode postOrderSearch1(int i) {
System.out.println("后序非递归查找~~");
Stack<HeroNode> s1 = new Stack<>();
Stack<HeroNode> s2 = new Stack<>();
HeroNode node = this;
s1.push(node);
while (!s1.isEmpty()){
node=s1.pop();
s2.push(node);
if(node.left!=null){
s1.push(node.left);
}
if(node.right!=null){
s1.push(node.right);
}
}
while (!s2.isEmpty()){
node=s2.pop();
if(node.id==i)
return node;
}
return null;
}
- 用一个临时变量代替当前节点,lastnode代表最右节点;创建1个栈s1
- 若当前节点不为空,则循环至最左节点入栈s1
- 若栈s1不为空,则弹出一个节点
- 若当前节点有有右节点,且右节点没有被访问过,则当前节点变为右节点,循环至右节点的最左节点
- 否则判断当前是否为查找值,将当前节点的值赋给lastnode,标记已访问
- 否则返回null
public HeroNode postOrderSearch2(int i) {
System.out.println("后序非递归查找~~");
Stack<HeroNode> s1 = new Stack<>();
HeroNode node = this;
HeroNode lasrnode = null;
while (node!=null){
s1.push(node);
node=node.left;
}
while (!s1.isEmpty()){
node=s1.pop();
if(node.right!=null&& node.right!=lasrnode){
s1.push(node);
node=node.right;
while (node!=null){
s1.push(node);
node=node.left;
}
}else {
if(node.id==i)
return node;
lasrnode=node;
}
}
return null;
}
}
三、二叉树删除节点
- 因为我们的二叉树是单向的,所以我们是判断当前结点的子结点是否需要删除结点,而不能去判断当前这个结点是不是需要删除结点.
- 如果当前结点的左子结点不为空,并且左子结点 就是要删除结点,就将this.left = null; 并且就返回(结束递归删除)
- 如果当前结点的右子结点不为空,并且右子结点 就是要删除结点,就将this.right= null ;并且就返回(结束递归删除)
- 如果第2和第3步没有删除结点,那么我们就需要向左子树进行递归删除
- 如果第4步也没有删除结点,则应当向右子树进行递归删除.
public void delNode(int i) {
if(root==null) return;
if(root.id==i)
root=null;
else root.delNode(i);
}
public void delNode(int i) {
if(this.left!=null&&this.left.id==i){
this.left=null;
return;
}
if(this.right!=null&&this.right.id==i){
this.right=null;
return;
}
if(this.left!=null)
this.left.delNode(i);
if(this.right!=null)
this.right.delNode(i);
}
- 找到该值,如果该节点为叶子节点或者该节点只有左节点,返回该节点的左子树
- 如果用该节点的右节点的最左节点与该节点进行值交换
- 递归得到总树
public HeroNode delNode1(HeroNode root,int i) {
if (root == null) return root;
if (root.id == i) {
if (root.right == null) { // 这里第二次操作目标值:最终删除的作用
return root.left;
}
HeroNode cur = root.right;
while (cur.left!=null) {
cur = cur.left;
}
HeroNode node = new HeroNode(root.id, root.name);
root.id=cur.id;
root.name=cur.name;
cur.id=node.id;
cur.name=node.name;// 这里第一次操作目标值:交换目标值其右子树最左面节点。仅仅是值替换,引用没有交换
}
root.left = delNode1(root.left, i);
root.right = delNode1(root.right, i);
return root;
}