AVL树是高度平衡的而二叉树。它的特点是:AVL树中任何节点的两个子树的高度最大差别为1。

旋转

如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。这种失去平衡的可以概括为4种姿态:LL(左左),LR(左右),RR(右右)和RL(右左)。下面给出它们的示意图:

1) LL:LeftLeft,也称为”左左”。插入或删除一个节点后,根节点的左子树的左子树还有非空子节点,导致”根的左子树的高度”比”根的右子树的高度”大2,导致AVL树失去了平衡。

例如,在上面LL情况中,由于”根节点(8)的左子树(4)的左子树(2)还有非空子节点”,而”根节点(8)的右子树(12)没有子节点”;导致”根节点(8)的左子树(4)高度”比”根节点(8)的右子树(12)”高2。

(2) LR:LeftRight,也称为”左右”。插入或删除一个节点后,根节点的左子树的右子树还有非空子节点,导致”根的左子树的高度”比”根的右子树的高度”大2,导致AVL树失去了平衡。

例如,在上面LR情况中,由于”根节点(8)的左子树(4)的左子树(6)还有非空子节点”,而”根节点(8)的右子树(12)没有子节点”;导致”根节点(8)的左子树(4)高度”比”根节点(8)的右子树(12)”高2。

(3) RL:RightLeft,称为”右左”。插入或删除一个节点后,根节点的右子树的左子树还有非空子节点,导致”根的右子树的高度”比”根的左子树的高度”大2,导致AVL树失去了平衡。

例如,在上面RL情况中,由于”根节点(8)的右子树(12)的左子树(10)还有非空子节点”,而”根节点(8)的左子树(4)没有子节点”;导致”根节点(8)的右子树(12)高度”比”根节点(8)的左子树(4)”高2。

(4) RR:RightRight,称为”右右”。插入或删除一个节点后,根节点的右子树的右子树还有非空子节点,导致”根的右子树的高度”比”根的左子树的高度”大2,导致AVL树失去了平衡。

例如,在上面RR情况中,由于”根节点(8)的右子树(12)的右子树(14)还有非空子节点”,而”根节点(8)的左子树(4)没有子节点”;导致”根节点(8)的右子树(12)高度”比”根节点(8)的左子树(4)”高2。

前面说过,如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。AVL失去平衡之后,可以通过旋转使其恢复平衡,下面分别介绍”LL(左左),LR(左右),RR(右右)和RL(右左)”这4种情况对应的旋转方法。

2.1 LL的旋转

LL失去平衡的情况,可以通过一次旋转让AVL树恢复平衡。如下图:

  1. /*
  2. * LL:左左对应的情况(左单旋转)。
  3. *
  4. * 返回值:旋转后的根节点
  5. */
  6. template <class T>
  7. AVLTreeNode<T>* AVLTree<T>::leftLeftRotation(AVLTreeNode<T>* k2)
  8. {
  9. AVLTreeNode<T>* k1;
  10. k1 = k2->left;
  11. k2->left = k1->right;
  12. k1->right = k2;
  13. k2->height = max( height(k2->left), height(k2->right)) + 1;
  14. k1->height = max( height(k1->left), k2->height) + 1;
  15. return k1;
  16. }

2.2 RR的旋转

理解了LL之后,RR就相当容易理解了。RR是与LL对称的情况!RR恢复平衡的旋转方法如下:

  1. /*
  2. * RR:右右对应的情况(右单旋转)。
  3. *
  4. * 返回值:旋转后的根节点
  5. */
  6. template <class T>
  7. AVLTreeNode<T>* AVLTree<T>::rightRightRotation(AVLTreeNode<T>* k1)
  8. {
  9. AVLTreeNode<T>* k2;
  10. k2 = k1->right;
  11. k1->right = k2->left;
  12. k2->left = k1;
  13. k1->height = max( height(k1->left), height(k1->right)) + 1;
  14. k2->height = max( height(k2->right), k1->height) + 1;
  15. return k2;
  16. }

2.3 LR的旋转

LR失去平衡的情况,需要经过两次旋转才能让AVL树恢复平衡。如下图:

  1. /*
  2. * LR:左右对应的情况(左双旋转)。
  3. *
  4. * 返回值:旋转后的根节点
  5. */
  6. template <class T>
  7. AVLTreeNode<T>* AVLTree<T>::leftRightRotation(AVLTreeNode<T>* k3)
  8. {
  9. k3->left = rightRightRotation(k3->left);
  10. return leftLeftRotation(k3);
  11. }

2.4 RL的旋转

RL是与LR的对称情况!RL恢复平衡的旋转方法如下:

  1. /*
  2. * RL:右左对应的情况(右双旋转)。
  3. *
  4. * 返回值:旋转后的根节点
  5. */
  6. template <class T>
  7. AVLTreeNode<T>* AVLTree<T>::rightLeftRotation(AVLTreeNode<T>* k1)
  8. {
  9. k1->right = leftLeftRotation(k1->right);
  10. return rightRightRotation(k1);
  11. }

完整代码

  1. #ifndef _AVL_TREE_HPP_
  2. #define _AVL_TREE_HPP_
  3. #include <iomanip>
  4. #include <iostream>
  5. using namespace std;
  6. template <class T>
  7. class AVLTreeNode{
  8. public:
  9. T key; // 关键字(键值)
  10. int height; // 高度
  11. AVLTreeNode *left; // 左孩子
  12. AVLTreeNode *right; // 右孩子
  13. AVLTreeNode(T value, AVLTreeNode *l, AVLTreeNode *r):
  14. key(value), height(0),left(l),right(r) {}
  15. };
  16. template <class T>
  17. class AVLTree {
  18. private:
  19. AVLTreeNode<T> *mRoot; // 根结点
  20. public:
  21. AVLTree();
  22. ~AVLTree();
  23. // 获取树的高度
  24. int height();
  25. // 获取树的高度
  26. int max(int a, int b);
  27. // 前序遍历"AVL树"
  28. void preOrder();
  29. // 中序遍历"AVL树"
  30. void inOrder();
  31. // 后序遍历"AVL树"
  32. void postOrder();
  33. // (递归实现)查找"AVL树"中键值为key的节点
  34. AVLTreeNode<T>* search(T key);
  35. // (非递归实现)查找"AVL树"中键值为key的节点
  36. AVLTreeNode<T>* iterativeSearch(T key);
  37. // 查找最小结点:返回最小结点的键值。
  38. T minimum();
  39. // 查找最大结点:返回最大结点的键值。
  40. T maximum();
  41. // 将结点(key为节点键值)插入到AVL树中
  42. void insert(T key);
  43. // 删除结点(key为节点键值)
  44. void remove(T key);
  45. // 销毁AVL树
  46. void destroy();
  47. // 打印AVL树
  48. void print();
  49. private:
  50. // 获取树的高度
  51. int height(AVLTreeNode<T>* tree) ;
  52. // 前序遍历"AVL树"
  53. void preOrder(AVLTreeNode<T>* tree) const;
  54. // 中序遍历"AVL树"
  55. void inOrder(AVLTreeNode<T>* tree) const;
  56. // 后序遍历"AVL树"
  57. void postOrder(AVLTreeNode<T>* tree) const;
  58. // (递归实现)查找"AVL树x"中键值为key的节点
  59. AVLTreeNode<T>* search(AVLTreeNode<T>* x, T key) const;
  60. // (非递归实现)查找"AVL树x"中键值为key的节点
  61. AVLTreeNode<T>* iterativeSearch(AVLTreeNode<T>* x, T key) const;
  62. // 查找最小结点:返回tree为根结点的AVL树的最小结点。
  63. AVLTreeNode<T>* minimum(AVLTreeNode<T>* tree);
  64. // 查找最大结点:返回tree为根结点的AVL树的最大结点。
  65. AVLTreeNode<T>* maximum(AVLTreeNode<T>* tree);
  66. // LL:左左对应的情况(左单旋转)。
  67. AVLTreeNode<T>* leftLeftRotation(AVLTreeNode<T>* k2);
  68. // RR:右右对应的情况(右单旋转)。
  69. AVLTreeNode<T>* rightRightRotation(AVLTreeNode<T>* k1);
  70. // LR:左右对应的情况(左双旋转)。
  71. AVLTreeNode<T>* leftRightRotation(AVLTreeNode<T>* k3);
  72. // RL:右左对应的情况(右双旋转)。
  73. AVLTreeNode<T>* rightLeftRotation(AVLTreeNode<T>* k1);
  74. // 将结点(z)插入到AVL树(tree)中
  75. AVLTreeNode<T>* insert(AVLTreeNode<T>* &tree, T key);
  76. // 删除AVL树(tree)中的结点(z),并返回被删除的结点
  77. AVLTreeNode<T>* remove(AVLTreeNode<T>* &tree, AVLTreeNode<T>* z);
  78. // 销毁AVL树
  79. void destroy(AVLTreeNode<T>* &tree);
  80. // 打印AVL树
  81. void print(AVLTreeNode<T>* tree, T key, int direction);
  82. };
  83. /*
  84. * 构造函数
  85. */
  86. template <class T>
  87. AVLTree<T>::AVLTree():mRoot(NULL)
  88. {
  89. }
  90. /*
  91. * 析构函数
  92. */
  93. template <class T>
  94. AVLTree<T>::~AVLTree()
  95. {
  96. destroy(mRoot);
  97. }
  98. /*
  99. * 获取树的高度
  100. */
  101. template <class T>
  102. int AVLTree<T>::height(AVLTreeNode<T>* tree)
  103. {
  104. if (tree != NULL)
  105. return tree->height;
  106. return 0;
  107. }
  108. template <class T>
  109. int AVLTree<T>::height()
  110. {
  111. return height(mRoot);
  112. }
  113. /*
  114. * 比较两个值的大小
  115. */
  116. template <class T>
  117. int AVLTree<T>::max(int a, int b)
  118. {
  119. return a>b ? a : b;
  120. }
  121. /*
  122. * 前序遍历"AVL树"
  123. */
  124. template <class T>
  125. void AVLTree<T>::preOrder(AVLTreeNode<T>* tree) const
  126. {
  127. if(tree != NULL)
  128. {
  129. cout<< tree->key << " " ;
  130. preOrder(tree->left);
  131. preOrder(tree->right);
  132. }
  133. }
  134. template <class T>
  135. void AVLTree<T>::preOrder()
  136. {
  137. preOrder(mRoot);
  138. }
  139. /*
  140. * 中序遍历"AVL树"
  141. */
  142. template <class T>
  143. void AVLTree<T>::inOrder(AVLTreeNode<T>* tree) const
  144. {
  145. if(tree != NULL)
  146. {
  147. inOrder(tree->left);
  148. cout<< tree->key << " " ;
  149. inOrder(tree->right);
  150. }
  151. }
  152. template <class T>
  153. void AVLTree<T>::inOrder()
  154. {
  155. inOrder(mRoot);
  156. }
  157. /*
  158. * 后序遍历"AVL树"
  159. */
  160. template <class T>
  161. void AVLTree<T>::postOrder(AVLTreeNode<T>* tree) const
  162. {
  163. if(tree != NULL)
  164. {
  165. postOrder(tree->left);
  166. postOrder(tree->right);
  167. cout<< tree->key << " " ;
  168. }
  169. }
  170. template <class T>
  171. void AVLTree<T>::postOrder()
  172. {
  173. postOrder(mRoot);
  174. }
  175. /*
  176. * (递归实现)查找"AVL树x"中键值为key的节点
  177. */
  178. template <class T>
  179. AVLTreeNode<T>* AVLTree<T>::search(AVLTreeNode<T>* x, T key) const
  180. {
  181. if (x==NULL || x->key==key)
  182. return x;
  183. if (key < x->key)
  184. return search(x->left, key);
  185. else
  186. return search(x->right, key);
  187. }
  188. template <class T>
  189. AVLTreeNode<T>* AVLTree<T>::search(T key)
  190. {
  191. return search(mRoot, key);
  192. }
  193. /*
  194. * (非递归实现)查找"AVL树x"中键值为key的节点
  195. */
  196. template <class T>
  197. AVLTreeNode<T>* AVLTree<T>::iterativeSearch(AVLTreeNode<T>* x, T key) const
  198. {
  199. while ((x!=NULL) && (x->key!=key))
  200. {
  201. if (key < x->key)
  202. x = x->left;
  203. else
  204. x = x->right;
  205. }
  206. return x;
  207. }
  208. template <class T>
  209. AVLTreeNode<T>* AVLTree<T>::iterativeSearch(T key)
  210. {
  211. return iterativeSearch(mRoot, key);
  212. }
  213. /*
  214. * 查找最小结点:返回tree为根结点的AVL树的最小结点。
  215. */
  216. template <class T>
  217. AVLTreeNode<T>* AVLTree<T>::minimum(AVLTreeNode<T>* tree)
  218. {
  219. if (tree == NULL)
  220. return NULL;
  221. while(tree->left != NULL)
  222. tree = tree->left;
  223. return tree;
  224. }
  225. template <class T>
  226. T AVLTree<T>::minimum()
  227. {
  228. AVLTreeNode<T> *p = minimum(mRoot);
  229. if (p != NULL)
  230. return p->key;
  231. return (T)NULL;
  232. }
  233. /*
  234. * 查找最大结点:返回tree为根结点的AVL树的最大结点。
  235. */
  236. template <class T>
  237. AVLTreeNode<T>* AVLTree<T>::maximum(AVLTreeNode<T>* tree)
  238. {
  239. if (tree == NULL)
  240. return NULL;
  241. while(tree->right != NULL)
  242. tree = tree->right;
  243. return tree;
  244. }
  245. template <class T>
  246. T AVLTree<T>::maximum()
  247. {
  248. AVLTreeNode<T> *p = maximum(mRoot);
  249. if (p != NULL)
  250. return p->key;
  251. return (T)NULL;
  252. }
  253. /*
  254. * LL:左左对应的情况(左单旋转)。
  255. *
  256. * 返回值:旋转后的根节点
  257. */
  258. template <class T>
  259. AVLTreeNode<T>* AVLTree<T>::leftLeftRotation(AVLTreeNode<T>* k2)
  260. {
  261. AVLTreeNode<T>* k1;
  262. k1 = k2->left;
  263. k2->left = k1->right;
  264. k1->right = k2;
  265. k2->height = max( height(k2->left), height(k2->right)) + 1;
  266. k1->height = max( height(k1->left), k2->height) + 1;
  267. return k1;
  268. }
  269. /*
  270. * RR:右右对应的情况(右单旋转)。
  271. *
  272. * 返回值:旋转后的根节点
  273. */
  274. template <class T>
  275. AVLTreeNode<T>* AVLTree<T>::rightRightRotation(AVLTreeNode<T>* k1)
  276. {
  277. AVLTreeNode<T>* k2;
  278. k2 = k1->right;
  279. k1->right = k2->left;
  280. k2->left = k1;
  281. k1->height = max( height(k1->left), height(k1->right)) + 1;
  282. k2->height = max( height(k2->right), k1->height) + 1;
  283. return k2;
  284. }
  285. /*
  286. * LR:左右对应的情况(左双旋转)。
  287. *
  288. * 返回值:旋转后的根节点
  289. */
  290. template <class T>
  291. AVLTreeNode<T>* AVLTree<T>::leftRightRotation(AVLTreeNode<T>* k3)
  292. {
  293. k3->left = rightRightRotation(k3->left);
  294. return leftLeftRotation(k3);
  295. }
  296. /*
  297. * RL:右左对应的情况(右双旋转)。
  298. *
  299. * 返回值:旋转后的根节点
  300. */
  301. template <class T>
  302. AVLTreeNode<T>* AVLTree<T>::rightLeftRotation(AVLTreeNode<T>* k1)
  303. {
  304. k1->right = leftLeftRotation(k1->right);
  305. return rightRightRotation(k1);
  306. }
  307. /*
  308. * 将结点插入到AVL树中,并返回根节点
  309. *
  310. * 参数说明:
  311. * tree AVL树的根结点
  312. * key 插入的结点的键值
  313. * 返回值:
  314. * 根节点
  315. */
  316. template <class T>
  317. AVLTreeNode<T>* AVLTree<T>::insert(AVLTreeNode<T>* &tree, T key)
  318. {
  319. if (tree == NULL)
  320. {
  321. // 新建节点
  322. tree = new AVLTreeNode<T>(key, NULL, NULL);
  323. if (tree==NULL)
  324. {
  325. cout << "ERROR: create avltree node failed!" << endl;
  326. return NULL;
  327. }
  328. }
  329. else if (key < tree->key) // 应该将key插入到"tree的左子树"的情况
  330. {
  331. tree->left = insert(tree->left, key);
  332. // 插入节点后,若AVL树失去平衡,则进行相应的调节。
  333. if (height(tree->left) - height(tree->right) == 2)
  334. {
  335. if (key < tree->left->key)
  336. tree = leftLeftRotation(tree);
  337. else
  338. tree = leftRightRotation(tree);
  339. }
  340. }
  341. else if (key > tree->key) // 应该将key插入到"tree的右子树"的情况
  342. {
  343. tree->right = insert(tree->right, key);
  344. // 插入节点后,若AVL树失去平衡,则进行相应的调节。
  345. if (height(tree->right) - height(tree->left) == 2)
  346. {
  347. if (key > tree->right->key)
  348. tree = rightRightRotation(tree);
  349. else
  350. tree = rightLeftRotation(tree);
  351. }
  352. }
  353. else //key == tree->key)
  354. {
  355. cout << "添加失败:不允许添加相同的节点!" << endl;
  356. }
  357. tree->height = max( height(tree->left), height(tree->right)) + 1;
  358. return tree;
  359. }
  360. template <class T>
  361. void AVLTree<T>::insert(T key)
  362. {
  363. insert(mRoot, key);
  364. }
  365. /*
  366. * 删除结点(z),返回根节点
  367. *
  368. * 参数说明:
  369. * tree AVL树的根结点
  370. * z 待删除的结点
  371. * 返回值:
  372. * 根节点
  373. */
  374. template <class T>
  375. AVLTreeNode<T>* AVLTree<T>::remove(AVLTreeNode<T>* &tree, AVLTreeNode<T>* z)
  376. {
  377. // 根为空 或者 没有要删除的节点,直接返回NULL。
  378. if (tree==NULL || z==NULL)
  379. return NULL;
  380. if (z->key < tree->key) // 待删除的节点在"tree的左子树"中
  381. {
  382. tree->left = remove(tree->left, z);
  383. // 删除节点后,若AVL树失去平衡,则进行相应的调节。
  384. if (height(tree->right) - height(tree->left) == 2)
  385. {
  386. AVLTreeNode<T> *r = tree->right;
  387. if (height(r->left) > height(r->right))
  388. tree = rightLeftRotation(tree);
  389. else
  390. tree = rightRightRotation(tree);
  391. }
  392. }
  393. else if (z->key > tree->key)// 待删除的节点在"tree的右子树"中
  394. {
  395. tree->right = remove(tree->right, z);
  396. // 删除节点后,若AVL树失去平衡,则进行相应的调节。
  397. if (height(tree->left) - height(tree->right) == 2)
  398. {
  399. AVLTreeNode<T> *l = tree->left;
  400. if (height(l->right) > height(l->left))
  401. tree = leftRightRotation(tree);
  402. else
  403. tree = leftLeftRotation(tree);
  404. }
  405. }
  406. else // tree是对应要删除的节点。
  407. {
  408. // tree的左右孩子都非空
  409. if ((tree->left!=NULL) && (tree->right!=NULL))
  410. {
  411. if (height(tree->left) > height(tree->right))
  412. {
  413. // 如果tree的左子树比右子树高;
  414. // 则(01)找出tree的左子树中的最大节点
  415. // (02)将该最大节点的值赋值给tree。
  416. // (03)删除该最大节点。
  417. // 这类似于用"tree的左子树中最大节点"做"tree"的替身;
  418. // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
  419. AVLTreeNode<T>* max = maximum(tree->left);
  420. tree->key = max->key;
  421. tree->left = remove(tree->left, max);
  422. }
  423. else
  424. {
  425. // 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
  426. // 则(01)找出tree的右子树中的最小节点
  427. // (02)将该最小节点的值赋值给tree。
  428. // (03)删除该最小节点。
  429. // 这类似于用"tree的右子树中最小节点"做"tree"的替身;
  430. // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
  431. AVLTreeNode<T>* min = maximum(tree->right);
  432. tree->key = min->key;
  433. tree->right = remove(tree->right, min);
  434. }
  435. }
  436. else
  437. {
  438. AVLTreeNode<T>* tmp = tree;
  439. tree = (tree->left!=NULL) ? tree->left : tree->right;
  440. delete tmp;
  441. }
  442. }
  443. return tree;
  444. }
  445. template <class T>
  446. void AVLTree<T>::remove(T key)
  447. {
  448. AVLTreeNode<T>* z;
  449. if ((z = search(mRoot, key)) != NULL)
  450. mRoot = remove(mRoot, z);
  451. }
  452. /*
  453. * 销毁AVL树
  454. */
  455. template <class T>
  456. void AVLTree<T>::destroy(AVLTreeNode<T>* &tree)
  457. {
  458. if (tree==NULL)
  459. return ;
  460. if (tree->left != NULL)
  461. destroy(tree->left);
  462. if (tree->right != NULL)
  463. destroy(tree->right);
  464. delete tree;
  465. }
  466. template <class T>
  467. void AVLTree<T>::destroy()
  468. {
  469. destroy(mRoot);
  470. }
  471. /*
  472. * 打印"二叉查找树"
  473. *
  474. * key -- 节点的键值
  475. * direction -- 0,表示该节点是根节点;
  476. * -1,表示该节点是它的父结点的左孩子;
  477. * 1,表示该节点是它的父结点的右孩子。
  478. */
  479. template <class T>
  480. void AVLTree<T>::print(AVLTreeNode<T>* tree, T key, int direction)
  481. {
  482. if(tree != NULL)
  483. {
  484. if(direction==0) // tree是根节点
  485. cout << setw(2) << tree->key << " is root" << endl;
  486. else // tree是分支节点
  487. cout << setw(2) << tree->key << " is " << setw(2) << key << "'s " << setw(12) << (direction==1?"right child" : "left child") << endl;
  488. print(tree->left, tree->key, -1);
  489. print(tree->right,tree->key, 1);
  490. }
  491. }
  492. template <class T>
  493. void AVLTree<T>::print()
  494. {
  495. if (mRoot != NULL)
  496. print(mRoot, mRoot->key, 0);
  497. }
  498. #endif

测试代码

  1. /**
  2. * C 语言: AVL树
  3. *
  4. * @author skywang
  5. * @date 2013/11/07
  6. */
  7. #include <iostream>
  8. #include "start.h"
  9. using namespace std;
  10. static int arr[]= {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
  11. #define TBL_SIZE(a) ( (sizeof(a)) / (sizeof(a[0])) )
  12. int main()
  13. {
  14. int i,ilen;
  15. AVLTree<int>* tree=new AVLTree<int>();
  16. cout << "== 依次添加: ";
  17. ilen = TBL_SIZE(arr);
  18. for(i=0; i<ilen; i++)
  19. {
  20. cout << arr[i] <<" ";
  21. tree->insert(arr[i]);
  22. }
  23. cout << "\n== 前序遍历: ";
  24. tree->preOrder();
  25. cout << "\n== 中序遍历: ";
  26. tree->inOrder();
  27. cout << "\n== 后序遍历: ";
  28. tree->postOrder();
  29. cout << endl;
  30. cout << "== 高度: " << tree->height() << endl;
  31. cout << "== 最小值: " << tree->minimum() << endl;
  32. cout << "== 最大值: " << tree->maximum() << endl;
  33. cout << "== 树的详细信息: " << endl;
  34. tree->print();
  35. i = 8;
  36. cout << "\n== 删除根节点: " << i;
  37. tree->remove(i);
  38. cout << "\n== 高度: " << tree->height() ;
  39. cout << "\n== 中序遍历: " ;
  40. tree->inOrder();
  41. cout << "\n== 树的详细信息: " << endl;
  42. tree->print();
  43. // 销毁二叉树
  44. tree->destroy();
  45. system("pause");
  46. return 0;
  47. }

References

AVL树(二)之 C++的实现 - 如果天空不死 - 博客园

效果如下

数据结构之AVL树的更多相关文章

  1. linux 内核数据结构之 avl树.

    转载: http://blog.csdn.net/programmingring/article/details/37969745 https://zh.wikipedia.org/wiki/AVL% ...

  2. [算法] 数据结构之AVL树

    1 .基本概念 AVL树的复杂程度真是比二叉搜索树高了整整一个数量级——它的原理并不难弄懂,但要把它用代码实现出来还真的有点费脑筋.下面我们来看看: 1.1  AVL树是什么? AVL树本质上还是一棵 ...

  3. D&F学数据结构系列——AVL树(平衡二叉树)

    AVL树(带有平衡条件的二叉查找树) 定义:一棵AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树. 为什么要使用AVL树(即为什么要给二叉查找树增加平衡条件),已经在我之前的博文中说到过 ...

  4. [javaSE] 数据结构(AVL树基本概念)

    AVL树是高度平衡的二叉树,任何节点的两个子树的高度差别<=1 实现AVL树 定义一个AVL树,AVLTree,定义AVLTree的节点内部类AVLNode,节点包含以下特性: 1.key——关 ...

  5. 大话数据结构—平衡二叉树(AVL树)

    平衡二叉树(Self-Balancing Binary Search Tree/Height-Balanced Binary Search Tree),是一种二叉排序树,当中每个节点的左子树和右子树的 ...

  6. 二叉树学习笔记之经典平衡二叉树(AVL树)

    二叉查找树(BSTree)中进行查找.插入和删除操作的时间复杂度都是O(h),其中h为树的高度.BST的高度直接影响到操作实现的性能,最坏情况下,二叉查找树会退化成一个单链表,比如插入的节点序列本身就 ...

  7. 经典平衡二叉树(AVL树)

    二叉查找树(BSTree)中进行查找.插入和删除操作的时间复杂度都是O(h),其中h为树的高度.BST的高度直接影响到操作实现的性能,最坏情况下,二叉查找树会退化成一个单链表,比如插入的节点序列本身就 ...

  8. AVL树C++实现

    1. AVL 树本质上还是一棵二叉搜索树,它的特点是: 本身首先是一棵二叉搜索树. 带有平衡条件: 每个结点的左右子树的高度之差的绝对值(平衡因子) 最多为 1. 2. 数据结构定义 AVL树节点类: ...

  9. AVL树(二叉平衡树)详解与实现

    AVL树概念 前面学习二叉查找树和二叉树的各种遍历,但是其查找效率不稳定(斜树),而二叉平衡树的用途更多.查找相比稳定很多.(欢迎关注数据结构专栏) AVL树是带有平衡条件的二叉查找树.这个平衡条件必 ...

随机推荐

  1. 如何开启telnet 23端口

    netstat -tnl|grep 23 查看23端口是否开启 或者 chkconfig --list|grep telnet 检查telnet状态 如果关闭状态, 开启:chkconfig --le ...

  2. .apache2 设置多个虚拟域名

    <VirtualHost 127.0.0.2:80> ServerName www.xylilun.cn DocumentRoot E:/www/ylll <Directory E: ...

  3. 免费的Android UI库及组件推荐

    短短数年时间Android平台就已经形成了一个庞大而活跃的开发者社区.许多社区开发的项目业已进入成熟阶段,甚至可以用于商业的软件生产中,且不用担心质量问题. 本文编译自androiduipattern ...

  4. AChartEngine 安卓折线图 柱形图等利器

    http://www.eoeandroid.com/thread-548233-1-6.html 最近公司项目中要用到折线图,状态类型的图标要用到折线图,柱形图等,并且能够动态显示,在网上找了许多de ...

  5. iOS开发——高级篇——UIDynamic 物理引擎

    一.UIDynamic 1.简介什么是UIDynamicUIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象重力.弹性碰撞 ...

  6. android之inflater用法

    在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById().不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例 ...

  7. 12 哈希表相关类——Live555源码阅读(一)基本组件类

    12 哈希表相关类--Live555源码阅读(一)基本组件类 这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 ...

  8. css position属性

    absolute, 屏幕为参照, 但固定在页面上,随页面滚动而动. fixed, 父元素没有指定position属性(或position属性为static时)==>屏幕为参照,固定在屏幕的某个位 ...

  9. 网页百度地图API相关资料

    百度地图API——网页URI接口.手机网页点击直接导航:js生成一个地图网页 或 直接跳转到百度导航界面 http://developer.baidu.com/map/index.php?title= ...

  10. 【Other】Ubuntu 14.04 pptp 客户端连接配置

    sudo apt-get install pptp-linux binutils modprobe ppp_mppe sudo pptpsetup --create testvpn --server ...