赞
踩
和链表一样,是一种动态数据结构
class Node{
E e;
Node left;
Node right
}
二叉树具有唯一根节点
每个节点最多有两个孩子(left–左孩子,right–右孩子)
每个节点最多有一个父亲 (根节点没有父节点)
没有孩子的节点–>叶子节点
二叉树具有天然的递归结构
二分搜索树是二叉树
二分搜索树的每个节点的值:
每⼀棵子树也是二分搜索树
存储的元素必须有可比较性
我们的二分搜索树不不包含重复元素
如果想包含重复元素的话,只需要定义:
左子树小于等于节点;或者右⼦子树⼤大于等于节点
注意:我们之前讲的数组和链表,可以有重复元素
二分搜索树添加元素的非递归写法,和链表很像
代码定义如下:
public class BST<E extends Comparable<E>> { private class Node{ public E e; public Node left, right; public Node(E e){ this.e = e; left = null; right = null; } } private Node root; private int size; public BST(){ root = null; size = 0; } public int size(){ return size; } public boolean isEmpty(){ return size == 0; } }
使用递归方法在二分搜索树上添加新的元素
// 向二分搜索树中添加新的元素e public void add(E e){ root = add(root, e); } // 向以node为根的二分搜索树中插入元素e,递归算法 // 返回插入新节点后二分搜索树的根 private Node add(Node node, E e){ if(node == null){ size ++; return new Node(e); } if(e.compareTo(node.e) < 0) node.left = add(node.left, e); else if(e.compareTo(node.e) > 0) node.right = add(node.right, e); return node; } // 看二分搜索树中是否包含元素e public boolean contains(E e){ return contains(root, e); } // 看以node为根的二分搜索树中是否包含元素e, 递归算法 private boolean contains(Node node, E e){ if(node == null) return false; if(e.compareTo(node.e) == 0) return true; else if(e.compareTo(node.e) < 0) return contains(node.left, e); else // e.compareTo(node.e) > 0 return contains(node.right, e); }
深度优先遍历:(具体来说是根据 根节点的遍历顺序)的遍历有三种遍历方式:
前序遍历、中序遍历、后序遍历
顺序为:根节点-->左节点-->右节点,
根据前序遍历对上图的二分搜索树进行遍历得到结果如下:
中序遍历:
(可以看作是 当遍历到节点中 中间的点时 可以读取节点中的数据)
顺序表示:
1 -> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> 10-> 11-> 12-> 13-> 14-> 15-> 16-> 17-> 18-> 19-> 20-> 21
后序遍历:
(可以看作是 当遍历到节点中 最右的点时 可以读取节点中的数据)
顺序表示:
1 -> 2-> 3-> 4-> 5-> 6-> 7-> 8-> 9-> 10-> 11-> 12-> 13-> 14-> 15-> 16-> 17-> 18-> 19-> 20-> 21
此处的代码实现都运用了递归的算法,非递归的方法也可以实现三种遍历,在此不再赘述,可以放在后面可以让读者自行研究
@Override public String toString(){ StringBuilder res = new StringBuilder(); generateBSTString(root, 0, res); return res.toString(); } // 生成以node为根节点,深度为depth的描述二叉树的字符串 private void generateBSTString(Node node, int depth, StringBuilder res){ if(node == null){ res.append(generateDepthString(depth) + "null\n"); return; } res.append(generateDepthString(depth) + node.e + "\n"); generateBSTString(node.left, depth + 1, res); generateBSTString(node.right, depth + 1, res); } private String generateDepthString(int depth){ StringBuilder res = new StringBuilder(); for(int i = 0 ; i < depth ; i ++) res.append("--"); return res.toString(); }
以此二分搜索树为例
/
// 5 //
// / \ //
// 3 6 //
// / \ \ //
// 2 4 8 //
/
// 二分搜索树的前序遍历
public void preOrder(){
preOrder(root);
}
// 前序遍历以node为根的二分搜索树, 递归算法
private void preOrder(Node node){
if(node == null)
return;
System.out.println(node.e);
preOrder(node.left);
preOrder(node.right);
}
//测试类 public class Main { public static void main(String[] args) { BST<Integer> bst = new BST<>(); int[] nums = {5, 3, 6, 8, 4, 2}; for(int num: nums) bst.add(num); System.out.println(); System.out.println(bst); } //打印结果: 5 --3 ----2 ------null ------null ----4 ------null ------null --6 ----null ----8 ------null ------null }
// 二分搜索树的中序遍历
public void inOrder(){
inOrder(root);
}
// 中序遍历以node为根的二分搜索树, 递归算法
private void inOrder(Node node){
if(node == null)
return;
inOrder(node.left);
System.out.println(node.e);
inOrder(node.right);
}
//测试结果
2
3
4
5
6
8
// 二分搜索树的后序遍历
public void postOrder(){
postOrder(root);
}
// 后序遍历以node为根的二分搜索树, 递归算法
private void postOrder(Node node){
if(node == null)
return;
postOrder(node.left);
postOrder(node.right);
System.out.println(node.e);
}
//测试结果
2
4
3
8
6
5
//前序遍历 public void preOrderNR(){ if(root == null) return; Stack<Node> stack = new Stack<>(); stack.push(root); while(!stack.isEmpty()){ Node cur = stack.pop(); System.out.println(cur.e); if(cur.right != null) stack.push(cur.right); if(cur.left != null) stack.push(cur.left); } } //层序遍历 public void levelOrder(){ if(root == null) return; Queue<Node> q = new LinkedList<>(); q.add(root); while(!q.isEmpty()){ Node cur = q.remove(); System.out.println(cur.e); if(cur.left != null) q.add(cur.left); if(cur.right != null) q.add(cur.right); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。