一、二叉搜索树Binary Search Tree
1、若左子树不为空,则左子树上所有节点的值均小于或等于它的根节点的值。
2、若右子树不为空,则右子树上所有节点的值均大于或等于它的根节点的值。
3、左、右子树也分别为二叉搜索树。
二、节点域设置
//根节点
private Entry<T> root;
//初始化
public BSTDemo(){
this.root=null;
}
//节点域
public class Entry<T extends Comparable<T>> {
private T data;//数据域
private Entry<T> left;//左孩子域
private Entry<T> right;//右孩子域
public Entry() {
this(null, null, null);
}
public Entry(T data,Entry<T> left,Entry<T> right){
this.data=data;
this.left=left;
this.right=right;
}
}
三、递归和非递归操作BST
1、插入
(1)递归插入
//插入
public void insert(T val){
this.root = insert(this.root, val);
}
private Entry<T> insert(Entry<T> root, T val) {
if(root == null){
return new Entry<T>(val, null, null);
}
if(root.data.compareTo(val) > 0){
root.left=insert(root.left, val);
} else if(root.data.compareTo(val) < 0){
root.right=insert(root.right, val);
}
return root;
}
(2)非递归插入
//插入
public void non_insert(T val){
if(this.root == null){
//直接生成根节点
this.root = new Entry<T>(val, null, null);
return;
}
Entry<T> parent = null;
Entry<T> cur = this.root;
while(cur != null){
parent = cur;
if(cur.data.compareTo(val) < 0){
cur = cur.right;
} else if(cur.data.compareTo(val) > 0){
cur = cur.left;
} else {
return;
}
}
if(parent.data.compareTo(val) < 0){
parent.right=new Entry<T>(val, null, null);
} else {
parent.left=new Entry<T>(val, null, null);
}
}
2、删除
(1)递归删除
public void delete(T data){
this.root = delete(this.root, data);
}
private Entry<T> delete(Entry<T> root, T val) {
if(root == null){
return null;
}
if(root.data.compareTo(val) > 0){
root.left=delete(root.left, val);
} else if(root.data.compareTo(val) < 0){
root.right=delete(root.right, val);
} else {
if(root.left!= null && root.right != null){
Entry<T> pre = root.left;
while(pre.right != null){
pre = pre.right;
}
root.data=pre.data;
// 递归继续删除前驱节点
root.left=delete(root.left, pre.data);
} else {
if(root.left != null){
return root.left;
} else if(root.right != null){
return root.right;
} else {
return null;
}
}
}
return root;
}
(2)非递归删除
//删除
public void non_delete(T val){
if(this.root==null){
System.out.println("该树不存在,无法进行删除。");
return;
}
Entry<T> parent = null; //记录根和跟的父节点
Entry<T> cur = this.root;
while(cur != null){
if(cur.data.compareTo(val) > 0){
parent = cur;
cur = cur.left;
} else if(cur.data.compareTo(val) < 0){
parent = cur;
cur = cur.right;
} else {
break;
}
}
if(cur == null){//没找到
System.out.println("树中不存在"+val+",删除失败。");
return;
}
//待删除节点有两个孩子
if(cur.left!= null && cur.right != null){
Entry<T> old = cur;//记录当前cur的位置
parent = cur;
cur = cur.left;//找前驱
while(cur.right != null){//找左子树中最大的,往右走
parent = cur;
cur = cur.right;
}
old.data=cur.data;
}
//待删节点有一个孩子或者没有孩子
Entry<T> child = cur.left;
if(child == null){
child = cur.right;//记录孩子位置,非左即右
}
if(parent == null){ //删除的是根节点
this.root = child;
} else {
if(cur == parent.left){ //把cur的child写入父节点的左孩子域
parent.left=child;
} else {
parent.right=child;
}
}
}
3、查询
(1)递归查询
//查询
public void search(T val){
search(this.root, val);
}
private Entry<T> search(Entry<T> root,T val) {
if (this.root == null) {
return null;
}
while (root != null) {
if (root.data.compareTo(val) < 0) {
return search(root.right, val);
} else if (root.data.compareTo(val) > 0) {
return search(root.left, val);
} else{
System.out.println("树中存在"+val+",查询成功。");
return root;
}
}
//没找到
System.out.println("树中不存在"+val+",查询失败。");
return null;
}
(2)非递归查询
//查询
public boolean non_search(T val){
if(this.root==null){
System.out.println("该树不存在,无法进行查询。");
return false;
}
Entry<T> cur=this.root;
while(cur!=null){
if(cur.data.compareTo(val)>0){
//插入元素比当前节点小,往左
cur=cur.left;
}else if(cur.data.compareTo(val)<0){
cur=cur.right;
}else {
System.out.println("树中存在"+ val +",查询成功。");
return true;
}
}
System.out.println("树中不存在"+ val +",查询失败。");
return false;
}
4、遍历
(1)递归遍历
①前序遍历
//前序遍历:中 左 右
public void prePrint() {
System.out.println("前序遍历:");
preOrder(this.root);
System.out.println();
}
private void preOrder(Entry<T> root) {
if (root == null) {
return;
}
System.out.print(root.data + " ");
preOrder(root.left);
preOrder(root.right);
}
②中序遍历
//中序遍历:左 中 右
public void inOrder() {
System.out.println("中序遍历:");
inOrder(this.root);
System.out.println();
}
private void inOrder(Entry<T> root) {
if (root == null) {
return;
}
inOrder(root.left);
System.out.print(root.data + " ");
inOrder(root.right);
}
③后序遍历
//后序遍历:左 右 中
public void postOrder(){
System.out.println("后序遍历:");
postOrder(this.root);
System.out.println();
}
private void postOrder(Entry<T> root) {
if (root == null) {
return;
}
postOrder(root.left);
postOrder(root.right);
System.out.print(root.data + " ");
}
④层序遍历
//层序遍历
//统计层数
public int level(){
return level(this.root);
}
private int level(Entry<T> root){
if(root==null){
return 0;
}else{
int left=level(root.left);
int right=level(root.right);
return right>left?(right+1):(left+1);
}
}
//开始遍历
public void levelOrder(){
System.out.println("层序遍历");
int level=level();
for(int i=0;i<level;i++){
levelOrder(this.root,i);
}
}
private void levelOrder(Entry<T> root,int i){
if(root==null){
return;
}
if(i==0){
System.out.print(root.data+" ");
return;
}
levelOrder(root.left,i-1);
levelOrder(root.right,i-1);
}
(2)非递归遍历
①前序遍历
//前序遍历:中 左 右
public void non_preOrder() {
System.out.println();
System.out.println("前序遍历:");
Stack<Entry> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
Entry<T> cur = stack.pop();
System.out.print(cur.data+" ");
if (cur.right != null) {//后进先出,因此先放右
stack.push(cur.right);
}
if (cur.left != null) {
stack.push(cur.left);
}
}
}
②中序遍历
//中序遍历:左 中 右
public void non_inOrder(){
System.out.println();
System.out.println("中序遍历:");
Entry<T> cur=this.root;
Stack<Entry> stack = new Stack<>();
if (cur != null) {
while (!stack.isEmpty()|| cur!=null) {
if (cur != null) {
stack.push(cur);
cur = cur.left;//一直向左走,走到左边全完了然后出栈
} else {
cur = stack.pop();
System.out.print(cur.data + " ");
cur = cur.right;
}
}
}
}
③后序遍历
//后序遍历:左 右 中
public void non_postOrder(){
System.out.println();
System.out.println("后序遍历:");
Entry<T> cur=this.root;
Stack<Entry> s1 = new Stack<>();
Stack<Entry> s2 = new Stack<>();
if (cur != null) {
s1.push(cur);
while (!s1.isEmpty()) {
cur = s1.pop();
s2.push(cur);
if (cur.left != null) {
s1.push(cur.left);
}
if (cur.right != null) {
s1.push(cur.right);
}
}
while (!s2.isEmpty()) {
System.out.print(s2.pop().data + " ");
}
}
}
④层序遍历
public void non_levelOrder(){
System.out.println();
System.out.println("层序遍历:");
LinkedList<Entry> linkedList=new LinkedList<>();
linkedList.add(this.root);
while(!linkedList.isEmpty()){
Entry<T> cur=linkedList.remove();
System.out.print(cur.data+" ");
if(cur.left!=null){
linkedList.add(cur.left);
}
if(cur.right!=null){
linkedList.add(cur.right);
}
}
}