二叉树
文章目录
1、什么是二叉树
二叉树是树的一种,每个节点最多可具有两个子树,即结点的度最大为 2(结点度:结点拥
有的子树数)。
2、二叉树种类
二叉查找树(binary search tree):
当前根节点的左边全部比根节点小,当前根节点的右边全部比根节点大。
斜树:
所有结点都只有左子树,或者右子树。
满二叉树
所有的分支节点都具有左右节点。
完全二叉树
若设二叉树的深度为 h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h
层所有的结点都连续集中在最左边,这就是完全二叉树。
3、二叉树的一些性质
二叉树第 i 层上的结点数目最多为 2^(i-1) (i≥1)
深度为 h 的二叉树至多有 2^h-1 个结点(h≥1)
包含 n 个结点的二叉树的高度至少为 log2 (n+1)
在任意一棵二叉树中,若终端结点的个数为 n0,度为 2 的结点数为 n2,则 n0=n2+1
4、二叉树的遍历
先序遍历
先访问根节点,再访问左节点,再访问右节点
中序遍历
先访问左节点,再访问根节点,再访问右节点
后序遍历
先访问左节点,再访问右节点,再访问根节点
提示:遍历方式是根据根节点的位置不同,而起名的。左右节点访问顺序不会改变
先序遍历(根-左-右):1-2-4-8-9-5-10-3-6-7
中序遍历:(左-根-右):8-4-9-2-10-5-1-6-3-7
后序遍历(左-右-根):8-9-4-10-5-2-6-7-3-1
5、代码实现
树的结构
public class TreeNode<T> {
private T data;
private TreeNode left;
private TreeNode right;
public TreeNode(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public TreeNode getLeft() {
return left;
}
public void setLeft(TreeNode left) {
this.left = left;
}
public TreeNode getRight() {
return right;
}
public void setRight(TreeNode right) {
this.right = right;
}
}
手动构建二叉树+遍历
public class TestMain {
public static void main(String[] args) {
TreeNode<String> root = new TreeNode<>("1");
TreeNode<String> node2 = new TreeNode<>("2");
TreeNode<String> node3 = new TreeNode<>("3");
TreeNode<String> node4 = new TreeNode<>("4");
TreeNode<String> node5 = new TreeNode<>("5");
TreeNode<String> node6 = new TreeNode<>("6");
TreeNode<String> node7 = new TreeNode<>("7");
// 手动构建二叉树
root.setLeft(node2);
node2.setLeft(node4);
node2.setRight(node5);
root.setRight(node3);
node3.setLeft(node6);
node3.setRight(node7);
System.out.println("广度遍历:");
printByLayer(root);
System.out.println("\n前序遍历:");
pre_print(root);
System.out.println("\n中序遍历:");
mid_print(root);
System.out.println("\n后序遍历:");
last_print(root);
}
/**
* 按广度遍历
* @param root
*/
public static void printByLayer(TreeNode root){
if (root == null) return;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
// 当队列不为空
while(!queue.isEmpty()){
TreeNode temp = queue.poll();
if (temp.getLeft()!=null){
// 进队列
queue.add(temp.getLeft());
} if (temp.getRight() != null){
// 进队列
queue.add(temp.getRight());
}
System.out.print(temp.getData()+"\t");
}
}
/**
* 前序遍历:根左右
* @param root
*/
public static void pre_print(TreeNode root) {
if (root != null) {
// 根
System.out.print(root.getData()+"\t");
// 左
pre_print(root.getLeft());
// 右
pre_print(root.getRight());
}
}
/**
* 中序遍历: 左根右
* @param root
*/
public static void mid_print(TreeNode root) {
if (root != null) {
// 左
mid_print(root.getLeft());
// 根
System.out.print(root.getData()+"\t");
// 右
mid_print(root.getRight());
}
}
/**
* 后序遍历: 左右根
* @param root
*/
public static void last_print(TreeNode root) {
if (root != null) {
// 左
last_print(root.getLeft());
// 右
last_print(root.getRight());
// 根
System.out.print(root.getData()+"\t");
}
}
}
运行结果
广度遍历:
1 2 3 4 5 6 7
前序遍历:
1 2 4 5 3 6 7
中序遍历:
4 2 5 1 6 3 7
后序遍历:
4 5 2 6 7 3 1
排序二叉树
/**
* 二叉排序树
*/
public class BinarySortTree<T> {
private TreeNode<T> root; // 根节点
public TreeNode<T> getRoot() {
return root;
}
public void setRoot(TreeNode<T> root) {
this.root = root;
}
/**
* 获取节点
* @param data
* @return
*/
public TreeNode get(T data){
if (this.root == null) return null;
TreeNode temp = root;
while (temp != null){
String currentData = String.valueOf(temp.getData());
String nodeData = String.valueOf(data);
if (currentData.compareTo(nodeData) > 0){
//根节点大 往左边走
temp = temp.getLeft();
} else if (currentData.compareTo(nodeData) < 0){
//根节点小 往右边走
temp = temp.getRight();
} else {
return temp;
}
}
return null;
}
/**
* 根据结点节点大小插入
* @param data treeNode节点
* @return
*/
public boolean add(TreeNode<T> data) {
if (root == null) {
this.root = data;
return true;
} else {
TreeNode<T> current = root;
TreeNode<T> parentNode = null;
while(current != null) {
parentNode = current;
String currentData = (String)parentNode.getData();
String nodeData = (String)data.getData();
//转换成字符串比较
if (currentData.compareTo(nodeData) > 0) {
// 根节点大
if (parentNode.getLeft() == null){
// 插入左子树
parentNode.setLeft(data);
return true;
}
// 继续看左子树
current = parentNode.getLeft();
} else {
// 根节点小
if (parentNode.getRight() == null){
// 插入右子树
parentNode.setRight(data);
return true;
}
// 继续看右子树
current = parentNode.getRight();
}
}
}
return false;
}
}
test
public class TestMain {
public static void main(String[] args) {
TreeNode<String> root = new TreeNode<>("a14");
TreeNode<String> node2 = new TreeNode<>("b25");
TreeNode<String> node3 = new TreeNode<>("c10");
TreeNode<String> node4 = new TreeNode<>("d18");
TreeNode<String> node5 = new TreeNode<>("d13");
//排序二叉树
BinarySortTree<String> btree = new BinarySortTree<String>();
btree.add(root);
btree.add(node2);
btree.add(node3);
btree.add(node4);
btree.add(node5);
System.out.println("\n中序遍历:");
mid_print(btree.getRoot());
TreeNode d13 = btree.get("d13");
System.out.println("\n" + d13.getData());
}
/**
* 中序遍历: 左根右
* @param root
*/
public static void mid_print(TreeNode root) {
if (root != null) {
// 左
mid_print(root.getLeft());
// 根
System.out.print(root.getData()+"\t");
// 右
mid_print(root.getRight());
}
}
}
运行结果
中序遍历:
a14 b25 c10 d13 d18
d13