转载自:https://www.cnblogs.com/eudiwffe/p/6207196.html
https://blog.youkuaiyun.com/weixin_38629529/article/details/81171245
目录
4)树的遍历(前序、中序、后序、深度遍历、广度遍历、递归与非递归)
1.二叉树(Binary Tree)
一个节点分出两个节点,称其为左右子节点;每个子节点又可以分出两个子节点,这样递归分叉,其形状很像一颗倒着的树。
二叉树限制了每个节点最多有两个子节点,没有子节点的节点称为叶子。
二叉树引导出很多名词概念:
其中节点B只有一个子节点D;
叶子:D, E, F没有子节点,被称为叶子。
深度: 指的是根节点到该节点的路径长度,A的深度为0,D的深度为2
高度:只有一个节点的树,高度为0,非空树的高度为从根结点到最远的叶结点的路径长度,习惯上将空树高度定义为-1。
出度:节点C分出两子节点,所以C的出度为2;
入度:C有且只有一个父节点,所以其入度为1。
出度、入度的概念来源于图(Graph,一种更加高级复杂的数据结构),二叉树或者说树形数据结构也是一类特殊的图,
二叉树的根节点入度为0,叶子节点出度为0。
2.完全二叉树:
除了最高层以外,其余层节点个数都达到最大值,并且最高层节点都优先集中在最左边。
3.满二叉树:
除了最高层有叶子节点,其余层无叶子,并且非叶子节点都有2个子节点。
满二叉树一定是一个完全二叉树,反之则不然
4.二叉查找树
二叉查找树(binary search tree,BST)是一种特殊的二叉树,相对较小的值保存在左节点中,较大的值保存在右节点中。
二叉查找树(没有重复元素)的特征是:对于树中的每一个结点,它的左子树中结点的值都小于该结点的值,而它的右子树中结点的值都大于该结点的值。
5.二叉查找树基本方法
转载自:《Java语言程序设计进阶篇》
1)二叉查找树表示
使用一个链式结点的集合来表示二叉树。每个结点都包含一个数值和两个称为left和right的链接,分别指向左孩子和右孩子,如图所示
节点可以定义为一个类:E是泛型,表示该节点可以放不同的类型
class TreeNode<E> {
protected E element;
protected TreeNode left;
protected TreeNode right;
public TreeNode(E element) {
this.element = element;
}
}
创建一颗树:
代码如下:
TreeNode<Integer> root = new TreeNode<>(60);
root.left = new TreeNode(50);
root.right = new TreeNode(70);
变量root指向树的根结点。如果树为空,那root的值为null
2)查找一个元素
要在二叉查找树中查找一个元素,可从根结点开始向下扫描,直到找到一个匹配元素,或者达到一棵空子树为止。
该算法在程序清单1中描述。让current指向根结点,
重复下面的步骤直到current为null或者元素匹配current.element:
如果element小于current.element,就将current.left赋给current
如果element大于current.element,就将current.right赋给current
如果element等于current.element,就返回true
如果current为null,那么子树为空且该元素不在这棵树中 返回false
public boolean search(E element){
TreeNode<E> current = root;
while(current!=null){
if (element < current.element){
current = current.left;
}else if(element > current.element){
current = current.right
}else
return true;
}
return false;
}
3) 插入一个元素
为了在BST中插入一个元素,需要确定在树中插入元素的位置。关键思路是确定新结点的父结点所在的位置。
若当前树不为空,寻找新元素结点的父结点位置。 如果新元素小于父元素值,设置为左子节点,大于则设置为右子节点。
4)树的遍历
树的遍历(tree traversal)就是访问树中每个结点一次且只有一次的过程。
中序(inorder)、前序(preorder)、后序(postorder)、深度优先(depth-first)和广度优先(breadth-first)等遍历方法。
A 中序遍历(inorder traversal)法
首先递归地访问当前结点的左子树,然后访问当前结点,最后递归地访问该结点的右子树。中序遍历法以递增顺序显示BST中的所有结点。
B 后序遍历(postorder traversal)法,首先递归地访问当前结点的左子树,然后递地访问该结点的右子树,最后访问该结点本身。后序遍历的一个应用就是找出一个文件系统中目录的个数。
C 前序遍历(preorder traversal)法,首先访问当前结点,然后递归地访问该结点的左子树,最后递归地访问该结点的右子树
D 深度优先遍历法与前序遍历法相同。
E 广度优先遍历法逐层访问树中的结点。首先访问根结点,然后从左往右访问根结点的所有子结点,再从左往右访问根结点的所有孙子结点,以此类推。
public class TreeNode {
protected int data;
protected TreeNode left;
protected TreeNode right;
public TreeNode(int data) {
this.data = data;
}
/**递归 就是有调用自己————————————*/
/**前序递归遍历*/
public static void preOrder(TreeNode root){
if (root != null){
System.out.print(root.data+"\t");
preOrder(root.left);
preOrder(root.right);
}
}
/**中序递归遍历*/
public static void inOrder(TreeNode root){
if (root != null){
inOrder(root.left);
System.out.print(root.data+"\t");
inOrder(root.right);
}
}
/**后序递归遍历*/
public static void postOrder(TreeNode root){
if (root != null){
postOrder(root.left);
postOrder(root.right);
System.out.print(root.data+"\t");
}
}
/**非递归-----------非递归写法一定会用到栈-------------------*/
// 如何写非递归代码呢?
// 一句话:让代码跟着思维走。我们的思维是什么?思维就是中序遍历的路径。
// 首先,我们遍历左子树,边遍历边打印,并把根节点存入栈中,
// 以后需借助这些节点进入右子树开启新一轮的循环。
// 接下来就是:出栈,根据栈顶节点进入右子树。
/**前序非递归遍历*/
public static void preOrderNoRe(TreeNode root){
Stack<TreeNode> s = new Stack<>();
while (root != null || !s.empty()) {
//边遍历 边打印 将根节点存入栈中
while (root !=null){
System.out.print(root.data+"\t");
s.push(root);
root = root.left;
}
if (!s.empty()){
root = s.pop();
root = root.right;
}
}
}
// 中序遍历非递归
public static void inOrderNoRe(TreeNode root) {
Stack<TreeNode> s = new Stack<TreeNode>();
while (root != null || !s.empty()) {
while (root != null) {
s.push(root);
root = root.left;
}
if (!s.empty()) {
root = s.pop();
System.out.print(root.data+"\t");
root = root.right;
}
}
}
// 后序遍历非递归
public static void postOrderNoRe(TreeNode root) {
Stack<TreeNode> s = new Stack<TreeNode>();
Stack<Integer> s2 = new Stack<Integer>();
Integer i = new Integer(1);
while (root != null || !s.empty()) {
while (root != null) {
s.push(root);
s2.push(new Integer(0));
root = root.left;
}
while (!s.empty() && s2.peek().equals(i)) {
s2.pop();
System.out.print(s.pop().data+"\t");
}
if (!s.empty()) {
s2.pop();
s2.push(new Integer(1));
root = s.peek();
root = root.right;
}
}
}
}
5)删除BST中的一个元素