Splay、treap、avl的实现

以下代码全部来自网络,我只是汇总了一下应对面试(sng腾讯云有问到,没答好)

Splay 树

typedef struct SplayNode *Tree;
typedef int ElementType;
struct SplayNode
{
    Tree parent; //该结点的父节点,方便操作
    ElementType val; //结点值
    Tree lchild;
    Tree rchild;
    SplayNode(int val=0) //默认构造函数
    {
      parent=NULL;
      lchild=rchild=NULL;
      this->val=val;
    }
};

Tree left_single_rotate(Tree &root, Tree node) {
  if (node == nullptr)
    return nullptr;
  Tree parent = node->parent;
  Tree grandparent = parent->parent;
  parent->rchild = node->lchild;
  if (node->lchild)
    node->lchild->parent = parent;
  node->lchild = parent;
  parent->parent = node;
  node->parent = grandparent;

  if (grandparent) {
    if (grandparent->lchild == parent) {
      grandparent->lchild = node;
    } else {
      grandparent->rchild = node;
    }
  } else {
    root = node;
  }

  return node;
}
Tree right_single_rotate(Tree &root, Tree node) {
  if (node==NULL)
    return NULL;
  Tree parent,grandparent;
  parent=node->parent;
  grandparent=parent->parent;
  parent->lchild=node->rchild;
  if (node->rchild)
    node->rchild->parent=parent;
  node->rchild=parent;
  parent->parent=node;
  node->parent=grandparent;
  if (grandparent)
  {
    if (grandparent->lchild==parent)
      grandparent->lchild=node;
    else
      grandparent->rchild=node;
  }
  else
    root=node;
  return node;
}

void left_double_rotate(Tree &root, Tree node) {
  left_single_rotate(root, node->parent);
  left_single_rotate(root, node);
}

void right_double_rotate(Tree &root, Tree node) {
  right_single_rotate(root, node->parent);
  right_single_rotate(root, node);
}

void RL_rotate(Tree &root, Tree node) {
  right_single_rotate(root, node);
  left_single_rotate(root, node);
}


void LR_rotate(Tree &root, Tree node) {
  left_single_rotate(root, node);
  right_single_rotate(root, node);
}

bool search(Tree& root, int val) {
  Tree parent = NULL;
  Tree *temp = NULL;
  temp = search_val(root, val, parent);
  if (*temp && *temp != root) {
    SplayTree(root, *temp);
    return true;
  }
  return false;
}

Tree *search_val(Tree &root, ElementType val, Tree &parent) {
  if (root == nullptr) {
    return &root;
  }
  if (root->val > val) {
    return search_val(root->rchild, val, parent=root);
  }  else if (root->val < val) {
    return search_val(root->rchild, val, parent=root);
  }
  return &root;
}

bool insert(Tree &root, ElementType val) {
  Tree *temp = NULL;
  Tree parent = NULL;
  temp = search_val(root, val, parent);

  if (*temp == nullptr) {
    Tree node = new SplayNode(val);
    *temp = node;
    node->parent = parent;
    return true;
  }
  return false;
}

void SplayTree(Tree &root, Tree node) {
  while (root->lchild != node && root->rchild != node&&
          root != node) {
    up(root, node);
  }
  if (root->lchild == node) {
    root = right_single_rotate(root, node);
  } else if (root->rchild == node) {
    root = left_single_rotate(root, node);
  }
}


void up(Tree &root, Tree node) {
  Tree parent, grandparent;
  int i, j;
  parent = node->parent;
  grandparent = parent->parent;
  i = grandparent->lchild == parent ? -1 : 1;
  j = parent->lchild == node ? -1 : 1;
  if (-1 == i && -1 == j) {
    right_double_rotate(root, node);
  } else if (-1 == i && 1 == j) {
    LR_rotate(root, node);
  } else if (1 == i && -1 == j ) {
    RL_rotate(root, node);
  } else {
    left_double_rotate(root, node);
  }
}

void remove(Tree &root, ElementType val) {
  Tree parent = nullptr;
  Tree *temp;
  Tree *replace;
  Tree replace2;
  temp = search_val(root, val, parent);

  if (*temp) {
    if (*temp != root) {
      SplayTree(root, *temp);
    }
    if (root->rchild) {
      replace =Find_Min(root->rchild);
      root->val = (*replace)->val;
      if ((*replace)->lchild == nullptr) {
        replace2 = *replace;
        *replace = (*replace)->rchild;
        delete replace2;
      } else if ((*replace)->rchild == nullptr) {
        replace2 = *replace;
        *replace = (*replace)->lchild;
        delete replace2;
      }
    } else {
      replace2 = root;
      root = root->lchild;
      delete replace2;
    }
  }
}

Tree* Find_Min(Tree &root) {
  if (root->lchild) {
    return Find_Min(root->lchild);
  }
  return &root;
}

特点: 每次查找都会把被查找的元素移动到根部。可能退化为链表,不会保证树一直是平衡的,但各种操作均摊后是O(lgn)。编程难度小,空间要求小。

主要是考虑到局部性的原理,热点数据靠近根部。

原链接: https://blog.csdn.net/u014634338/article/details/49586689

Treap

附加一个priority域,同时满足查找树性质和堆的性质。

原链接: https://blog.csdn.net/k346k346/article/details/50808879

struct Node {
    int key;
    int priority;
    Node* left;
    Node* right;
};
Node* root;
void rotate_left(Node* &node) { // right up, node down
  Node* x = node->right;
  node->right = x->left;
  x->left = node;
  node = x;
}
void rotate_right(Node* &node) { // left up, node down
  Node* x = node->left;
  node->left = x->right;
  x->right = node;
  node = x;
}
void treap_insert(Node* &root, int key, int priority) {
  if (nullptr == root) {
    root = new Node;
    root->left = root->right = nullptr;
    root->priority = priority;
    root->key = key;
    return;
  }
  if (key < root->key) {
    treap_insert(root->left, key, priority);
    if (root->left->priority < root->priority) {
      rotate_right(root);
    }
    return;
  }
  treap_insert(root->right, key, priority);
  if (root->right->priority < root->priority) {
    rotate_left(root);
  }
}
void treap_delete(Node* &root, int key) {
  if (root != nullptr) {
    if (key < root->key) {
      treap_delete(root->left, key);
    } else if (key > root->key) {
      treap_delete(root->right, key);
    } else {
      if (root->left == nullptr) {
        root = root->right; // in a chain
      } else if (root->right == nullptr) {
        root = root->left; // in a chain
      } else {
        if (root->left->priority < root->right->priority) {
          rotate_right(root);
          treap_delete(root->right, key);
        } else {
          rotate_left(root);
          treap_delete(root->left, key);
        }
      }
    }
  }
}

其中需要注意的是,这个实现依赖于引用的技巧,简化版本为,如root->left = treap_delete(root->left, key) 传值而非引用。

AVL树

特点:两子树高度差最多为1,通过LR LL RL RR四种旋转方式来维护高度性质,附加了高度域。

AVL是严格平衡树,在增加和删除节点的时候,根据不同情况,旋转次数要比红黑树多。

红黑树非平衡,旋转次数少。

如果你的应用中,搜索远大于插入和删除,那么选择AVL,如果搜索插入删除差不多,使用RB。

原链接: https://www.cnblogs.com/skywang12345/p/3576969.html

struct Node {
    int key;
    int height;
    Node* left;
    Node* right;
};

#define MAX(a, b)    ( (a) > (b) ? (a) : (b) )

int avltree_height(Node *root) {
  if (root == nullptr) return -1;
  return root->height;
}

Node* search(Node* root, int key) {
  if (root == nullptr || root->key == key) {
    return root;
  }
  if (key < root->key) {
    return search(root->left, key);
  } else {
    return search(root->right, key);
  }
}

Node* minnode(Node* root) {
  if (root == nullptr) return nullptr;
  while (root->left != nullptr) {
    root = root->left;
  }
  return root;
}


Node* maxnode(Node* root) {
  if (root == nullptr) {
    return root;
  }
  while (root->right) {
    root = root->right;
  }
  return root;
}


Node* LL(Node* root) {
  Node* k1;

  k1 = root->left;
  root->left = k1->right;
  k1->right = root;

  root->height = MAX(avltree_height(root->left), avltree_height(root->right))
                 + 1;
  k1->height = MAX(avltree_height(k1->left), avltree_height(k1->right)) + 1;

  return k1;
}


Node* RR(Node* k1) {
  Node* k2;
  k2 = k1->right;
  k1->right = k2->left;
  k2->left = k1;

  k1->height = MAX( avltree_height(k1->left), avltree_height(k1->right)) + 1;
  k2->height = MAX( avltree_height(k2->right), k1->height) + 1;
  return k2;
}

Node* LR(Node* k3) {
  k3->left = RR(k3->left);

  return RR(k3);
}


Node* RL(Node* k1) {
  k1->right = LL(k1->right);
  return RR(k1);
}

Node* create(int key, Node* left, Node* right) {
  Node *p;

  p = new Node;
  p->key = key;
  p->height = 0;
  p->left = left;
  p->right = right;

  return p;
}

Node* avl_insert(Node* tree, int key) {
  if (tree == nullptr) {
    tree = create(key, nullptr, nullptr);
  } else if (key < tree->key) {
    tree->left = avl_insert(tree->left, key);
    if (avltree_height(tree->left) - avltree_height(tree->right) == 2) {
      if (key < tree->left->key) {
        tree = LL(tree);
      } else {
        tree = LR(tree);
      }
    }
  } else if (key > tree->key) {
    tree->right = avl_insert(tree->right, key);
    if (avltree_height(tree->right) - avltree_height(tree->left) == 2) {
      if (key > tree->right->key) {
        tree = RR(tree);
      } else {
        tree = RL(tree);
      }
    }
  }

  tree->height = MAX(avltree_height(tree->left), avltree_height(tree->right))
                 + 1;
  return tree;
}

Node* avldelete(Node* tree, Node* z) {
  if (tree == nullptr || z == nullptr) {
    return nullptr;
  }
  if (z->key < tree->key) {
    tree->left = avldelete(tree->left, z);
    if (avltree_height(tree->right) - avltree_height(tree->left) == 2) {
      Node *r = tree->right;
      if (avltree_height(r->left) > avltree_height(r->right)) {
        tree = RL(tree);
      } else {
        tree = RR(tree);
      }
    }
  } else if (z->key > tree->key) {
    tree->right = avldelete(tree->right, z);
    if (avltree_height(tree->left) - avltree_height(tree->right) == 2) {
      Node *l = tree->left;
      if (avltree_height(l->right) > avltree_height(l->left)) {
        tree = LR(tree);
      } else {
        tree = LL(tree);
      }
    }
  } else {
    if (tree->left && tree->right) {
      if (avltree_height(tree->left) > avltree_height(tree->right)) {
        Node* max = maxnode(tree->left);
        tree->key = max->key;
        tree->left = avldelete(tree->left, max);
      } else {
        Node *min = minnode(tree->right);
        tree->key = min->key;
        tree->right = avldelete(tree->right, min);
      }
    } else {
      Node *tmp = tree;
      tree = tree->left ? tree->left : tree->right;
      delete tmp;
    }
  }

  return tree;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值