转载请注明出处:
http://blog.csdn.net/gane_cheng/article/details/52643120
http://www.ganecheng.tech/blog/52643120.html (浏览效果更好)
百度面试很喜欢问树,直接被虐惨。有必要对数据结构中的各种树进行仔细的研究。本篇博客重点研究二叉搜索树。
数据结构中为了存储和查找的方便,用各种树结构来存储数据,下面就浅谈一下各种树的表示方法、特点及各自的用途,涉及的树结构包括:二叉搜索树(二叉查找树,二叉排序树)、平衡二叉树(AVL树)、红黑树、B-树、B+树、字典树(trie树)、后缀树、广义后缀树。
① 二叉搜索树(二叉查找树,二叉排序树)
二叉查找树是一种动态查找表,具有这些性质:
(1)若它的左子树不为空,则左子树上的所有节点的值都小于它的根节点的值;
(2)若它的右子树不为空,则右子树上所有节点的值都大于它的根节点的值;
(3)其他的左右子树也分别为二叉查找树;
(4)二叉查找树是动态查找表,在查找的过程中可见添加和删除相应的元素,在这些操作中需要保持二叉查找树的以上性质。
② 平衡二叉树(AVL树)
含有相同节点的二叉查找树可以有不同的形态,而二叉查找树的平均查找长度与树的深度有关,所以需要找出一个查找平均长度最小的一棵,那就是平衡二叉树,具有以下性质:
(1)要么是棵空树,要么其根节点左右子树的深度之差的绝对值不超过1;
(2)其左右子树也都是平衡二叉树;
(3)二叉树节点的平衡因子定义为该节点的左子树的深度减去右子树的深度。则平衡二叉树的所有节点的平衡因子只可能是-1,0,1。
③ 红黑树
红黑树是一种自平衡二叉树,在平衡二叉树的基础上每个节点又增加了一个颜色的属性,节点的颜色只能是红色或黑色。具有以下性质:
(1)根节点只能是黑色;
(2)红黑树中所有的叶子节点后面再接上左右两个空节点,这样可以保持算法的一致性,而且所有的空节点都是黑色;
(3)其他的节点要么是红色,要么是黑色,红色节点的父节点和左右孩子节点都是黑色,及黑红相间;
(4)在任何一棵子树中,从根节点向下走到空节点的路径上所经过的黑节点的数目相同,从而保证了是一个平衡二叉树。
④ B-树
B-树是一种平衡多路查找树,它在文件系统中很有用。一棵m阶B-树,具有下列性质:
(1)树中每个节点至多有m棵子树;
(2)若根节点不是叶子节点,则至少有2棵子树;
(3)除根节点之外的所有非终端节点至少有棵子树;
(4)每个节点中的信息结构为(A0,K1,A1,K2……Kn,An),其中n表示关键字个数,Ki为关键字,Ai为指针;
(5)所有的叶子节点都出现在同一层次上,且不带任何信息,也是为了保持算法的一致性。
⑤ B+树
B+数是B-树的一种变形,它与B-树的差别在于:
(1)有n棵子树的节点含有n个关键字;
(2)所有的叶子节点包含了全部关键字的信息,及指向这些关键字记录的指针,且叶子节点本身按关键字大小自小到大顺序链接;
(3)所有非终端节点可以看成是索引部分,节点中仅含有其子树(根节点)中最大(或最小)关键字,所有B+树更像一个索引顺序表;
(4)对B+树进行查找运算,一是从最小关键字起进行顺序查找,二是从根节点开始,进行随机查找。
⑥ 字典树(trie树)
字典树是一种以树形结构保存大量字符串。以便于字符串的统计和查找,经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比较,查询效率比哈希表高。具有以下特点:
(1)根节点为空;
(2)除根节点外,每个节点包含一个字符;
(3)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
(4)每个字符串在建立字典树的过程中都要加上一个区分的结束符,避免某个短字符串正好是某个长字符串的前缀而淹没。
⑦ 后缀树
后缀树则是一个字符串的所有后缀组成的字典树。
⑧ 广义后缀树
广义后缀树是好几个字符串的的所有后缀组成的字典树,同样每个字符串的所有后缀都具有一个相同的结束符,不同字符串的结束符不同。
二叉搜索树和二分查找法类似,可以在O(logN)的时间里查找到想要的元素,同时又具有链表的优点,插入,删除节点快。
下面从插入,查找,删除,前序遍历,中序遍历,后序遍历,深度优先遍历,广度优先遍历,求深度,求最小值,求最大值,这些方面来深入对二叉搜索树这种高效的数据结构的理解。
先来定义二叉搜索树的数据结构
class Node
{
int value;
Node leftChild;
Node rightChild;
Node(int value)
{
this.value = value;
}
}
插入(递归)
/** * 插入元素,构造二叉查找树 * * @param value * 整数 * @param node */
public void insert(int value, Node node)
{
if (value < node.value)
{
if (node.leftChild != null)
{
insert(value, node.leftChild);
}
else
{
node.leftChild = new Node(value);
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
insert(value, node.rightChild);
}
else
{
node.rightChild = new Node(value);
}
}
}
插入(非递归)
/** * 插入元素,构造二叉查找树(非递归) * * @param value * 整数 * @param node */
public void insertNoRecursion(int value, Node node)
{
while (true)
{
if (value < node.value)
{
if (node.leftChild != null)
{
node = node.leftChild;
}
else
{
node.leftChild = new Node(value);
return;
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
node = node.rightChild;
}
else
{
node.rightChild = new Node(value);
return;
}
}
}
}
查找(递归)
/** * 查找元素,从二叉查找树中查找某个元素 * * @param value * 整数 * @param node */
public boolean search(int value, Node node)
{
if (value < node.value)
{
if (node.leftChild != null)
{
return search(value, node.leftChild);
}
else
{
return false;
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
return search(value, node.rightChild);
}
else
{
return false;
}
}
else
{
return true;
}
}
查找(非递归)
/** * 查找元素,从二叉查找树中查找某个元素(非递归) * * @param value * 整数 * @param node */
public boolean searchNoRecursion(int value, Node node)
{
while (true)
{
if (value < node.value)
{
if (node.leftChild != null)
{
node = node.leftChild;
}
else
{
return false;
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
node = node.rightChild;
}
else
{
return false;
}
}
else
{
return true;
}
}
}
删除
// 删除节点分三种方式删除节点
// 1、删除没有子节点的节点,直接让该节点的父节点的左节点或右节点指向空
// 2、删除有一个子节点的节点,直接让该节点的父节点指向被删除节点的剩余节点
// 3、删除有三个节点的子节点,找到要删除节点的后继节点, 用该节点替代删除的节点
public Node delete(int Key, Node root) throws Exception
{
// 首先查找节点,并记录该节点的父节点引用
Node current = root;
Node parent = root;
boolean isLeftNode = true;
while (current != null && current.value != Key)
{
parent = current;
if (Key < current.value)
{
isLeftNode = true;
current = current.leftChild;
}
else
{
isLeftNode = false;
current = current.rightChild;
}
}
if (current == null)
{
System.out.println("没有找到要删除的节点!");
throw new Exception("没有找到要删除的节点!");
}
// 下面分三种情况删除节点
if (current.leftChild == null && current.rightChild == null)
{ // 要删除的节点没有子节点
if (current == root)
{ // 根节点就删除整棵树
root = null;
}
else if (isLeftNode)
{ // 如果是左节点,做节点指向空
parent.leftChild = null;
}
else
{ // 如果是右节点,右节点指向空
parent.rightChild = null;
}
}
else if (current.leftChild == null)
{ // 要删除的节点只有右节点
if (current == root)
{
root = current.rightChild;
}
else if (isLeftNode)
{
parent.leftChild = current.rightChild;
}
else
{
parent.rightChild = current.rightChild;
}
}
else if (current.rightChild == null)
{ // 要删除的节点只有左节点
if (current == root)
{
root = current.leftChild;
}
else if (isLeftNode)
{
parent.leftChild = current.leftChild;
}
else
{
parent.rightChild = current.leftChild;
}
}
else
{ // 要删除的节点有两个节点
Node successor = findSuccessor(current);
if (current == root)
{
root = successor;
}
else if (isLeftNode)
{
parent.leftChild = successor;
}
else
{
parent.rightChild = successor;
}
successor.leftChild = current.leftChild;
}
return root;
}
private Node findSuccessor(Node delNode)
{
Node parent = delNode;
Node successor = delNode;
Node current = delNode.rightChild;
while (current != null)
{
parent = successor;
successor = current;
current = current.leftChild;
}
if (successor != delNode.rightChild)
{
parent.leftChild = successor.rightChild;
successor.rightChild = delNode.rightChild;
}
return successor;
}
删除的原理可以参考这篇文章
http://marcospring.iteye.com/blog/1623571
前序遍历(递归)
/** * 递归先序遍历 * * @param node */
public void preTraverse(Node node)
{
if (node == null)
{
return;
}
System.out.print(node.value + " ");
preTraverse(node.leftChild);
preTraverse(node.rightChild);
}
前序遍历(非递归)
/** * 非递归先序遍历(用栈来实现,先将右节点压入栈,再将左节点压入栈) * * @param node */
public void preTraverseNoRecursion(Node node)
{
Stack<Node> stack = new Stack<Node>();
if (node != null)
{
stack.push(node);
}
while (!stack.isEmpty())
{
node = stack.pop();
System.out.print(node.value + " ");
if (node.rightChild != null)
{
stack.push(node.rightChild);
}
if (node.leftChild != null)
{
stack.push(node.leftChild);
}
}
}
/** * 非递归先序遍历2(先输出自身,再向左走到底,在返回来输出右节点) * * @param node */
public void preTraverseNoRecursion2(Node node)
{
Stack<Node> stack = new Stack<Node>();
while (node != null || stack.size() > 0)
{
while (node != null)
{
System.out.print(node.value + " ");
stack.push(node);
node = node.leftChild;
}
if (stack.size() > 0)
{
node = stack.pop();
node = node.rightChild;
}
}
}
中序遍历(递归)
/** * 递归中序遍历 * * @param node */
public void midTraverse(Node node)
{
if (node.leftChild != null)
{
midTraverse(node.leftChild);
}
System.out.print(node.value + " ");
if (node.rightChild != null)
{
midTraverse(node.rightChild);
}
}
中序遍历(非递归)
/** * 非递归中序遍历 * * @param node */
public void midTraverseNoRecursion(Node node)
{
Stack<Node> stack = new Stack<Node>();
while (node != null || stack.size() > 0)
{
while (node != null)
{
stack.push(node);
node = node.leftChild;
}
if (stack.size() > 0)
{
node = stack.pop();
System.out.print(node.value + " ");
node = node.rightChild;
}
}
}
后序遍历(递归)
/** * 递归后序遍历 * * @param node */
public void postTraverse(Node node)
{
if (node.leftChild != null)
{
postTraverse(node.leftChild);
}
if (node.rightChild != null)
{
postTraverse(node.rightChild);
}
System.out.print(node.value + " ");
}
后序遍历(非递归)
/** * 非递归后序遍历 * * @param node */
public void postTraverseNoRecursion(Node node)
{
Stack<Node> stack = new Stack<Node>();
Stack<Node> temp = new Stack<Node>();
while (node != null || stack.size() > 0)
{
while (node != null)
{
stack.push(node);
temp.push(node);
node = node.rightChild;
}
if (stack.size() > 0)
{
node = stack.pop();
node = node.leftChild;
}
}
while (temp.size() > 0)
{
node = temp.pop();
System.out.print(node.value + " ");
}
}
深度优先遍历(递归)
和前序遍历的递归实现一样。
深度优先遍历(非递归)
/** * 深度优先遍历(用栈实现) * * @param node */
public void depthTraverse(Node node)
{
Stack<Node> stack = new Stack<Node>();
stack.push(node);
while (!stack.isEmpty())
{
node = stack.pop();
System.out.print(node.value + " ");
if (node.rightChild != null)
{
stack.push(node.rightChild);
}
if (node.leftChild != null)
{
stack.push(node.leftChild);
}
}
}
广度优先遍历(递归)
广度优先遍历怎么用递归实现,暂时还想不出来,等找到方法了再加进来。
广度优先遍历(非递归)
/** * 广度优先遍历(用队列实现) * * @param node */
public void breadthTraverse(Node node)
{
Queue<Node> queue = new LinkedList<Node>();
queue.add(node);
while (!queue.isEmpty())
{
node = queue.remove();
System.out.print(node.value + " ");
if (node.leftChild != null)
{
queue.add(node.leftChild);
}
if (node.rightChild != null)
{
queue.add(node.rightChild);
}
}
}
求深度(递归)
/** * 递归求深度(分治法,交给左右子树分别去计算深度,然后在合并计算结果) * * @param node * @return */
public int depthRecursion(Node node)
{
if (node == null)
{
return 0;
}
int leftChildDepth = depthRecursion(node.leftChild);
int rightChildDepth = depthRecursion(node.rightChild);
return leftChildDepth >= rightChildDepth ? leftChildDepth + 1 : rightChildDepth + 1;
}
求深度(非递归)
/** * 非递归求深度(利用广度优先遍历的思维,每次将下一层的节点加进来,直到下一层没有节点为止) * * @param node */
public void depthNoRecursion(Node node)
{
Queue<Node> queue = new LinkedList<Node>();
queue.add(node);
int level = 1;
System.out.print(node.value + " ");
while (!queue.isEmpty())
{
List<Node> list2 = new ArrayList<Node>();
boolean flag = false;
while (!queue.isEmpty())
{
list2.add(queue.remove());
}
for (int i = 0; i < list2.size(); i++)
{
Node temp = list2.get(i);
if (temp.leftChild != null)
{
queue.add(temp.leftChild);
System.out.print(temp.leftChild.value + " ");
flag = true;
}
if (temp.rightChild != null)
{
queue.add(temp.rightChild);
System.out.print(temp.rightChild.value + " ");
flag = true;
}
}
if (flag)
{
level++;
}
}
System.out.println("深度为:" + level);
}
求最小值(递归)
/** * 最小值 * * @param node * @return */
public int min(Node node)
{
if (node.leftChild == null)
{
return node.value;
}
else
{
return min(node.leftChild);
}
}
求最小值(非递归)
/** * 最小值(非递归,使用while循环) * * @param node * @return */
public int minNoRecursion(Node node)
{
Node parent = null;
while (node != null)
{
parent = node;
node = node.leftChild;
}
return parent.value;
}
求最大值(递归)
/** * 最大值 * * @return */
public int max(Node node)
{
if (node.rightChild == null)
{
return node.value;
}
else
{
return max(node.rightChild);
}
}
求最大值(非递归)
/** * 最大值(非递归,使用while循环) * * @return */
public int maxNoRecursion(Node node)
{
Node parent = null;
while (node != null)
{
parent = node;
node = node.rightChild;
}
return parent.value;
}
全部源码
import java.util.*;
public class BinaryTree {
static class Node
{
int value;
Node leftChild;
Node rightChild;
Node(int value)
{
this.value = value;
}
}
/** * 插入元素,构造二叉查找树 * * @param value * 整数 * @param node */
public void insert(int value, Node node)
{
if (value < node.value)
{
if (node.leftChild != null)
{
insert(value, node.leftChild);
}
else
{
node.leftChild = new Node(value);
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
insert(value, node.rightChild);
}
else
{
node.rightChild = new Node(value);
}
}
}
/** * 插入元素,构造二叉查找树(非递归) * * @param value * 整数 * @param node */
public void insertNoRecursion(int value, Node node)
{
while (true)
{
if (value < node.value)
{
if (node.leftChild != null)
{
node = node.leftChild;
}
else
{
node.leftChild = new Node(value);
return;
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
node = node.rightChild;
}
else
{
node.rightChild = new Node(value);
return;
}
}
}
}
/** * 查找元素,从二叉查找树中查找某个元素 * * @param value * 整数 * @param node */
public boolean search(int value, Node node)
{
if (value < node.value)
{
if (node.leftChild != null)
{
return search(value, node.leftChild);
}
else
{
return false;
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
return search(value, node.rightChild);
}
else
{
return false;
}
}
else
{
return true;
}
}
/** * 查找元素,从二叉查找树中查找某个元素(非递归) * * @param value * 整数 * @param node */
public boolean searchNoRecursion(int value, Node node)
{
while (true)
{
if (value < node.value)
{
if (node.leftChild != null)
{
node = node.leftChild;
}
else
{
return false;
}
}
else if (value > node.value)
{
if (node.rightChild != null)
{
node = node.rightChild;
}
else
{
return false;
}
}
else
{
return true;
}
}
}
/** * 递归先序遍历 * * @param node */
public void preTraverse(Node node)
{
if (node == null)
{
return;
}
System.out.print(node.value + " ");
preTraverse(node.leftChild);
preTraverse(node.rightChild);
}
/** * 非递归先序遍历(用栈来实现,先将右节点压入栈,再将左节点压入栈) * * @param node */
public void preTraverseNoRecursion(Node node)
{
Stack<Node> stack = new Stack<Node>();
if (node != null)
{
stack.push(node);
}
while (!stack.isEmpty())
{
node = stack.pop();
System.out.print(node.value + " ");
if (node.rightChild != null)
{
stack.push(node.rightChild);
}
if (node.leftChild != null)
{
stack.push(node.leftChild);
}
}
}
/** * 非递归先序遍历2(先输出自身,再向左走到底,在返回来输出右节点) * * @param node */
public void preTraverseNoRecursion2(Node node)
{
Stack<Node> stack = new Stack<Node>();
while (node != null || stack.size() > 0)
{
while (node != null)
{
System.out.print(node.value + " ");
stack.push(node);
node = node.leftChild;
}
if (stack.size() > 0)
{
node = stack.pop();
node = node.rightChild;
}
}
}
/** * 递归中序遍历 * * @param node */
public void midTraverse(Node node)
{
if (node.leftChild != null)
{
midTraverse(node.leftChild);
}
System.out.print(node.value + " ");
if (node.rightChild != null)
{
midTraverse(node.rightChild);
}
}
/** * 非递归中序遍历 * * @param node */
public void midTraverseNoRecursion(Node node)
{
Stack<Node> stack = new Stack<Node>();
while (node != null || stack.size() > 0)
{
while (node != null)
{
stack.push(node);
node = node.leftChild;
}
if (stack.size() > 0)
{
node = stack.pop();
System.out.print(node.value + " ");
node = node.rightChild;
}
}
}
/** * 递归后序遍历 * * @param node */
public void postTraverse(Node node)
{
if (node.leftChild != null)
{
postTraverse(node.leftChild);
}
if (node.rightChild != null)
{
postTraverse(node.rightChild);
}
System.out.print(node.value + " ");
}
/** * 非递归后序遍历 * * @param node */
public void postTraverseNoRecursion(Node node)
{
Stack<Node> stack = new Stack<Node>();
Stack<Node> temp = new Stack<Node>();
while (node != null || stack.size() > 0)
{
while (node != null)
{
stack.push(node);
temp.push(node);
node = node.rightChild;
}
if (stack.size() > 0)
{
node = stack.pop();
node = node.leftChild;
}
}
while (temp.size() > 0)
{
node = temp.pop();
System.out.print(node.value + " ");
}
}
/** * 深度优先遍历(用栈实现) * * @param node */
public void depthTraverse(Node node)
{
Stack<Node> stack = new Stack<Node>();
stack.push(node);
while (!stack.isEmpty())
{
node = stack.pop();
System.out.print(node.value + " ");
if (node.rightChild != null)
{
stack.push(node.rightChild);
}
if (node.leftChild != null)
{
stack.push(node.leftChild);
}
}
}
/** * 广度优先遍历(用队列实现) * * @param node */
public void breadthTraverse(Node node)
{
Queue<Node> queue = new LinkedList<Node>();
queue.add(node);
while (!queue.isEmpty())
{
node = queue.remove();
System.out.print(node.value + " ");
if (node.leftChild != null)
{
queue.add(node.leftChild);
}
if (node.rightChild != null)
{
queue.add(node.rightChild);
}
}
}
/** * 递归求深度(分治法,交给左右子树分别去计算深度,然后在合并计算结果) * * @param node * @return */
public int depthRecursion(Node node)
{
if (node == null)
{
return 0;
}
int leftChildDepth = depthRecursion(node.leftChild);
int rightChildDepth = depthRecursion(node.rightChild);
return leftChildDepth >= rightChildDepth ? leftChildDepth + 1 : rightChildDepth + 1;
}
/** * 非递归求深度(利用广度优先遍历的思维,每次将下一层的节点加进来,直到下一层没有节点为止) * * @param node */
public void depthNoRecursion(Node node)
{
Queue<Node> queue = new LinkedList<Node>();
queue.add(node);
int level = 1;
System.out.print(node.value + " ");
while (!queue.isEmpty())
{
List<Node> list2 = new ArrayList<Node>();
boolean flag = false;
while (!queue.isEmpty())
{
list2.add(queue.remove());
}
for (int i = 0; i < list2.size(); i++)
{
Node temp = list2.get(i);
if (temp.leftChild != null)
{
queue.add(temp.leftChild);
System.out.print(temp.leftChild.value + " ");
flag = true;
}
if (temp.rightChild != null)
{
queue.add(temp.rightChild);
System.out.print(temp.rightChild.value + " ");
flag = true;
}
}
if (flag)
{
level++;
}
}
System.out.println("深度为:" + level);
}
/** * 最大值(非递归,使用while循环) * * @return */
public int maxNoRecursion(Node node)
{
Node parent = null;
while (node != null)
{
parent = node;
node = node.rightChild;
}
return parent.value;
}
/** * 最大值 * * @return */
public int max(Node node)
{
if (node.rightChild == null)
{
return node.value;
}
else
{
return max(node.rightChild);
}
}
/** * 最小值(非递归,使用while循环) * * @param node * @return */
public int minNoRecursion(Node node)
{
Node parent = null;
while (node != null)
{
parent = node;
node = node.leftChild;
}
return parent.value;
}
/** * 最小值 * * @param node * @return */
public int min(Node node)
{
if (node.leftChild == null)
{
return node.value;
}
else
{
return min(node.leftChild);
}
}
// 删除节点分三种方式删除节点
// 1、删除没有子节点的节点,直接让该节点的父节点的左节点或右节点指向空
// 2、删除有一个子节点的节点,直接让该节点的父节点指向被删除节点的剩余节点
// 3、删除有三个节点的子节点,找到要删除节点的后继节点, 用该节点替代删除的节点
public Node delete(int Key, Node root) throws Exception
{
// 首先查找节点,并记录该节点的父节点引用
Node current = root;
Node parent = root;
boolean isLeftNode = true;
while (current != null && current.value != Key)
{
parent = current;
if (Key < current.value)
{
isLeftNode = true;
current = current.leftChild;
}
else
{
isLeftNode = false;
current = current.rightChild;
}
}
if (current == null)
{
System.out.println("没有找到要删除的节点!");
throw new Exception("没有找到要删除的节点!");
}
// 下面分三种情况删除节点
if (current.leftChild == null && current.rightChild == null)
{ // 要删除的节点没有子节点
if (current == root)
{ // 根节点就删除整棵树
root = null;
}
else if (isLeftNode)
{ // 如果是左节点,做节点指向空
parent.leftChild = null;
}
else
{ // 如果是右节点,右节点指向空
parent.rightChild = null;
}
}
else if (current.leftChild == null)
{ // 要删除的节点只有右节点
if (current == root)
{
root = current.rightChild;
}
else if (isLeftNode)
{
parent.leftChild = current.rightChild;
}
else
{
parent.rightChild = current.rightChild;
}
}
else if (current.rightChild == null)
{ // 要删除的节点只有左节点
if (current == root)
{
root = current.leftChild;
}
else if (isLeftNode)
{
parent.leftChild = current.leftChild;
}
else
{
parent.rightChild = current.leftChild;
}
}
else
{ // 要删除的节点有两个节点
Node successor = findSuccessor(current);
if (current == root)
{
root = successor;
}
else if (isLeftNode)
{
parent.leftChild = successor;
}
else
{
parent.rightChild = successor;
}
successor.leftChild = current.leftChild;
}
return root;
}
private Node findSuccessor(Node delNode)
{
Node parent = delNode;
Node successor = delNode;
Node current = delNode.rightChild;
while (current != null)
{
parent = successor;
successor = current;
current = current.leftChild;
}
if (successor != delNode.rightChild)
{
parent.leftChild = successor.rightChild;
successor.rightChild = delNode.rightChild;
}
return successor;
}
public static void main(String[] args)
{
Node root = new Node(5);
BinaryTree btree = new BinaryTree();
btree.insertNoRecursion(4, root);
btree.insertNoRecursion(7, root);
btree.insertNoRecursion(1, root);
btree.insert(3, root);
btree.insert(8, root);
btree.insert(6, root);
btree.insert(9, root);
btree.preTraverse(root);
System.out.println();
btree.preTraverseNoRecursion(root);
System.out.println();
btree.preTraverseNoRecursion2(root);
System.out.println();
btree.midTraverse(root);
System.out.println();
btree.midTraverseNoRecursion(root);
System.out.println();
btree.postTraverse(root);
System.out.println();
btree.postTraverseNoRecursion(root);
System.out.println();
btree.depthTraverse(root);
System.out.println();
btree.breadthTraverse(root);
System.out.println();
System.out.println(btree.depthRecursion(root));
System.out.println();
btree.depthNoRecursion(root);
System.out.println();
System.out.println("查找元素:" + btree.search(3, root));
System.out.println("查找元素非递归:" + btree.searchNoRecursion(4, root));
System.out.println("最大值:" + btree.max(root));
System.out.println("最大值非递归:" + btree.maxNoRecursion(root));
System.out.println("最小值:" + btree.min(root));
System.out.println("最小值非递归:" + btree.minNoRecursion(root));
try
{
root = btree.delete(5, root);
}
catch (Exception e)
{
System.out.println("没有此元素,删除失败");
}
btree.breadthTraverse(root);
}
}
二叉搜索树的应用非常广泛。搜索平均效率是O(LogN),但是如果全是左子树,或者是右子树,搜索时间会直接下降到O(N),因此,只有在左右子树深度差不多的时候,才是最理想的状态。平衡二叉树就是为了解决这个问题。下一篇博客,会重点研究平衡二叉树。
参考文献
1.http://www.cnblogs.com/zwj911112/articles/3875433.html
2.http://blog.csdn.net/sinat_26533265/article/details/51247920
3.http://blog.csdn.net/lingzhm/article/details/44497191
4.http://marcospring.iteye.com/blog/1623571