当前位置:   article > 正文

数据结构篇:旋转操作在AVL树中的实现过程

数据结构篇:旋转操作在AVL树中的实现过程

本节课在线学习视频(网盘地址,保存后即可免费观看):

https://pan.quark.cn/s/06d5ed47e33b

AVL树是平衡二叉搜索树的一种,它通过旋转操作来保持树的平衡。AVL树的特点是,任何节点的两个子树的高度最大差别为1。本文将详细介绍AVL树中的旋转操作及其实现过程,并通过多个代码案例来说明这些操作的应用。

1. AVL树的基本概念

AVL树是一种自平衡二叉搜索树,其核心思想是通过旋转操作来维持树的平衡。旋转操作有四种:左旋、右旋、左右旋和右左旋。旋转操作的目的是调整树的结构,使其保持平衡,从而保证二叉搜索树的性能。

平衡因子

平衡因子是指某个节点的左子树高度减去右子树高度的值。AVL树的每个节点的平衡因子只能是-1、0或1。

2. 旋转操作

2.1 右旋(Right Rotation)

右旋是对某个节点进行的单次旋转,使得该节点的左子树成为其父节点。

案例1:右旋操作
  1. class AVLNode {
  2. int val;
  3. int height;
  4. AVLNode left;
  5. AVLNode right;
  6. AVLNode(int val) {
  7. this.val = val;
  8. this.height = 1;
  9. }
  10. }
  11. public class AVLTree {
  12. private int height(AVLNode node) {
  13. if (node == null) return 0;
  14. return node.height;
  15. }
  16. private AVLNode rightRotate(AVLNode y) {
  17. AVLNode x = y.left;
  18. AVLNode T2 = x.right;
  19. x.right = y;
  20. y.left = T2;
  21. y.height = Math.max(height(y.left), height(y.right)) + 1;
  22. x.height = Math.max(height(x.left), height(x.right)) + 1;
  23. return x;
  24. }
  25. public static void main(String[] args) {
  26. AVLTree tree = new AVLTree();
  27. AVLNode root = new AVLNode(30);
  28. root.left = new AVLNode(20);
  29. root.left.left = new AVLNode(10);
  30. root = tree.rightRotate(root);
  31. System.out.println("After right rotation, root is: " + root.val);
  32. }
  33. }

在这个例子中,我们对根节点进行了右旋操作,使其左子树成为新的根节点。

2.2 左旋(Left Rotation)

左旋是对某个节点进行的单次旋转,使得该节点的右子树成为其父节点。

案例2:左旋操作
  1. class AVLTree {
  2. // 同上
  3. private AVLNode leftRotate(AVLNode x) {
  4. AVLNode y = x.right;
  5. AVLNode T2 = y.left;
  6. y.left = x;
  7. x.right = T2;
  8. x.height = Math.max(height(x.left), height(x.right)) + 1;
  9. y.height = Math.max(height(y.left), height(y.right)) + 1;
  10. return y;
  11. }
  12. public static void main(String[] args) {
  13. AVLTree tree = new AVLTree();
  14. AVLNode root = new AVLNode(10);
  15. root.right = new AVLNode(20);
  16. root.right.right = new AVLNode(30);
  17. root = tree.leftRotate(root);
  18. System.out.println("After left rotation, root is: " + root.val);
  19. }
  20. }

在这个例子中,我们对根节点进行了左旋操作,使其右子树成为新的根节点。

2.3 左右旋(Left-Right Rotation)

左右旋是对某个节点进行的两次旋转:先对其左子树进行左旋,再对该节点进行右旋。

案例3:左右旋操作
  1. class AVLTree {
  2. // 同上
  3. private AVLNode leftRightRotate(AVLNode node) {
  4. node.left = leftRotate(node.left);
  5. return rightRotate(node);
  6. }
  7. public static void main(String[] args) {
  8. AVLTree tree = new AVLTree();
  9. AVLNode root = new AVLNode(30);
  10. root.left = new AVLNode(10);
  11. root.left.right = new AVLNode(20);
  12. root = tree.leftRightRotate(root);
  13. System.out.println("After left-right rotation, root is: " + root.val);
  14. }
  15. }

在这个例子中,我们对根节点进行了左右旋操作,先对其左子树进行左旋,再对根节点进行右旋。

2.4 右左旋(Right-Left Rotation)

右左旋是对某个节点进行的两次旋转:先对其右子树进行右旋,再对该节点进行左旋。

案例4:右左旋操作
  1. class AVLTree {
  2. // 同上
  3. private AVLNode rightLeftRotate(AVLNode node) {
  4. node.right = rightRotate(node.right);
  5. return leftRotate(node);
  6. }
  7. public static void main(String[] args) {
  8. AVLTree tree = new AVLTree();
  9. AVLNode root = new AVLNode(10);
  10. root.right = new AVLNode(30);
  11. root.right.left = new AVLNode(20);
  12. root = tree.rightLeftRotate(root);
  13. System.out.println("After right-left rotation, root is: " + root.val);
  14. }
  15. }

在这个例子中,我们对根节点进行了右左旋操作,先对其右子树进行右旋,再对根节点进行左旋。

3. AVL树的插入操作

AVL树的插入操作需要在插入新节点后,检查节点的平衡因子,并根据平衡因子进行相应的旋转操作,以保持树的平衡。

案例5:AVL树的插入操作
  1. public class AVLTree {
  2. // 同上
  3. private int balanceFactor(AVLNode node) {
  4. if (node == null) return 0;
  5. return height(node.left) - height(node.right);
  6. }
  7. public AVLNode insert(AVLNode node, int val) {
  8. if (node == null) return new AVLNode(val);
  9. if (val < node.val) node.left = insert(node.left, val);
  10. else if (val > node.val) node.right = insert(node.right, val);
  11. else return node;
  12. node.height = 1 + Math.max(height(node.left), height(node.right));
  13. int balance = balanceFactor(node);
  14. if (balance > 1 && val < node.left.val) return rightRotate(node);
  15. if (balance < -1 && val > node.right.val) return leftRotate(node);
  16. if (balance > 1 && val > node.left.val) {
  17. node.left = leftRotate(node.left);
  18. return rightRotate(node);
  19. }
  20. if (balance < -1 && val < node.right.val) {
  21. node.right = rightRotate(node.right);
  22. return leftRotate(node);
  23. }
  24. return node;
  25. }
  26. public static void main(String[] args) {
  27. AVLTree tree = new AVLTree();
  28. AVLNode root = null;
  29. int[] values = {10, 20, 30, 40, 50, 25};
  30. for (int val : values) {
  31. root = tree.insert(root, val);
  32. }
  33. System.out.println("AVL Tree constructed successfully.");
  34. }
  35. }

在这个例子中,我们实现了AVL树的插入操作。每次插入新节点后,我们检查平衡因子,并通过旋转操作保持树的平衡。

4. 注意事项

  • 在进行旋转操作时,需要同时更新节点的高度和子树的高度。
  • 插入和删除操作可能会导致多个节点的平衡因子变化,需要从插入或删除位置向上逐层检查和调整。
  • 在实现AVL树时,确保所有旋转操作的逻辑正确,以避免树的不平衡或错误的结构。

结语

本文详细介绍了AVL树中的旋转操作及其实现过程,包括右旋、左旋、左右旋和右左旋。通过多个代码案例,我们展示了这些旋转操作的应用和效果。在实际开发中,AVL树通过旋转操作保持平衡,从而保证二叉搜索树的高效性能。希望这些示例和注意事项能帮助你更好地理解和应用AVL树中的旋转操作。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/737232
推荐阅读
相关标签
  

闽ICP备14008679号