1、树的整体介绍
2、二叉搜索树
1)定义一个二叉搜索树
//自定义一棵二叉搜索树,这棵树里面的内容是可以比较的泛型
public class BST <E extends Comparable<E>> {
//1、定义一个节点
private class Node{
E e;
Node left;
Node right;
//写一个构造函数,构造一个节点
public Node(E e) {
this.e = e;
this.left = null;
this.right = null;
}
}
//2.定义二叉搜索树的属性
private Node root;
private int size;
//3.提供一个获取二叉树长度的方法
public int size() {
return size;
}
}
2)向BST里面添加元素
//自定义一棵二叉搜索树,这棵树里面的内容是可以比较的泛型
public class BST <E extends Comparable<E>> {
//1、定义一个节点
private class Node{
E e;
Node left;
Node right;
//写一个构造函数,构造一个节点
public Node(E e) {
this.e = e;
this.left = null;
this.right = null;
}
}
//2.定义二叉搜索树的属性
private Node root;
private int size;
//3.提供一个获取二叉树长度的方法
public int size() {
return size;
}
//4.写一个添加节点的方法
public void addEle(E e) {
if(root==null) {
root = new Node(e);
}else {
addEle(root,e);
}
}
/**
* 将元素E添加到以node为根节点的树上
* @param node
* @param e
*/
private void addEle(Node node , E e) {
if(node.left==null && e.compareTo(node.e)<0) {
node.left = new Node(e);
size++;
return;
}
if(node.right==null && e.compareTo(node.e)>0) {
node.right = new Node(e);
size++;
return;
}
if(e.compareTo(node.e)<0) {
addEle(node.left,e);
}
if (e.compareTo(node.e)>0) {
addEle(node.right,e);
}
}
}
public class BSTTest {
public static void main(String[] args) {
BST bst = new BST();
bst.addEle(7);
bst.addEle(3);
bst.addEle(10);
}
}
上述方法的升级版
//4.写一个添加节点的方法
public void addEle(E e) {
root = addEle(root, e);
}
/**
* 将元素E添加到以node为根节点的树上
* return 返回的就是新插入节点后新子树的根节点
* @param node
* @param e
*/
private Node addEle(Node node , E e) {
if(node == null) {
size++;
return new Node(e);
}
if(e.compareTo(node.e)<0) {
node.left = addEle(node, e);
}
if(e.compareTo(node.e)>0) {
node.right = addEle(node, e);
}
return node;
}
3)查找一个值所在二叉树中的节点
public Node search(E e){
return search(root,e);
}
/**
* 在以node为根的树上去查找元素e所在的节点
* @param node
* @param e
* @return
*/
private Node search(Node node, E e) {
if(node==null){
return null;
}
if(e.compareTo(node.e)==0){
return node;
}else if(e.compareTo(node.e)<0){
return search(node.left,e);
}else{
return search(node.right,e);
}
}
4) 查找某个元素所在节点的父节点是谁
public Node searchParent(E e){
return searchParent(root,e);
}
/**
* 从以node为根的树中查找元素e所在节点的父节点
* @param node
* @param e
* @return
*/
private Node searchParent(Node node, E e) {
//递归的退出条件
if(node==null){
return null;
}
if((node!=null && e.compareTo(node.left.e)<0) || (node!=null && e.compareTo(node.right.e)>0)){
return node;
} else {
if (node.left != null && e.compareTo(node.e) < 0) {
return searchParent(node.left, e);
} else if (node.right != null && e.compareTo(node.e) > 0) {
return searchParent(node.right, e);
}else{
return null;
}
}
}
5) 二叉收索树深度优先遍历
public void preOrder(){
preOrder(root);
}
/**
* 从根节点开始前序遍历
* @param node
*/
private void preOrder(Node node) {
if(node == null){
return;
}
System.out.println(node.e);
preOrder(node.left);
preOrder(node.right);
}
public void midOrder(){
midOrder(root);
}
/**
* 中序遍历
* @param node
*/
private void midOrder(Node node) {
if(node == null){
return;
}
preOrder(node.left);
System.out.println(node.e);
preOrder(node.right);
}
public void lastOrder(){
midOrder(root);
}
/**
* 后序遍历
* @param node
*/
private void lastOrder(Node node) {
if(node == null){
return;
}
preOrder(node.left);
preOrder(node.right);
System.out.println(node.e);
}
6)二叉收索树非递归前序遍历,中序遍历,后序遍历
/**
* 非递归的前序遍历
*/
public void preOrderNR(){
if(root==null){
return;
}
Stack <Node> stack = new Stack();
stack.push(root);
while(!stack.isEmpty()){
Node current = stack.pop();
System.out.println(current.e);
if(current.right!=null){
stack.push(current.right);
}
if(current.left!=null){
stack.push(current.left);
}
}
}
7)二叉搜索树的广度优先遍历
/**
* 二叉树的广度遍历
*/
public void widthSearch(){
if(root == null){
return;
}
Queue <Node> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
Node current = queue.remove();
System.out.println(current.e);
if(current.left!=null){
queue.add(current.left);
}
if(current.right!=null){
queue.add(current.right);
}
}
}
8)二叉搜索树的删除
/**
* 删除节点:有三种情况
*/
public void delNode(E e){
if(root == null) return;
Node target = search(e);
if (target == null) return;
Node parent = searchParent(e);
if(target.right==null && target.left==null){
//这种情况说明是叶子节点,直接删除就好
if(parent.left!=null && e.compareTo(parent.left.e)==0){
parent.left = null;
size--;
}else if(parent.right!=null && e.compareTo(parent.right.e)==0){
parent.right = null;
size--;
}
}else if(target.right!=null && target.left!=null){
//这种说明是有两个子树
//找出目标节点右边节点的最小值,这里的意思就是说在目标结点的右子树上去找min,右子树的min肯定在子树的左边。
Node minNode = minNode(target.right);
delNode(minNode.e);
//此处通过赋值的方式来达到节点交换的目的
target.e = minNode.e;
}else{
//只有一个子树
//只有左子树
if(target.left!=null){
if(e.compareTo(parent.left.e)==0){
parent.left = target.left;
size--;
}else{
parent.right = target.left;
size--;
}
//只有右子树
}else if(target.right!=null){
if(e.compareTo(parent.right.e)==0){
if(target.right!=null){
parent.right = target.right;
size--;
}else{
parent.right = target.left;
size--;
}
}
}
}
}
private Node minNode(Node node) {
if(node.left==null)
return null;
return minNode(node.left):
}
删除的改进
/**
* 从以node为根的树中删除元素为e的节点,并将删除e节点后生成的新的子树的根返回
*/
public Node removeNode(Node node,E e){
//递归的退出条件
if(node==null){
return null;
}
//判断去到左子树还是右子树上进行删除
//去到左子树上删除
if(e.compareTo(node.left.e)<0){
node.left = removeNode(node.left, e);
size--;
return node;
}
//去到右子树山面删除
else if(e.compareTo(node.right.e)>0){
node.right= removeNode(node.right, e);
size--;
return node;
}
else{
if(node.left==null){
Node rightNode = node.right;
node.right = null;
size--;
return rightNode;
}
if (node.right==null){
Node leftNode = node.left;
node.left = null;
size--;
return leftNode;
}
Node minNode = minNode(node.right);
minNode.right = removeNode(node.right, minNode.e);
minNode.left = node.left;
node.left = node.right = null;
return minNode;
}
}
private Node minNode(Node node) {
if(node.left==null)
return null;
return minNode(node.left);
}