当前位置:   article > 正文

数据结构:AVL树_在数据库中配置avl树

在数据库中配置avl树

目录

1、AVL树的概念

2、二叉搜索树的功能与实现

1、AVL树节点定义

2、AVL树的插入

3、AVL树的旋转操作

1、左旋

2、右旋

3、左右旋

 4、右左旋

 3、AVL树完整代码实现


1、AVL树的概念

        在前面的文章中,我们学过了二叉搜索树,二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii 和E.M.Landis在1962年 发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右 子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

一棵 AVL 树或者是空树,或者是具有以下性质的二叉搜索树:
它的左右子树都是 AVL
左右子树高度之差 ( 简称平衡因子 ) 的绝对值不超过 1(-1/0/1)
平衡因子:右子树高度减去左子树高度
如果一棵二叉搜索树是高度平衡的,它就是 AVL 树。如果它有 n 个结点,其高度可保持在
O(log2 n) ,搜索时间复杂度 O(log2 n)
以下是一个简单AVL树的示例:节点周围的是平衡因子。

2、二叉搜索树的功能与实现

1、AVL树节点定义

  1. template<class K,class V>
  2. struct AVLTreeNode
  3. {
  4. AVLTreeNode<K, V>* _left;
  5. AVLTreeNode<K, V>* _right;
  6. AVLTreeNode<K, V>* _parent;
  7. int _bf; //平衡因子
  8. pair<K, V> _kv;
  9. AVLTreeNode(const pair<K, V>& kv)
  10. :_left(nullptr)
  11. , _right(nullptr)
  12. , _parent(nullptr)
  13. , _bf(0)
  14. ,_kv(kv)
  15. {
  16. }
  17. };
每个节点的平衡因子设置为0,每个节点包含左右指针,以及父节点指针,每个节点的数据用pair来实现,第一个元素为Key来比较。

2、AVL树的插入

AVL树是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看作二叉搜索树

插入过程与二叉搜索树一致,只不过要注意更新节点的平衡因子。

因为平衡因子是右子树高度减去左子树高度,所以如果在左子树添加节点,bf(平衡因子)--,在右子树添加,bf++。

parent节点的平衡因子更新有三种情况:

1、parent的平衡因子为0,说明满足AVL性质,插入成功。

2、parent的平衡因子为1或-1,说明该树的高度增加,需要向上更新。

3、parent的平衡因子为-2或2,说明该节点违反了平衡树性质,需要对其进行旋转处理。

旋转处理下面会介绍,我们先来看插入的代码实现:

  1. bool Insert(const pair<K, V>& kv)
  2. {
  3. if (_root == nullptr)
  4. {
  5. _root = new Node(kv);
  6. return true;
  7. }
  8. Node* parent = nullptr;
  9. Node* cur = _root;
  10. while (cur)
  11. {
  12. if (cur->_kv.first < kv.first)
  13. {
  14. parent = cur;
  15. cur = cur->_right;
  16. }
  17. else if (cur->_kv.first > kv.first)
  18. {
  19. parent = cur;
  20. cur = cur->_left;
  21. }
  22. else
  23. {
  24. return false;
  25. }
  26. }
  27. cur = new Node(kv);
  28. if (parent->_kv.first < kv.first)
  29. {
  30. parent->_right = cur;
  31. }
  32. else
  33. {
  34. parent->_left = cur;
  35. }
  36. cur->_parent = parent;
  37. while (parent)
  38. {
  39. if (cur == parent->_left)
  40. {
  41. parent->_bf--;
  42. }
  43. else
  44. {
  45. parent->_bf++;
  46. }
  47. if (parent->_bf == 0)
  48. {
  49. break;
  50. }
  51. else if (parent->_bf == 1 || parent->_bf == -1)
  52. {
  53. cur = cur->_parent;
  54. parent = parent->_parent;
  55. }
  56. else if (parent->_bf == 2 || parent->_bf == -2)
  57. {
  58. if (parent->_bf == 2 && cur->_bf == 1)
  59. {
  60. RotateL(parent);
  61. }
  62. else if (parent->_bf == -2 && cur->_bf == -1)
  63. {
  64. RotateR(parent);
  65. }
  66. else if (parent->_bf == -2 && cur->_bf == 1)
  67. {
  68. RotateLR(parent);
  69. }
  70. else
  71. {
  72. RotateRL(parent);
  73. }
  74. break;
  75. }
  76. else
  77. {
  78. assert(false);
  79. }
  80. }
  81. return true;
  82. }

寻找插入位置与搜索二叉树一致,然后更新平衡因子 ,对于不同的违反AVL树性质需要不同的旋转操作。

3、AVL树的旋转操作

我们先来看左旋对应的情况:

1、左旋

a,b,c具有相同的高度,旋转后注意更新parent和cur的平衡因子为0;
  1. void RotateL(Node* parent)
  2. {
  3. Node* sub = parent->_right;
  4. Node* subl = sub->_left;
  5. parent->_right = subl;
  6. if (subl)
  7. {
  8. subl->_parent = parent;
  9. }
  10. sub->_left = parent;
  11. Node* ppnode = parent->_parent;
  12. parent->_parent = sub;
  13. if (parent == _root)
  14. {
  15. _root = sub;
  16. sub->_parent = nullptr;
  17. }
  18. else
  19. {
  20. if (parent == ppnode->_left)
  21. {
  22. ppnode->_left = sub;
  23. }
  24. else
  25. {
  26. ppnode->_right = sub;
  27. }
  28. sub->_parent = ppnode;
  29. }
  30. parent->_bf = 0;
  31. sub->_bf = 0;
  32. }

2、右旋

原理与左旋相似,不过是向右旋转而已 (a,b,c具有相同的高度)

  1. void RotateR(Node* parent)
  2. {
  3. Node* sub = parent->_left;
  4. Node* subr = sub->_right;
  5. parent->_left = subr;
  6. if (subr)
  7. {
  8. subr->_parent = parent;
  9. }
  10. sub->_right = parent;
  11. Node* ppnode = parent->_parent;
  12. parent->_parent = sub;
  13. if (parent == _root)
  14. {
  15. _root = sub;
  16. sub->_parent = nullptr;
  17. }
  18. else
  19. {
  20. if (parent == ppnode->_left)
  21. {
  22. ppnode->_left = sub;
  23. }
  24. else
  25. {
  26. ppnode->_right = sub;
  27. }
  28. sub->_parent = ppnode;
  29. }
  30. parent->_bf = 0;
  31. sub->_bf = 0;
  32. }

3、左右旋

先以subl为根左旋,再以parent为根进行右旋。(a,b,c具有相同的高度)

  1. void RotateLR(Node* parent)
  2. {
  3. Node* subl = parent->_left;
  4. Node* sublr = subl->_right;
  5. int bf = sublr->_bf;
  6. RotateL(subl);
  7. RotateR(parent);
  8. if (bf == -1)
  9. {
  10. sublr->_bf = 0;
  11. parent->_bf = 1;
  12. subl->_bf = 0;
  13. }
  14. else if (bf == 1)
  15. {
  16. sublr->_bf = 0;
  17. parent->_bf = 0;
  18. subl->_bf = -1;
  19. }
  20. else if (bf == 0)
  21. {
  22. subl->_bf = 0;
  23. parent->_bf = 0;
  24. sublr->_bf = 0;
  25. }
  26. else
  27. {
  28. assert(false);
  29. }
  30. }

根据sublr的平衡因子的不同(也就是插入到了B还是C)来判断如何更新平衡因子。

 4、右左旋

原理与左右旋相似,只是换了个方向。(a,b,c具有相同的高度)

  1. void RotateRL(Node* parent)
  2. {
  3. Node* subr = parent->_right;
  4. Node* subrl = subr->_left;
  5. int bf = subrl->_bf;
  6. RotateR(subr);
  7. RotateL(parent);
  8. if (bf == -1)
  9. {
  10. subrl->_bf = 0;
  11. parent->_bf = 0;
  12. subr->_bf = 1;
  13. }
  14. else if (bf == 1)
  15. {
  16. subrl->_bf = 0;
  17. parent->_bf = -1;
  18. subr->_bf = 0;
  19. }
  20. else if(bf==0)
  21. {
  22. subrl->_bf = 0;
  23. parent->_bf = 0;
  24. subr->_bf = 0;
  25. }
  26. else
  27. {
  28. assert(false);
  29. }
  30. }

根据sublr的平衡因子的不同(也就是插入到了B还是C)来判断如何更新平衡因子。 

 3、AVL树完整代码实现

内部包含查找以及判断是否是AVL树的函数,以及中序遍历。

  1. #pragma once
  2. namespace AVLTree_test
  3. {
  4. template<class K,class V>
  5. struct AVLTreeNode
  6. {
  7. AVLTreeNode<K, V>* _left;
  8. AVLTreeNode<K, V>* _right;
  9. AVLTreeNode<K, V>* _parent;
  10. int _bf; //平衡因子
  11. pair<K, V> _kv;
  12. AVLTreeNode(const pair<K, V>& kv)
  13. :_left(nullptr)
  14. , _right(nullptr)
  15. , _parent(nullptr)
  16. , _bf(0)
  17. ,_kv(kv)
  18. {
  19. }
  20. };
  21. template<class K,class V>
  22. class AVLTree
  23. {
  24. typedef AVLTreeNode<K, V> Node;
  25. public:
  26. bool Insert(const pair<K, V>& kv)
  27. {
  28. if (_root == nullptr)
  29. {
  30. _root = new Node(kv);
  31. return true;
  32. }
  33. Node* parent = nullptr;
  34. Node* cur = _root;
  35. while (cur)
  36. {
  37. if (cur->_kv.first < kv.first)
  38. {
  39. parent = cur;
  40. cur = cur->_right;
  41. }
  42. else if (cur->_kv.first > kv.first)
  43. {
  44. parent = cur;
  45. cur = cur->_left;
  46. }
  47. else
  48. {
  49. return false;
  50. }
  51. }
  52. cur = new Node(kv);
  53. if (parent->_kv.first < kv.first)
  54. {
  55. parent->_right = cur;
  56. }
  57. else
  58. {
  59. parent->_left = cur;
  60. }
  61. cur->_parent = parent;
  62. while (parent)
  63. {
  64. if (cur == parent->_left)
  65. {
  66. parent->_bf--;
  67. }
  68. else
  69. {
  70. parent->_bf++;
  71. }
  72. if (parent->_bf == 0)
  73. {
  74. break;
  75. }
  76. else if (parent->_bf == 1 || parent->_bf == -1)
  77. {
  78. cur = cur->_parent;
  79. parent = parent->_parent;
  80. }
  81. else if (parent->_bf == 2 || parent->_bf == -2)
  82. {
  83. if (parent->_bf == 2 && cur->_bf == 1)
  84. {
  85. RotateL(parent);
  86. }
  87. else if (parent->_bf == -2 && cur->_bf == -1)
  88. {
  89. RotateR(parent);
  90. }
  91. else if (parent->_bf == -2 && cur->_bf == 1)
  92. {
  93. RotateLR(parent);
  94. }
  95. else
  96. {
  97. RotateRL(parent);
  98. }
  99. break;
  100. }
  101. else
  102. {
  103. assert(false);
  104. }
  105. }
  106. return true;
  107. }
  108. void RotateL(Node* parent)
  109. {
  110. Node* sub = parent->_right;
  111. Node* subl = sub->_left;
  112. parent->_right = subl;
  113. if (subl)
  114. {
  115. subl->_parent = parent;
  116. }
  117. sub->_left = parent;
  118. Node* ppnode = parent->_parent;
  119. parent->_parent = sub;
  120. if (parent == _root)
  121. {
  122. _root = sub;
  123. sub->_parent = nullptr;
  124. }
  125. else
  126. {
  127. if (parent == ppnode->_left)
  128. {
  129. ppnode->_left = sub;
  130. }
  131. else
  132. {
  133. ppnode->_right = sub;
  134. }
  135. sub->_parent = ppnode;
  136. }
  137. parent->_bf = 0;
  138. sub->_bf = 0;
  139. }
  140. void RotateR(Node* parent)
  141. {
  142. Node* sub = parent->_left;
  143. Node* subr = sub->_right;
  144. parent->_left = subr;
  145. if (subr)
  146. {
  147. subr->_parent = parent;
  148. }
  149. sub->_right = parent;
  150. Node* ppnode = parent->_parent;
  151. parent->_parent = sub;
  152. if (parent == _root)
  153. {
  154. _root = sub;
  155. sub->_parent = nullptr;
  156. }
  157. else
  158. {
  159. if (parent == ppnode->_left)
  160. {
  161. ppnode->_left = sub;
  162. }
  163. else
  164. {
  165. ppnode->_right = sub;
  166. }
  167. sub->_parent = parent;
  168. }
  169. parent->_bf = 0;
  170. sub->_bf = 0;
  171. }
  172. void RotateLR(Node* parent)
  173. {
  174. Node* subl = parent->_left;
  175. Node* sublr = subl->_right;
  176. int bf = sublr->_bf;
  177. RotateL(subl);
  178. RotateR(parent);
  179. if (bf == -1)
  180. {
  181. sublr->_bf = 0;
  182. parent->_bf = 1;
  183. subl->_bf = 0;
  184. }
  185. else if (bf == 1)
  186. {
  187. sublr->_bf = 0;
  188. parent->_bf = 0;
  189. subl->_bf = -1;
  190. }
  191. else if (bf == 0)
  192. {
  193. subl->_bf = 0;
  194. parent->_bf = 0;
  195. sublr->_bf = 0;
  196. }
  197. else
  198. {
  199. assert(false);
  200. }
  201. }
  202. void RotateRL(Node* parent)
  203. {
  204. Node* subr = parent->_right;
  205. Node* subrl = subr->_left;
  206. int bf = subrl->_bf;
  207. RotateR(subr);
  208. RotateL(parent);
  209. if (bf == -1)
  210. {
  211. subrl->_bf = 0;
  212. parent->_bf = 0;
  213. subr->_bf = 1;
  214. }
  215. else if (bf == 1)
  216. {
  217. subrl->_bf = 0;
  218. parent->_bf = -1;
  219. subr->_bf = 0;
  220. }
  221. else if(bf==0)
  222. {
  223. subrl->_bf = 0;
  224. parent->_bf = 0;
  225. subr->_bf = 0;
  226. }
  227. else
  228. {
  229. assert(false);
  230. }
  231. }
  232. void _InOrder(Node* root)
  233. {
  234. if (root == nullptr)
  235. return;
  236. _InOrder(root->_left);
  237. cout << root->_kv.first << " " << root->_bf << endl;
  238. _InOrder(root->_right);
  239. }
  240. void InOrder()
  241. {
  242. _InOrder(_root);
  243. }
  244. int Height(Node* root)
  245. {
  246. if (root == nullptr)
  247. {
  248. return 0;
  249. }
  250. int leftHeight = Height(root->_left);
  251. int rightHeight = Height(root->_right);
  252. return (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;
  253. }
  254. bool _IsBalance(Node* root)
  255. {
  256. if (root == nullptr)
  257. return true;
  258. int leftHeight = Height(root->_left);
  259. int rightHeight = Height(root->_right);
  260. if (abs(rightHeight - leftHeight) >= 2)
  261. {
  262. cout << root->_kv.first << "不平衡" << endl;
  263. return false;
  264. }
  265. if (rightHeight - leftHeight != root->_bf)
  266. {
  267. cout << root->_kv.first << "平衡因子异常" << endl;
  268. return false;
  269. }
  270. return _IsBalance(root->_left) && _IsBalance(root->_right);
  271. }
  272. bool IsBalance()
  273. {
  274. return _IsBalance(_root);
  275. }
  276. Node* Find(const K& key)
  277. {
  278. Node* cur = _root;
  279. while (cur)
  280. {
  281. if (cur->_kv.first < key)
  282. {
  283. cur = cur->_right;
  284. }
  285. else if (cur->_kv.first > key)
  286. {
  287. cur = cur->_left;
  288. }
  289. else
  290. {
  291. return cur;
  292. }
  293. }
  294. return NULL;
  295. }
  296. private:
  297. Node* _root = nullptr;
  298. };
  299. void TestAVLTree1()
  300. {
  301. int a[] = { 4, 2, 6, 1,0 ,67,56,33,212,90};
  302. AVLTree<int, int> t;
  303. for (auto e : a)
  304. {
  305. if (e == 14)
  306. {
  307. int x = 0;
  308. }
  309. t.Insert(make_pair(e,e));
  310. }
  311. t.InOrder();
  312. cout << t.IsBalance();
  313. }
  314. }

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

闽ICP备14008679号