二叉树简介
树(tree)是一种抽象数据类型(ADT),用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限节点通过连接它们的边组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树、二叉排序树、二叉搜索树。
完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
**满二叉树:**除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。
树的常用语:
①、路径:顺着节点的边从一个节点走到另一个节点,所经过的节点的顺序排列就称为“路径”。
②、根:树顶端的节点称为根。一棵树只有一个根,如果要把一个节点和边的集合称为树,那么从根到其他任何一个节点都必须有且只有一条路径。A是根节点。
③、父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;B是D的父节点。
④、子节点:一个节点含有的子树的根节点称为该节点的子节点;D是B的子节点。
⑤、兄弟节点:具有相同父节点的节点互称为兄弟节点;比如上图的D和E就互称为兄弟节点。
⑥、叶节点:没有子节点的节点称为叶节点,也叫叶子节点,比如上图的H、E、F、G都是叶子节点。
⑦、子树:每个节点都可以作为子树的根,它和它所有的子节点、子节点的子节点等都包含在子树中。
⑧、节点的层次:从根开始定义,根为第一层,根的子节点为第二层,以此类推。
⑨、深度:对于任意节点n,n的深度为从根到n的唯一路径长,根的深度为0;
⑩、高度:对于任意节点n,n的高度为从n到一片树叶的最长路径长,所有树叶的高度为0;
二叉树特点总结:
(1)树执行查找、删除、插入的时间复杂度都是O(logN)
(2)遍历二叉树的方法包括前序、中序、后序
(3)非平衡树指的是根的左右两边的子节点的数量不一致
(4) 在非空二叉树中,第i层的结点总数不超过 , i>=1;
(5)深度为h的二叉树最多有个结点(h>=1),最少有h个结点;
(6)对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
二叉树代码实现
public class Node {
//左节点
private Node leftNode;
//右节点
private Node rightNode;
//数据
private int value;
//因为二叉树中节点删除操作过于繁琐,故加一属性进行简单标识
private boolean isDelete;
public Node getLeftNode() {
return leftNode;
}
public void setLeftNode(Node leftNode) {
this.leftNode = leftNode;
}
public Node getRightNode() {
return rightNode;
}
public void setRightNode(Node rightNode) {
this.rightNode = rightNode;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isDelete() {
return isDelete;
}
public void setDelete(boolean isDelete) {
this.isDelete = isDelete;
}
public Node(Node leftNode, Node rightNode, int value, boolean isDelete) {
super();
this.leftNode = leftNode;
this.rightNode = rightNode;
this.value = value;
this.isDelete = isDelete;
}
public Node() {
super();
}
public Node(int value) {
super();
this.value = value;
this.isDelete=false;
}
@Override
public String toString() {
return "Node [leftNode=" + leftNode + ", rightNode=" + rightNode + ", value=" + value + ", isDelete=" + isDelete
+ "]";
}
}
public class BinaryTree {
//根节点
private Node root;
public Node getRoot() {
return root;
}
/*
* 插入
*/
public void insert(int value){
Node node=new Node(value);
//判断是否存在根节点
if(root==null){
root=node;
root.setLeftNode(null);
root.setRightNode(null);
}else{
Node currentNode=root;
Node parentNode;
while(true){
parentNode=currentNode;
//往右放
if(node.getValue()>currentNode.getValue()){
currentNode=currentNode.getRightNode();
//判断是否还有右节点
if(currentNode==null){
//找到位置,放入
parentNode.setRightNode(node);
return;
}
//往左放
}else{
currentNode=currentNode.getLeftNode();
//判断是否有左节点
if(currentNode==null){
//找到位置,放入
parentNode.setLeftNode(node);
return;
}
}
}
}
}
/*
* 查找
*/
public Node select(int key){
Node currentNode=root;
//判断是否有根节点
if(currentNode!=null){
//此时标记的节点的值与key不相等
while(currentNode.getValue()!=key){
//左查找
if(currentNode.getValue()>key){
currentNode=currentNode.getLeftNode();
}else{
//右查找
currentNode=currentNode.getRightNode();
}
//判断是否查到最后
if(currentNode==null){
return null;
}
}
//退出while循环即为找出
//判断是否被删除
if(currentNode.isDelete()){
return null;
}else{
return currentNode;
}
}else{
//没有根节点直接返回null
return null;
}
}
/*
* 中序遍历
*/
public void inOrder(Node node){
if(node!=null&&node.isDelete()==false){
inOrder(node.getLeftNode());
System.out.println(node.getValue());
inOrder(node.getRightNode());
}
}
}
public static void main(String[] args) {
BinaryTree bt=new BinaryTree();
//插入测试
bt.insert(100);
bt.insert(55);
bt.insert(65);
bt.insert(81);
bt.insert(152);
bt.insert(162);
System.out.println("根节点:"+bt.getRoot().getValue());
//排序测试
bt.inOrder(bt.getRoot());
//查找测试
if(bt.select(60)!=null){
System.out.println("已找到60");
}else{
System.out.println("未找到60");
}
if(bt.select(65)!=null){
System.out.println("已找到65");
}else{
System.out.println("未找到65");
}
}
结果:
根节点:100
55
65
81
100
152
162
未找到60
已找到65