二叉查找树主要的特点:当前节点左边的所有节点要小于该节点,右边的要大于该节点。(不能只判断当前节点的左儿子和右儿子是否小于或大于当前节点)
下面是对二叉查找树的各种操作列表
1. 插入(递归、非递归)
2. 删除
3. 查找最小值、最大值
4. 先序遍历(递归,非递归)
5. 中序遍历(递归,非递归)
6. 后序遍历(递归,非递归)
7. 层次遍历
8. 检查二叉树是否二叉查找树(时间复杂度O(nlogn)和O(n))
节点类代码:
import java.util.Queue;
import java.util.Stack;
import java.util.concurrent.LinkedBlockingDeque;
/**
*
* @author fx50jk
* @param <T>
*/
class BinaryTree<Key extends Comparable<Key>, T> {
TreeNode root;
public class TreeNode {
public TreeNode leftchild;
public TreeNode rightchild;
public Key key;
public T data;
public boolean visited = false;
public TreeNode() {
}
public TreeNode(Key key, T data) {
this.key = key;
this.data = data;
}
public TreeNode(T data, TreeNode leftchild, TreeNode rightchild) {
this.leftchild = leftchild;
this.rightchild = rightchild;
this.data = data;
}
}
public BinaryTree(TreeNode root) {
this.root = root;
}
public BinaryTree() {
}
public void insert1(Key key) {
if (key == null) {
System.out.println("???");
} else {
root = insert1(root, key);
}
}
private TreeNode insert1(TreeNode rootNode, Key key) {
if (rootNode == null) {
rootNode = new TreeNode();
rootNode.key = key;
}
//插入左子树还是右子树
int comRes = key.compareTo(rootNode.key);
if (comRes < 0) {
rootNode.leftchild = insert1(rootNode.leftchild, key);
} else if (comRes > 0) {
rootNode.rightchild = insert1(rootNode.rightchild, key);
} else {
//已经有该数据
System.out.println("键值重复");
}
return rootNode;
}
public void insert(Key key, T value) {
if (root == null) {
root = new TreeNode(key, value);
return;
}
TreeNode currentNode = root;
TreeNode parentNode = root;
boolean isLeftChild = true;
while (currentNode != null) {
parentNode = currentNode;//保存父节点的信息
//判断它是左节点还是右节点
int comRes = key.compareTo(currentNode.key);
if (comRes < 0) {
currentNode = currentNode.leftchild;
isLeftChild = true;
} else {
currentNode = currentNode.rightchild;
isLeftChild = false;
}
}
TreeNode newNode = new TreeNode(key, value);
if (isLeftChild) {
parentNode.leftchild = newNode;
} else {
parentNode.rightchild = newNode;
}
}
//根据key删除节点
public void remove(Key key){
root=remove(root,key);
}
private TreeNode remove(TreeNode rootNode,Key key){
if (rootNode==null) {
return rootNode;
}
int comRes=key.compareTo(rootNode.key);
if (comRes<0) {
rootNode.leftchild=remove(rootNode.leftchild, key);
}else if(comRes>0){
rootNode.rightchild=remove(rootNode.rightchild, key);
}else if(rootNode.leftchild!=null&&rootNode.rightchild!=null){//已找到该节点,开始进行删除
rootNode.key=findMin(rootNode.rightchild).key;
rootNode.rightchild=remove(rootNode.rightchild, key);
}else{
rootNode=(rootNode.leftchild!=null)?rootNode.leftchild:rootNode.rightchild;
}
return rootNode;
}
//查找最小值
public Key findMin(){
if (root==null) {
return null;
}
return findMin(root).key;
}
private TreeNode findMin(TreeNode rootNode){
if (rootNode==null) {
return null;
}else if(rootNode.leftchild==null){//从左子树中找最左的节点
return rootNode;
}else{
return findMin(rootNode.leftchild);
}
}
//查找最大值
public Key findMax(){
if (root==null) {
return null;
}
return findMax(root).key;
}
private TreeNode findMax(TreeNode rootNode){
if (rootNode==null) {
return null;
}else if(rootNode.rightchild==null){//从右子树中找最右的节点
return rootNode;
}else{
return findMin(rootNode.rightchild);
}
}
//遍历的递归实现
//先序遍历
public void preOrder() {
preOrder(root);
System.out.println("");
}
private void preOrder(TreeNode treeNode) {
if (treeNode != null) {
System.out.print(treeNode.key + "\t");
preOrder(treeNode.leftchild);
preOrder(treeNode.rightchild);
}
}
//中序遍历
public void midOrder() {
midOrder(root);
System.out.println("");
}
private void midOrder(TreeNode treeNode) {
if (treeNode != null) {
midOrder(treeNode.leftchild);
System.out.print(treeNode.key + "\t");
midOrder(treeNode.rightchild);
}
}
//后序遍历
public void postOrder() {
postOrder(root);
}
private void postOrder(TreeNode treeNode) {
if (treeNode != null) {
postOrder(treeNode.leftchild);
postOrder(treeNode.rightchild);
System.out.print(treeNode.key + "\t");
}
}
//遍历的非递归实现
public void preOrderTraverse() {
Stack<TreeNode> stack = new Stack<>();
TreeNode rootNode = root;
if (rootNode != null) {
stack.push(rootNode);
while (!stack.isEmpty()) {
rootNode = stack.pop();
System.out.print(rootNode.key + "\t");
if (rootNode.rightchild != null) {
stack.push(rootNode.rightchild);
}
if (rootNode.leftchild != null) {
stack.push(rootNode.leftchild);
}
}
}
System.out.println("");
}
public void inOrderTraverse() {
Stack<TreeNode> stack = new Stack<>();
TreeNode rootNode = root;
while (rootNode != null) {
while (rootNode != null) {
if (rootNode.rightchild != null) {
stack.push(rootNode.rightchild);//先让右节点入栈
}
stack.push(rootNode);//让中间节点入栈
rootNode = rootNode.leftchild;
}
rootNode = stack.pop();
while (!stack.isEmpty() && rootNode.rightchild == null) {
System.out.print(rootNode.key + "\t");
rootNode = stack.pop();
}
System.out.print(rootNode.key + "\t");
if (!stack.empty()) {
rootNode = stack.pop();
} else {
rootNode = null;
}
}
System.out.println("");
}
public void postOrderTraverse() {
TreeNode rootNode = root;
TreeNode temp = root;
Stack<TreeNode> stack = new Stack<>();
while (rootNode != null) {
//左子树入栈
while (rootNode.leftchild != null) {
stack.push(rootNode);
rootNode = rootNode.leftchild;
}
// 当前结点无右子结点或右子结点已经输出
while (rootNode != null && (rootNode.rightchild == null || rootNode.rightchild == temp)) {
System.out.print(rootNode.key + "\t");
temp = rootNode;
if (stack.isEmpty()) {
return;
}
rootNode = stack.pop();
}
//处理右节点
stack.push(rootNode);
rootNode = rootNode.rightchild;
}
System.out.println("");
}
public void levelOrder() {
/**
* 存放需要遍历的结点,左结点一定优先右节点遍历
*/
Queue<TreeNode> queue = new LinkedBlockingDeque<>();
TreeNode rootNode = this.root;
while (rootNode != null) {
//记录经过的结点
System.out.print(rootNode.key + "\t");
//先按层次遍历结点,左结点一定在右结点之前访问
if (rootNode.leftchild != null) {
//孩子结点入队
queue.add(rootNode.leftchild);
}
if (rootNode.rightchild != null) {
queue.add(rootNode.rightchild);
}
//访问下一个结点
rootNode = queue.poll();
}
}
//检查二叉树是否是二叉查找树 时间复杂度为O(NlogN)
public boolean isBalanced(){
return isBalanced(root);
}
private boolean isBalanced(TreeNode rootNode){
if (rootNode==null) {
return true;
}
int heightDiff=getHeight(rootNode.leftchild)-getHeight(rootNode.rightchild);
if (Math.abs(heightDiff)>1) {
return false;
}else{
return isBalanced(rootNode.leftchild)&&isBalanced(rootNode.rightchild);
}
}
public int getHeight(TreeNode rootNode){
if(rootNode==null){
return 0;
}
return Math.max(getHeight(rootNode.leftchild), getHeight(rootNode.rightchild))+1;
}
//判断是否平衡 时间复杂度为O(n)
private int checkHeight(TreeNode rootNode){
if (rootNode==null) {
return 0;
}
//检查左子树是否平衡
int leftHeight=checkHeight(rootNode.leftchild);
if (leftHeight==-1) {
return -1;
}
//检查右子树
int rightHeight=checkHeight(rootNode.rightchild);
if (rightHeight==-1) {
return -1;
}
//检查当前节点是否平衡
int heightDiff=Math.abs(leftHeight-rightHeight);
if (heightDiff>1) {
return -1;
}else{
return Math.max(leftHeight,rightHeight)+1;
}
}
public boolean isBalanced1(){
return checkHeight(root) != -1;
}
/**
* @return the root
*/
public TreeNode getRoot() {
return root;
}
}
测试类代码 :
public class Test {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
BinaryTree binaryTree=new BinaryTree();
binaryTree.insert(1,2);
binaryTree.insert(3,4);
binaryTree.insert(7,6);
binaryTree.insert(4,8);
binaryTree.insert(5,9);
System.out.println(binaryTree.getRoot().key);
System.out.print("前序遍历(递归):"+"\t");
binaryTree.preOrder();
System.out.print("中序遍历(递归):"+"\t");
binaryTree.midOrder();
System.out.print("后序遍历(递归):"+"\t");
binaryTree.postOrder();
System.out.print("\n前序遍历(非递归):"+"\t");
binaryTree.preOrderTraverse();
System.out.print("中序遍历(非递归):"+"\t");
binaryTree.inOrderTraverse();
System.out.print("后序遍历(非递归):"+"\t");
binaryTree.postOrderTraverse();
System.out.print("\n层次遍历(非递归):"+"\t");
binaryTree.levelOrder();
}
}