1.概念
(01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值; (02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值; (03) 任意节点的左、右子树也分别为二叉查找树。 (04) 没有键值相等的节点(no duplicate nodes)
2.特点
中序遍历可以从小到大排列
3.操作
添加
查找
删除
4.实现
/**
* (01) 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
* (02) 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
* (03) 任意节点的左、右子树也分别为二叉查找树。
* (04) 没有键值相等的节点(no duplicate nodes)
* @author Administrator
*/
public class 二叉搜索树 {
private Node root;
/**
* 添加
* @param data
*/
public void insert(int data){
Node newNode = new Node(data);
if (root == null){
//如果是第一个节点,也就是根节点为null,直接创建一个新的节点即可
root = newNode;
}else {
Node current = root;
//current的父结点
Node parent;
//循环查找插入的位置
while (true){
parent = current;
//如果插入的值小于当前结点的值,从左孩子树查找
if (data < current.val){
current = current.leftChild;
//直到当前结点为null
if (current == null){
//设置当前结点的父结点为新创建的结点
parent.leftChild = newNode;
return;
}
//如果插入的值大于当前结点的值,从左子树查找
}else {
current = current.rightChild;
//直到当前结点为null
if (current == null){
//设置当前结点的父结点为新创建的结点
parent.rightChild = newNode;
return;
}
}
}
}
}
/**
* 查询操作
* @param value
* @return
*/
public Node find(int value){
Node current = root;
while (current.val != value){
if (value<current.val){
current = current.leftChild;
}else {
current = current.rightChild;
}
if (current == null){
return null;
}
}
return current;
}
public static void main(String[] args) {
二叉搜索树 test = new 二叉搜索树();
test.insert(50);
test.insert(25);
test.insert(75);
test.insert(15);
test.insert(35);
test.insert(65);
test.insert(85);
// test.insert(10);
// test.insert(20);
test.insert(30);
// test.insert(40);
// test.insert(60);
// test.insert(70);
// test.insert(80);test.insert(90);
// test.insert(18);
// test.insert(22);
// test.insert(38);
test.inOrder(test.root);
test.printTree(test.root);
boolean delete = test.delete(50);
System.out.println(delete);
test.inOrder(test.root);
test.printTree(test.root);
}
/**
* 删除操作
* @param value
* @return
*/
public boolean delete(int value) {
//删除的父结点
Node parent = null;
//删除的结点
Node current = root;
//删除的结点是左结点
boolean isLeft = false;
//删除的结点是右结点
boolean isRight = false;
//查找要删除的结点是左子结点还是右子结点
while (current.val != value){
parent = current;
isLeft = false;
isRight = false;
if (value<current.val){
current = current.leftChild;
isLeft = true;
}else {
current = current.rightChild;
isRight = true;
}
//不存在该值
if(current == null) {
return false;
}
}
if (parent == null){
System.out.println("parent " + "null" + " 删除的父结点");
System.out.println("current " + current.val+" 删除结点就是跟结点");
}else {
System.out.println("parent " + parent.val + " 删除的父结点");
System.out.println("current " + current.val+" 删除结点");
System.out.println("isLeft "+isLeft+" isRight "+isRight);
}
//是叶子结点,不存在子结点
if (current.leftChild == null && current.rightChild==null){
// 删除结点是左结点
if (isLeft){
//删除父结点的左子
parent.leftChild = null;
System.out.print("删除结点是左叶子结点");
}
//删除结点是右结点
else if (isRight){
parent.rightChild = null;
System.out.print("删除结点是右叶子结点");
}
//删除结点是跟结点
else {
root = null;
System.out.print("删除结点是跟结点");
}
System.out.println(",不存在子结点");
return true;
}
//存在左子结点
else if (current.leftChild !=null && current.rightChild==null){
System.out.println("不是叶子结点");
// 删除结点是左结点
if (isLeft){
parent.leftChild = current.leftChild;
System.out.print("删除结点是左结点");
}
// 删除结点是右结点
else if (isRight) {
parent.rightChild = current.leftChild;
System.out.print("删除结点是右结点");
}
//删除结点是跟结点
else {
root = current.leftChild;
System.out.print("删除结点是跟结点");
}
current = null;
System.out.println(",存在左子结点");
return true;
}
//存在右子结点
else if (current.rightChild !=null && current.leftChild==null){
System.out.println("不是叶子结点");
// 删除结点是左结点
if (isLeft){
parent.leftChild = current.rightChild;
System.out.print("删除结点是左结点");
}
// 删除结点是右结点
else if (isRight) {
parent.rightChild = current.rightChild;
System.out.print("删除结点是右结点");
}
//删除结点是根结点
else {
root = current.rightChild;
System.out.print("删除结点是根结点");
}
current = null;
System.out.println(",存在右子结点");
return true;
}
//左右子结点都存在
else {
System.out.println("不是叶子结点");
//指针
Node currentLeft = current.rightChild;
//获得删除右子树中最小结点
Node parentMin = currentLeft;
while (currentLeft !=null){
parentMin = currentLeft;
currentLeft = currentLeft.leftChild;
}
// 删除结点是左结点
if (isLeft){
//删除结点的父结点的左指针指向,删除结点的右子树
parent.leftChild = current.rightChild;
System.out.print("删除结点是左叶子结点");
}
//删除结点是右结点
else if (isRight){
//删除结点的父结点的右指针指向,删除结点的右子树
parent.rightChild = current.rightChild;
System.out.print("删除结点是右叶子结点");
}
//删除结点是根结点
else {
//根结点的右指针指向,删除结点的右子树
root = current.rightChild;
System.out.print("删除结点是根结点");
}
//删除右子树中最小结点指针指向,删除结点的左子树
parentMin.leftChild = current.leftChild;
current = null;
System.out.println(",存在左、右子结点");
return true;
}
}
/**
* 中序遍历,由小到大
* @param localNode
*/
public void inOrder(Node localNode) {
if(localNode != null) {
inOrder(localNode.leftChild);
System.out.print(localNode.val+" ");
inOrder(localNode.rightChild);
}
}
public void printTree(Node head) {
System.out.println("-----------------\r\nBinary Tree:");
printInOrder(head, 0, "Root-", 8);
System.out.println();
}
public void printInOrder(Node head, int height, String to, int len) {
if (head == null) {
return;
}
printInOrder(head.rightChild, height + 1, "R-", len);
String val = to + head.val;
int lenM = val.length();
int lenL = (len - lenM) / 2;
int lenR = len - lenM - lenL;
val = getSpace(lenL) + val;// + getSpace(lenR);
System.out.println(getSpace(height * len) + val);
printInOrder(head.leftChild, height + 1, "L-", len);
}
public String getSpace(int num) {
String space = " ";
StringBuffer buf = new StringBuffer("");
for (int i = 0; i < num; i++) {
buf.append(space);
}
return buf.toString();
}
}
class Node{
/**
* 结点值
*/
int val;
/**
* 左孩子结点引用
*/
Node leftChild;
/**
* 右孩子结点引用
*/
Node rightChild;
public Node(int val) {
this.val = val;
}
public void printNode(){
System.out.println(val);
}
}