AVL树(AVL树的中序遍历一定是有序序列)

avl树是一种自平衡二叉搜索树
在avl树中,任何节点的两个子树的高度最多相差1个
如果某个时间,某节点的两个子树之间的高度差超过1,则将通过树旋转进行重新平衡以恢复此属性,这里的旋转有两种方式,左旋和右旋,两者组合后又有两种方式,先左旋后右旋和 先右旋后左旋,所以总共有4种操作。

四种操作

image.png

image.png
构建一颗二叉搜索树dfdafda

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 30;
  4. int n,v[N],idx,l[N],r[N];
  5. void insert(int &u,int w){
  6. if(!u) u = ++idx,v[u]=w;
  7. else if(v[u]<w){
  8. insert(l[u],w);
  9. }
  10. else{
  11. insert(r[u],w);
  12. }
  13. }
  14. int main(){
  15. cin>>n;
  16. int root = 0;
  17. for(int i=0;i<n;i++){
  18. int w;
  19. cin>>w;
  20. insert(root,w);
  21. }
  22. cout<<v[root];
  23. return 0;
  24. }

添加平衡条件

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 30;
  4. int n,v[N],idx,l[N],r[N],h[N];
  5. void update(int u)
  6. {
  7. h[u] = max(h[l[u]], h[r[u]]) + 1;
  8. }
  9. void R(int& u)
  10. {
  11. int p = l[u];
  12. l[u] = r[p], r[p] = u;
  13. update(u);
  14. u = p;
  15. }
  16. void L(int& u)
  17. {
  18. int p = r[u];
  19. r[u] = l[p], l[p] = u;
  20. update(u);
  21. u = p;
  22. }
  23. int get_balance(int u)
  24. {
  25. return h[l[u]] - h[r[u]];
  26. }
  27. void insert(int& u, int w)
  28. {
  29. if (!u) u = ++ idx, v[u] = w;
  30. else if (w < v[u])
  31. {
  32. insert(l[u], w);
  33. if (get_balance(u) == 2)
  34. {
  35. if (get_balance(l[u]) == 1) R(u);
  36. else L(l[u]), R(u);
  37. }
  38. }
  39. else
  40. {
  41. insert(r[u], w);
  42. if (get_balance(u) == -2)
  43. {
  44. if (get_balance(r[u]) == -1) L(u);
  45. else R(r[u]), L(u);
  46. }
  47. }
  48. update(u);
  49. }
  50. int main(){
  51. cin>>n;
  52. int root = 0;
  53. for(int i=0;i<n;i++){
  54. int w;
  55. cin>>w;
  56. insert(root,w);
  57. }
  58. cout<<v[root];
  59. return 0;
  60. }

红黑树

数据结构中有一类特殊的平衡二叉搜索树,称为红黑树
满足下面的性质

  • 节点是红色或黑色
  • 根节点是黑色
  • 每个红色节点的两个子节点都是黑色
  • 从任一节点到每个叶子的所有路径包含相同数目的黑色节点

image.png
image.png

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N = 40;
  4. unordered_map <int,int> pos;
  5. int pre[N],in[N];
  6. bool ans;
  7. int build(int il, int ir, int pl, int pr, int& sum)
  8. {
  9. int root = pre[pl];
  10. int k = pos[abs(root)];
  11. if (k < il || k > ir)
  12. {
  13. ans = false;
  14. return 0;
  15. }
  16. int left = 0, right = 0, ls = 0, rs = 0;
  17. if (il < k) left = build(il, k - 1, pl + 1, pl + 1 + k - 1 - il, ls);
  18. if (k < ir) right = build(k + 1, ir, pl + 1 + k - 1 - il + 1, pr, rs);
  19. if (ls != rs) ans = false;
  20. sum = ls;
  21. if (root < 0)
  22. {
  23. if (left < 0 || right < 0) ans = false;
  24. }
  25. else sum ++ ;
  26. return root;
  27. }
  28. int main(){
  29. int T;
  30. cin>>T;
  31. while(T--){
  32. int n;
  33. cin>>n;
  34. pos.clear();
  35. for(int i=0;i<n;i++){
  36. cin>>pre[i];
  37. in[i] = abs(pre[i]);
  38. }
  39. sort(in,in+n);
  40. for(int i=0;i<n;i++){
  41. pos[in[i]] = i;
  42. }
  43. ans = true;
  44. int sum;
  45. int root = build(0,n-1,0,n-1,sum);
  46. if(root<0) ans = false;
  47. if(ans) puts("Yes");
  48. else puts("No");
  49. }
  50. return 0;
  51. }