二叉树入门
Posted BLACK CAT JAVA
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树入门相关的知识,希望对你有一定的参考价值。
二叉树入门
1.1 基本概念
二叉树:二叉树就是度不超过2的树(每个节点最多两个子节点)
满二叉树:一个二叉树,如果每一层的节点都达到最大值,则这个二叉树就叫满二叉树(2^n-1)
完全二叉树:叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树,即如果树不满则要求左满右不满,是为完全二叉树
1.2 二叉查找树的创建
1.2.1 二叉树的属性
节点类
class Node {
//存储key
private Key key;
//存储value
private Value value;
//左子节点
private Node left;
//右子节点
private Node right;
public Node(Key key, Value value, Node left, Node right) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
}
二叉树的属性
public class BinaryTree<< span="">Key extends Comparable<< span="">Key>, Value> {
//元素个数
private int size;
//根节点
private Node root;
}
1.2.2 插入
public void put(K key,V value) 向树中插入一个键值对
private Node put(Node,K key,V value) 向树中指定结点处插入键值对
//向树中插入一个键值对
public void put(Key key, Value value) {
root = put(root, key, value);
}
//给指定树x上,添加键一个键值对,并返回添加后的新树
private Node put(Node node, Key key, Value value) {
//如果当前树中没有任何一个结点,则直接返回新结点
if (node == null) {
//节点数+1
size++;
return new Node(key, value, null, null);
}
int cmp = key.compareTo(node.key);
if (cmp > 0) {
//如果新结点的key大于当前结点的key,则继续找当前结点的右子结点
node.right = put(node.right, key, value);
} else if (cmp < 0) {
//如果新结点的key小于当前结点的key,则继续找当前结点的左子结点
node.left = put(node.left, key, value);
} else {
//如果新结点的key等于当前结点的key,则树中已经存在这样的结点,替换该结点的value值即可
node.value = value;
}
return node;
}
1.2.3 获取
public Value get(Key key) //根据key,从树中找出对应的值
private Value get(Node node, Key key //从指定的树x中,找出key对应的值
//根据key,从树中找出对应的值
public Value get(Key key) {
return get(root, key);
}
//从指定的树x中,找出key对应的值
private Value get(Node node, Key key) {
if (node == null) {
return null;
}
int cmp = key.compareTo(node.key);
if (cmp > 0) {
//如果新结点的key大于当前结点的key,则继续找当前结点的右子结点
return get(node.right, key);
} else if (cmp < 0) {
//如果新结点的key小于当前结点的key,则继续找当前结点的左子结点
return get(node.left, key);
} else {
//如果新结点的key等于当前结点的key,则直接返回
return node.value;
}
}
1.2.4 删除
public void delete(K key) 根据key删除键值对
private Node delete(Node x,K key) 根据key删除树中指定结点处的键值对
//根据key,删除树中对应的键值对
public void delete(Key key) {
root = delete(root, key);
}
//删除指定树x上的键为key的键值对,并返回删除后的新树
private Node delete(Node node, Key key) {
if (node == null) {
return null;
}
//找到被删除结点
int cmp = key.compareTo(node.key);
if (cmp > 0) {
//新结点的key大于当前结点的key,继续找当前结点的右子结点
node.right = delete(node.right, key);
} else if (cmp < 0) {
//新结点的key大于当前结点的key,继续找当前结点的左子结点
node.left = delete(node.left, key);
} else {
//1.如果当前结点的右子树不存在,则直接返回当前结点的左子结点
if (node.right == null) {
return node.left;
}
//2.如果当前结点的左子树不存在,则直接返回当前结点的右子结点
if (node.left == null) {
return node.right;
}
//3.当前结点的左右子树都存在
//3.1找到右子树中最小的结点
Node minNode = node.right;
while (minNode.left != null) {
minNode = minNode.left;
}
//3.2删除右子树中最小的结点
Node delNode = node.right;
while (delNode.left != null) {
if (delNode.left.left == null) {
delNode.left = null;
break;
}
delNode = delNode.left;
}
//3.3.让被删除结点的左子树称为最小结点minNode的左子树,
//让被删除结点的右子树称为最小结点minNode的右子树
minNode.left = node.left;
minNode.right = node.right;
//3.4.让被删除结点的父节点指向最小结点minNode
node = minNode;
//4.个数减1
size--;
}
return node;
}
1.2.5 获取size
public int size() 获取树中元素个数
public int size() {
return size;
}
1.2.6 查找二叉树中最小的键
//找出整个树中最小的键
public Key min() {
return min(root).key;
}
//找出指定树x中最小的键所在的结点
private Node min(Node x) {
if (x.left != null) {
return min(x.left);
} else {
return x;
}
}
1.2.7查找二叉树中最大的键
//找出整个树中最大的键
public Key max() {
return max(root).key;
}
//找出指定树x中最大的键所在的结点
private Node max(Node x) {
if (x.right != null) {
return max(x.right);
} else {
return x;
}
}
1.3 二叉树的基础遍历
1.3.1 前序遍历
二叉树前序遍历: 先遍历根结点,再遍历左子树,最后遍历右子树
//前序遍历
public Queue<< span="">Key> pre() {
Queue<< span="">Key> keys = new LinkedList<>();
pre(root, keys);
return keys;
}
private void pre(Node node, Queue<< span="">Key> keys) {
if (node == null) {
return;
}
keys.add(node.key);
if (node.left != null) {
pre(node.left, keys);
}
if (node.right != null) {
pre(node.right, keys);
}
}
1.3.2 中序遍历
二叉树中序遍历: 先遍历左子树,再遍历根结点,最后遍历右子树
//中序遍历
public Queue<< span="">Key> mid() {
Queue<< span="">Key> keys = new LinkedList<>();
mid(root, keys);
return keys;
}
private void mid(Node node, Queue<< span="">Key> keys) {
if (node == null) {
return;
}
if (node.left != null) {
mid(node.left, keys);
}
keys.add(node.key);
if (node.right != null) {
mid(node.right, keys);
}
}
1.3.3 后序遍历
二叉树后序遍历: 先遍历左子树,再遍历右子树,最后遍历根结点
//后序遍历
public Queue<< span="">Key> after() {
Queue<< span="">Key> keys = new LinkedList<>();
after(root, keys);
return keys;
}
private void after(Node node, Queue<< span="">Key> keys) {
if (node == null) {
return;
}
if (node.left != null) {
after(node.left, keys);
}
if (node.right != null) {
after(node.right, keys);
}
keys.add(node.key);
}
1.4 二叉树的层序遍历
//层序遍历
//1.创建队列,存储每一层的结点;
//2.使用循环从队列中弹出一个结点:
// 2.1获取当前结点的key;
// 2.2如果当前结点的左子结点不为空,则把左子结点放入到队列中
// 2.3如果当前结点的右子结点不为空,则把右子结点放入到队列中
public Queue<< span="">Key> layer() {
Queue<< span="">Key> keys = new LinkedList<>();
Queue<< span="">Node> nodes = new LinkedList();
nodes.offer(root);
while (!nodes.isEmpty()) {
Node node = nodes.poll();
keys.add(node.key);
if (node.right != null) {
nodes.offer(node.right);
}
if (node.left != null) {
nodes.offer(node.left);
}
}
return keys;
}
1.5 二叉树的最大深度问题
//最大深度
public int maxDepth() {
return maxDepth(root);
}
//1.如果根结点为空,则最大深度为0;
//2.计算左子树的最大深度;
//3.计算右子树的最大深度;
//4.当前树的最大深度=左子树的最大深度和右子树的最大深度中的较大者+1
private int maxDepth(Node node) {
if (node == null) {
return 0;
}
int leftDepth = 0;
if (node.left != null) {
leftDepth = maxDepth(node.left);
}
int rightDepth = 0;
if (node.right != null) {
rightDepth = maxDepth(node.right);
}
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
以上是关于二叉树入门的主要内容,如果未能解决你的问题,请参考以下文章