《漫画算法2》源码整理-1 二分查找树 AVL树 红黑树
作者:互联网
二分查找树
public class BinarySearchTree {
private Node root;
//查找结点
public Node search(int data) {
Node targetNode = root;
while (targetNode!=null && targetNode.data != data) {
if (data > targetNode.data) {
targetNode = targetNode.right;
} else {
targetNode = targetNode.left;
}
}
if(targetNode == null){
System.out.println("未找到结点:" + data);
} else {
System.out.println("已找到结点:" + data);
}
return targetNode;
}
//中序遍历
public static void inOrderTraversal(Node node){
if(node == null){
return;
}
inOrderTraversal(node.left);
System.out.print(node.data + " ");
inOrderTraversal(node.right);
}
//插入结点
public boolean insert(int data) {
Node node = new Node(data);
if(root == null){
root = node;
return true;
}
Node targetNode = root;
while (targetNode != null) {
if( data == targetNode.data){
System.out.println("二叉查找树中已有重复的结点:" + data);
return false;
}
else if (data > targetNode.data) {
if(targetNode.right == null){
targetNode.right = node;
return true;
}
targetNode = targetNode.right;
}
else {
if(targetNode.left == null){
targetNode.left = node;
return true;
}
targetNode = targetNode.left;
}
}
return true;
}
//删除结点
public boolean delete(int data) {
Node targetNode = root;
Node parentNode = new Node(data);
//判断待删除结点是否存在
while (targetNode.data != data) {
parentNode = targetNode;
if (data > targetNode.data) {
targetNode = targetNode.right;
} else {
targetNode = targetNode.left;
}
if (targetNode == null) {
// 没有找到待删除结点
return false;
}
}
// 待删除结点没有子节点
if (targetNode.right==null && targetNode.left==null) {
if (targetNode == root) {
//待删除结点是根结点
root = null;
} else {
if (parentNode.right == targetNode) {
parentNode.right = null;
} else {
parentNode.left = null;
}
}
}
//待删除结点有一个子结点(右)
else if(targetNode.left == null) {
if(targetNode == root) {
root = targetNode.right;
} else if(parentNode.right == targetNode) {
parentNode.right = targetNode.right;
} else {
parentNode.left = targetNode.right;
}
}
//待删除结点有一个子结点(左)
else if(targetNode.right == null) {
if(targetNode == root) {
root = targetNode.left;
} else if(parentNode.right == targetNode) {
parentNode.right = targetNode.left;
} else {
parentNode.left = targetNode.left;
}
}
//待删除结点有两个子结点
else {
//待删除结点的后继结点的父结点
Node successParentNode = targetNode;
//待删除结点的后继结点
Node successNode = targetNode.right;
while(successNode.left != null)
{
successParentNode = successNode;
successNode = successNode.left;
}
//把后继结点复制到待删除结点位置
targetNode.data = successNode.data;
//删除后继结点
if(successParentNode.right == successNode) {
successParentNode.right = successNode.right;
} else {
successParentNode.left = successNode.right;
}
}
return true;
}
// 结点类
private class Node {
int data;
Node right;
Node left;
Node(int data){
this.data = data;
}
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
int input[]= {6,3,8,2,5,7,9,1,4};
for(int i=0; i<input.length; i++) {
tree.insert(input[i]);
}
inOrderTraversal(tree.root);
System.out.println();
tree.search(3);
tree.delete(3);
tree.search(3);
tree.delete(6);
inOrderTraversal(tree.root);
}
}
AVL树
import java.util.LinkedList;
import java.util.Queue;
public class AVLTree {
private TreeNode root;
/*
* 获取树的高度
*/
private int height(TreeNode node) {
if (node != null)
return node.height;
return 0;
}
public int height() {
return height(root);
}
//查找结点
public TreeNode search(TreeNode node, int data) {
while (node!=null) {
if (data < node.data)
node = node.left;
else if (data > node.data)
node = node.right;
else
return node;
}
return node;
}
//左左局面旋转
private TreeNode leftLeftRotation(TreeNode node) {
//leftChildNode 对应示意图中的结点B
TreeNode leftChildNode = node.left;
node.left = leftChildNode.right;
leftChildNode.right = node;
//刷新结点A和结点B的高度
node.height = Math.max(height(node.left), height(node.right)) + 1;
leftChildNode.height = Math.max(height(leftChildNode.left), node.height) + 1;
//返回旋转后的父结点
return leftChildNode;
}
//右右局面旋转
private TreeNode rightRightRotation(TreeNode node) {
//rightChildNode 对应示意图中的结点B
TreeNode rightChildNode = node.right;
node.right = rightChildNode.left;
rightChildNode.left = node;
//刷新结点A和结点B的高度
node.height = Math.max(height(node.left), height(node.right)) + 1;
rightChildNode.height = Math.max(height(rightChildNode.right), node.height) + 1;
//返回旋转后的父结点
return rightChildNode;
}
//左右局面旋转
private TreeNode leftRightRotation(TreeNode node) {
//先做左旋
node.left = rightRightRotation(node.left);
//再做右旋
return leftLeftRotation(node);
}
//右左局面旋转
private TreeNode rightLeftRotation(TreeNode node) {
//先做右旋
node.right = leftLeftRotation(node.right);
//再做左旋
return rightRightRotation(node);
}
//插入结点
public void insert(int data) {
root = insert(root, data);
}
//插入结点详细过程(递归)
private TreeNode insert(TreeNode node, int data) {
if (node == null) {
node = new TreeNode(data);
} else {
if (data < node.data) {
//新结点小于当前结点,选择当前结点的左子树插入
node.left = insert(node.left, data);
// 插入节点后,若AVL树失去平衡,则进行相应的调节。
if (node.getBalance() == 2) {
if (data < node.left.data) {
node = leftLeftRotation(node);
} else {
node = leftRightRotation(node);
}
}
} else if (data > node.data) {
//新结点大于当前结点,选择当前结点的右子树插入
node.right = insert(node.right, data);
// 插入节点后,若AVL树失去平衡,则进行相应的调节。
if (node.getBalance() == -2) {
if (data > node.right.data) {
node = rightRightRotation(node);
} else {
node = rightLeftRotation(node);
}
}
} else {
System.out.println("AVL树中已有重复的结点!");
}
}
//刷新结点的高度
node.height = Math.max(height(node.left), height(node.right)) + 1;
return node;
}
//删除结点
public void remove(int data) {
TreeNode deletedNode;
if ((deletedNode = search(root, data)) != null)
root = remove(root, deletedNode);
}
//删除结点详细过程(递归)
private TreeNode remove(TreeNode node, TreeNode deletedNode) {
// 根为空 或者 没有要删除的节点,直接返回null。
if (node==null || deletedNode==null)
return null;
if (deletedNode.data < node.data){
//待删除结点小于当前结点,在当前结点的左子树继续执行
node.left = remove(node.left, deletedNode);
// 删除节点后,若AVL树失去平衡,则进行相应的调节。
if (height(node.right) - height(node.left) == 2) {
TreeNode r = node.right;
if (height(r.left) > height(r.right))
node = rightLeftRotation(node);
else
node = rightRightRotation(node);
}
} else if (deletedNode.data > node.data) {
//待删除结点大于当前结点,在当前结点的右子树继续执行
node.right = remove(node.right, deletedNode);
// 删除节点后,若AVL树失去平衡,则进行相应的调节。
if (height(node.left) - height(node.right) == 2) {
TreeNode l = node.left;
if (height(l.right) > height(l.left))
node = leftRightRotation(node);
else
node = leftLeftRotation(node);
}
} else {
// tree的左右孩子都非空
if ((node.left!=null) && (node.right!=null)) {
if (height(node.left) > height(node.right)) {
// 如果node的左子树比右子树高,找出左子树最大结点赋值给Node,并删除最小结点
TreeNode max = maximum(node.left);
node.data = max.data;
node.left = remove(node.left, max);
} else {
// 如果node的右子树比左子树高,找出右子树最小结点赋值给Node,并删除最小结点
TreeNode min = minimum(node.right);
node.data = min.data;
node.right = remove(node.right, min);
}
} else {
node = (node.left!=null) ? node.left : node.right;
}
}
node.height = Math.max(height(node.left), height(node.right)) + 1;
return node;
}
//找出结点node为根的子树的最大节点
private TreeNode maximum(TreeNode node) {
if (node == null)
return null;
while(node.right != null)
node = node.right;
return node;
}
//找出结点node为根的子树的最小节点
private TreeNode minimum(TreeNode node) {
if (node == null)
return null;
while(node.left != null)
node = node.left;
return node;
}
//中序遍历
public static void inOrderTraversal(TreeNode node) {
if(node != null) {
inOrderTraversal(node.left);
System.out.print(node.data+" ");
inOrderTraversal(node.right);
}
}
//层序遍历
public static void levelOrderTraversal(TreeNode root){
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
System.out.print(node.data+" ");
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
}
class TreeNode {
int data;
int height;
TreeNode left;
TreeNode right;
public TreeNode(int data) {
this.data = data;
this.height = 0;
}
//获得结点的平衡因子
public int getBalance(){
int left = (this.left==null ? 0:this.left.height);
int right = (this.right==null ? 0:this.right.height);
return left - right;
}
}
public static void main(String[] args) {
AVLTree tree = new AVLTree();
int input[]= {5,3,7,2,4,6,9,1};
for(int i=0; i<input.length; i++) {
tree.insert(input[i]);
}
System.out.println("中序遍历: ");
inOrderTraversal(tree.root);
System.out.println();
System.out.println("层序遍历: ");
levelOrderTraversal(tree.root);
System.out.println();
System.out.printf("高度: %d\n", tree.height());
int deletedData = 3;
System.out.printf("删除根节点: %d\n", deletedData);
tree.remove(deletedData);
System.out.println("中序遍历: ");
inOrderTraversal(tree.root);
System.out.println();
System.out.println("层序遍历: ");
levelOrderTraversal(tree.root);
System.out.println();
System.out.printf("高度: %d\n", tree.height());
}
}
红黑树
import java.util.LinkedList;
import java.util.Queue;
public class RedBlackTree {
TreeNode root;
final static boolean RED = true;
final static boolean BLACK = false;
//查找结点
public TreeNode search(int data) {
TreeNode tmp = root;
while (tmp != null) {
if (tmp.data == data)
return tmp;
else if (tmp.data > data)
tmp = tmp.left;
else
tmp = tmp.right;
}
return null;
}
//插入结点
public boolean insert(int data) {
TreeNode node = new TreeNode(data);
//局面1:新结点位于树根,没有父结点。
if (root == null) {
root = node;
node.color = BLACK;
return true;
}
TreeNode targetNode = root;
while (targetNode != null) {
if( data == targetNode.data){
System.out.println("红黑树中已有重复的结点:" + data);
return false;
} else if (data > targetNode.data) {
if(targetNode.right == null){
targetNode.right = node;
node.parent = targetNode;
insertAdjust(node);
return true;
}
targetNode = targetNode.right;
} else {
if(targetNode.left == null){
targetNode.left = node;
node.parent = targetNode;
insertAdjust(node);
return true;
}
targetNode = targetNode.left;
}
}
return true;
}
//插入后自我调整
private void insertAdjust(TreeNode node) {
//创建父结点和祖父结点指针
TreeNode parent, grandParent;
//局面3的调整有可能引发后续的一系列调整,所以使用while循环。
while (node.parent != null && node.parent.color == RED) {
parent = node.parent;
grandParent = parent.parent;
if (grandParent.left == parent) {
TreeNode uncle = grandParent.right;
//局面3:新结点的父结点和叔叔结点都是红色。
if (uncle != null && uncle.color == RED) {
parent.color = BLACK;
uncle.color = BLACK;
grandParent.color = RED;
node = grandParent;
continue;
}
//局面4:新结点的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的右孩子,父结点是祖父结点的左孩子。
if (node == parent.right) {
leftRotate(parent);
TreeNode tmp = node;
node = parent;
parent = tmp;
}
//局面5:新结点的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的左孩子,父结点是祖父结点的左孩子。
parent.color = BLACK;
grandParent.color = RED;
rightRotate(grandParent);
} else {
TreeNode uncle = grandParent.left;
//局面3(镜像):新结点的父结点和叔叔结点都是红色。
if (uncle != null && uncle.color == RED) {
parent.color = BLACK;
uncle.color = BLACK;
grandParent.color = RED;
node = grandParent;
continue;
}
//局面4(镜像):新结点的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的左孩子,父结点是祖父结点的右孩子。
if (node == parent.left) {
rightRotate(parent);
TreeNode tmp = node;
node = parent;
parent = tmp;
}
//局面5(镜像):新结点的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的右孩子,父结点是祖父结点的右孩子。
parent.color = BLACK;
grandParent.color = RED;
leftRotate(grandParent);
}
}
//经过局面3的调整,有可能把根结点变为红色,此时再变回黑色即可。
if(root.color == RED){
root.color = BLACK;
}
}
//删除节点
public void remove(int key) {
remove(search(key));
}
//删除节点详细逻辑
private void remove(TreeNode node) {
TreeNode targetNode = node;
if (node == null)
return;
//第一步:如果待删除结点有两个非空的孩子结点,转化成待删除结点只有一个孩子(或没有孩子)的情况。
if (node.left != null && node.right != null) {
//待删除结点的后继结点
TreeNode successNode = targetNode.right;
while(successNode.left != null) {
successNode = successNode.left;
}
if(targetNode == root) {
root = successNode;
}
//把后继结点复制到待删除结点位置
targetNode.data = successNode.data;
remove(successNode);
return;
}
//第二步:根据待删除结点和其唯一子结点的颜色,分情况处理。
TreeNode successNode = node.left!= null ? node.left : node.right;
TreeNode parent = node.parent;
if (parent == null) {
//子情况1,被删除结点是红黑树的根结点:
root = successNode;
if (successNode != null)
successNode.parent = null;
} else {
if (successNode != null)
successNode.parent = parent;
if (parent.left == node)
parent.left = successNode;
else {
parent.right = successNode;
}
}
if (node.color == BLACK )
//第三步:遇到双黑结点,在子结点顶替父结点之后,分成6种子情况处理。
removeAdjust(parent, successNode);
}
//删除结点后的自我调整
private void removeAdjust(TreeNode parent, TreeNode node) {
while ((node == null || node.color == BLACK) && node != root) {
if (parent.left == node) {
//node的兄弟节点
TreeNode sibling = parent.right;
//子情况3,node的兄弟结点是红色:
if (sibling != null && sibling.color == RED) {
parent.color = RED;
sibling.color = BLACK;
leftRotate(parent);
sibling = parent.right;
}
if (sibling == null || ((sibling.left == null || sibling.left.color == BLACK) && (sibling.right == null || sibling.right.color == BLACK))) {
//子情况2(镜像),node的父结点是黑色,兄弟和侄子结点是黑色:
if(parent.color == BLACK){
sibling.color = RED;
node = parent;
parent = node.parent;
continue;
}
//子情况4(镜像),node的父结点是红色,兄弟和侄子结点是黑色:
else {
sibling.color = RED;
break;
}
}
//子情况5,node的父结点随意,兄弟结点是黑色右孩子,左侄子结点是红色,右侄子结点是黑色:
if (sibling.left == null || sibling.color == RED) {
sibling.left.color = BLACK;
sibling.color = RED;
rightRotate(sibling);
sibling = sibling.parent;
}
//子情况6,结点2的父结点随意,兄弟结点B是黑色右孩子,右侄子结点是红色:
sibling.color = parent.color;
parent.color = BLACK;
sibling.right.color = BLACK;
leftRotate(parent);
node = root; //跳出循环
} else {
//node的兄弟节点
TreeNode sibling = parent.left;
//子情况3(镜像),node的兄弟结点是红色:
if (sibling != null && sibling.color == RED) {
parent.color = RED;
sibling.color = BLACK;
rightRotate(parent);
sibling = parent.left;
}
if (sibling == null || ((sibling.left == null || sibling.left.color == BLACK) && (sibling.right == null || sibling.right.color == BLACK))) {
//子情况2(镜像),node的父结点是黑色,兄弟和侄子结点是黑色:
if(parent.color == BLACK){
sibling.color = RED;
node = parent;
parent = node.parent;
continue;
}
//子情况4(镜像),node的父结点是红色,兄弟和侄子结点是黑色:
else {
sibling.color = RED;
break;
}
}
//子情况5(镜像),node的父结点随意,兄弟结点是黑色左孩子,右侄子结点是红色,左侄子结点是黑色:
if (sibling.right == null || sibling.right.color == RED) {
sibling.right.color = BLACK;
sibling.color = RED;
leftRotate(sibling);
sibling = sibling.parent;
}
//子情况6(镜像),结点2的父结点随意,兄弟结点是黑色左孩子,左侄子结点是红色:
sibling.color = parent.color;
parent.color = BLACK;
sibling.left.color = BLACK;
rightRotate(parent);
node = root; //跳出循环
}
}
if (node != null) {
node.color = BLACK;
}
}
//左旋转
private void leftRotate(TreeNode node) {
TreeNode right = node.right;
TreeNode parent = node.parent;
if (parent == null) {
root = right;
right.parent = null;
} else {
if (parent.left != null && parent.left == node) {
parent.left = right;
} else {
parent.right = right;
}
right.parent = parent;
}
node.parent = right;
node.right = right.left;
if (right.left != null) {
right.left.parent = node;
}
right.left = node;
}
//右旋转
private void rightRotate(TreeNode node) {
TreeNode left = node.left;
TreeNode parent = node.parent;
if (parent == null) {
root = left;
left.parent = null;
} else {
if (parent.left != null && parent.left == node) {
parent.left = left;
} else {
parent.right = left;
}
left.parent = parent;
}
node.parent = left;
node.left = left.right;
if (left.right != null) {
left.right.parent = node;
}
left.right = node;
}
//中序遍历
public static void inOrderTraversal(TreeNode node) {
if(node != null) {
inOrderTraversal(node.left);
System.out.print(node);
inOrderTraversal(node.right);
}
}
//层序遍历
public static void levelOrderTraversal(TreeNode root){
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
System.out.print(node);
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
}
class TreeNode {
int data;
boolean color;
TreeNode left;
TreeNode right;
TreeNode parent;
public TreeNode(int data) {
this.data = data;
this.color = RED;
}
@Override
public String toString() {
return data + (color?"(red)":"(black)") + " " ;
}
}
public static void main(String[] args) {
RedBlackTree rbTree = new RedBlackTree();
int input[]= {13,8,17,1,11,15,25,6,22,27};
for(int i=0; i<input.length; i++) {
rbTree.insert(input[i]);
}
rbTree.remove(8);
System.out.println("中序遍历: ");
inOrderTraversal(rbTree.root);
System.out.println();
System.out.println("层序遍历: ");
levelOrderTraversal(rbTree.root);
System.out.println();
}
}
标签:node,结点,right,parent,AVL,源码,红黑树,data,left 来源: https://blog.csdn.net/GarfieldEr007/article/details/122287542