以下代码全部来自网络,我只是汇总了一下应对面试(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; }