Arbre à évaser. Chercher

Bonjour, Habr! Nous invitons les futurs étudiants du cours "Algorithmes et structures de données" à un webinaire ouvert sur le thème "Réserves d'arbres de recherche binaires".



Et maintenant, nous partageons avec vous la traduction traditionnelle de documents utiles.






, , , (Binary Search Tree) O(n). , . O(log n) - -.





, , - -?





- -, Splay- ( ) . splay- , , , , , O(1) . , ( 80% 20% ). , , , .





splay- O(log n), n - . (n).





 

splay- , ( — splay). , . , NULL.





:





1. . , , , , .





2. Zig: ( ). ( ), ( ).





T1, T2 T3 — y () x ()





3. , . :





) Zig-Zig Zag-Zag. , ( ) , ( ).





) Zig-Zag Zag-Zig. , ( ) , ( ).





:





, (splay) , . , 1.





:

C++

#include <bits/stdc++.h> 
using namespace std; 

// An AVL tree node 
class node 
{ 
	public: 
	int key; 
	node *left, *right; 
}; 

/* Helper function that allocates 
a new node with the given key and 
	NULL left and right pointers. */
node* newNode(int key) 
{ 
	node* Node = new node(); 
	Node->key = key; 
	Node->left = Node->right = NULL; 
	return (Node); 
} 

// A utility function to right 
// rotate subtree rooted with y 
// See the diagram given above. 
node *rightRotate(node *x) 
{ 
	node *y = x->left; 
	x->left = y->right; 
	y->right = x; 
	return y; 
} 

// A utility function to left 
// rotate subtree rooted with x 
// See the diagram given above. 
node *leftRotate(node *x) 
{ 
	node *y = x->right; 
	x->right = y->left; 
	y->left = x; 
	return y; 
} 

// This function brings the key at 
// root if key is present in tree. 
// If key is not present, then it 
// brings the last accessed item at 
// root. This function modifies the 
// tree and returns the new root 
node *splay(node *root, int key) 
{ 
	// Base cases: root is NULL or 
	// key is present at root 
	if (root == NULL || root->key == key) 
		return root; 

	// Key lies in left subtree 
	if (root->key > key) 
	{ 
		// Key is not in tree, we are done 
		if (root->left == NULL) return root; 

		// Zig-Zig (Left Left) 
		if (root->left->key > key) 
		{ 
			// First recursively bring the 
			// key as root of left-left 
			root->left->left = splay(root->left->left, key); 

			// Do first rotation for root, 
			// second rotation is done after else 
			root = rightRotate(root); 
		} 
		else if (root->left->key < key) // Zig-Zag (Left Right) 
		{ 
			// First recursively bring 
			// the key as root of left-right 
			root->left->right = splay(root->left->right, key); 

			// Do first rotation for root->left 
			if (root->left->right != NULL) 
				root->left = leftRotate(root->left); 
		} 

		// Do second rotation for root 
		return (root->left == NULL)? root: rightRotate(root); 
	} 
	else // Key lies in right subtree 
	{ 
		// Key is not in tree, we are done 
		if (root->right == NULL) return root; 

		// Zag-Zig (Right Left) 
		if (root->right->key > key) 
		{ 
			// Bring the key as root of right-left 
			root->right->left = splay(root->right->left, key); 

			// Do first rotation for root->right 
			if (root->right->left != NULL) 
				root->right = rightRotate(root->right); 
		} 
		else if (root->right->key < key)// Zag-Zag (Right Right) 
		{ 
			// Bring the key as root of 
			// right-right and do first rotation 
			root->right->right = splay(root->right->right, key); 
			root = leftRotate(root); 
		} 

		// Do second rotation for root 
		return (root->right == NULL)? root: leftRotate(root); 
	} 
} 

// The search function for Splay tree. 
// Note that this function returns the 
// new root of Splay Tree. If key is 
// present in tree then, it is moved to root. 
node *search(node *root, int key) 
{ 
	return splay(root, key); 
} 

// A utility function to print 
// preorder traversal of the tree. 
// The function also prints height of every node 
void preOrder(node *root) 
{ 
	if (root != NULL) 
	{ 
		cout<<root->key<<" "; 
		preOrder(root->left); 
		preOrder(root->right); 
	} 
} 

/* Driver code*/
int main() 
{ 
	node *root = newNode(100); 
	root->left = newNode(50); 
	root->right = newNode(200); 
	root->left->left = newNode(40); 
	root->left->left->left = newNode(30); 
	root->left->left->left->left = newNode(20); 

	root = search(root, 20); 
	cout << "Preorder traversal of the modified Splay tree is \n"; 
	preOrder(root); 
	return 0; 
} 

// This code is contributed by rathbhupendra 
      
      



C

// The code is adopted from http://goo.gl/SDH9hH 
#include<stdio.h> 
#include<stdlib.h> 

// An AVL tree node 
struct node 
{ 
	int key; 
	struct node *left, *right; 
}; 

/* Helper function that allocates a new node with the given key and 
	NULL left and right pointers. */
struct node* newNode(int key) 
{ 
	struct node* node = (struct node*)malloc(sizeof(struct node)); 
	node->key = key; 
	node->left = node->right = NULL; 
	return (node); 
} 

// A utility function to right rotate subtree rooted with y 
// See the diagram given above. 
struct node *rightRotate(struct node *x) 
{ 
	struct node *y = x->left; 
	x->left = y->right; 
	y->right = x; 
	return y; 
} 

// A utility function to left rotate subtree rooted with x 
// See the diagram given above. 
struct node *leftRotate(struct node *x) 
{ 
	struct node *y = x->right; 
	x->right = y->left; 
	y->left = x; 
	return y; 
} 

// This function brings the key at root if key is present in tree. 
// If key is not present, then it brings the last accessed item at 
// root. This function modifies the tree and returns the new root 
struct node *splay(struct node *root, int key) 
{ 
	// Base cases: root is NULL or key is present at root 
	if (root == NULL || root->key == key) 
		return root; 

	// Key lies in left subtree 
	if (root->key > key) 
	{ 
		// Key is not in tree, we are done 
		if (root->left == NULL) return root; 

		// Zig-Zig (Left Left) 
		if (root->left->key > key) 
		{ 
			// First recursively bring the key as root of left-left 
			root->left->left = splay(root->left->left, key); 

			// Do first rotation for root, second rotation is done after else 
			root = rightRotate(root); 
		} 
		else if (root->left->key < key) // Zig-Zag (Left Right) 
		{ 
			// First recursively bring the key as root of left-right 
			root->left->right = splay(root->left->right, key); 

			// Do first rotation for root->left 
			if (root->left->right != NULL) 
				root->left = leftRotate(root->left); 
		} 

		// Do second rotation for root 
		return (root->left == NULL)? root: rightRotate(root); 
	} 
	else // Key lies in right subtree 
	{ 
		// Key is not in tree, we are done 
		if (root->right == NULL) return root; 

		// Zag-Zig (Right Left) 
		if (root->right->key > key) 
		{ 
			// Bring the key as root of right-left 
			root->right->left = splay(root->right->left, key); 

			// Do first rotation for root->right 
			if (root->right->left != NULL) 
				root->right = rightRotate(root->right); 
		} 
		else if (root->right->key < key)// Zag-Zag (Right Right) 
		{ 
			// Bring the key as root of right-right and do first rotation 
			root->right->right = splay(root->right->right, key); 
			root = leftRotate(root); 
		} 

		// Do second rotation for root 
		return (root->right == NULL)? root: leftRotate(root); 
	} 
} 

// The search function for Splay tree. Note that this function 
// returns the new root of Splay Tree. If key is present in tree 
// then, it is moved to root. 
struct node *search(struct node *root, int key) 
{ 
	return splay(root, key); 
} 

// A utility function to print preorder traversal of the tree. 
// The function also prints height of every node 
void preOrder(struct node *root) 
{ 
	if (root != NULL) 
	{ 
		printf("%d ", root->key); 
		preOrder(root->left); 
		preOrder(root->right); 
	} 
} 

/* Driver program to test above function*/
int main() 
{ 
	struct node *root = newNode(100); 
	root->left = newNode(50); 
	root->right = newNode(200); 
	root->left->left = newNode(40); 
	root->left->left->left = newNode(30); 
	root->left->left->left->left = newNode(20); 

	root = search(root, 20); 
	printf("Preorder traversal of the modified Splay tree is \n"); 
	preOrder(root); 
	return 0; 
} 

      
      



Java

// Java implementation for above approach 
class GFG 
{ 

// An AVL tree node 
static class node 
{ 

	int key; 
	node left, right; 
}; 

/* Helper function that allocates 
a new node with the given key and 
	null left and right pointers. */
static node newNode(int key) 
{ 
	node Node = new node(); 
	Node.key = key; 
	Node.left = Node.right = null; 
	return (Node); 
} 

// A utility function to right 
// rotate subtree rooted with y 
// See the diagram given above. 
static node rightRotate(node x) 
{ 
	node y = x.left; 
	x.left = y.right; 
	y.right = x; 
	return y; 
} 

// A utility function to left 
// rotate subtree rooted with x 
// See the diagram given above. 
static node leftRotate(node x) 
{ 
	node y = x.right; 
	x.right = y.left; 
	y.left = x; 
	return y; 
} 

// This function brings the key at 
// root if key is present in tree. 
// If key is not present, then it 
// brings the last accessed item at 
// root. This function modifies the 
// tree and returns the new root 
static node splay(node root, int key) 
{ 
	// Base cases: root is null or 
	// key is present at root 
	if (root == null || root.key == key) 
		return root; 

	// Key lies in left subtree 
	if (root.key > key) 
	{ 
		// Key is not in tree, we are done 
		if (root.left == null) return root; 

		// Zig-Zig (Left Left) 
		if (root.left.key > key) 
		{ 
			// First recursively bring the 
			// key as root of left-left 
			root.left.left = splay(root.left.left, key); 

			// Do first rotation for root, 
			// second rotation is done after else 
			root = rightRotate(root); 
		} 
		else if (root.left.key < key) // Zig-Zag (Left Right) 
		{ 
			// First recursively bring 
			// the key as root of left-right 
			root.left.right = splay(root.left.right, key); 

			// Do first rotation for root.left 
			if (root.left.right != null) 
				root.left = leftRotate(root.left); 
		} 

		// Do second rotation for root 
		return (root.left == null) ? 
							root : rightRotate(root); 
	} 
	else // Key lies in right subtree 
	{ 
		// Key is not in tree, we are done 
		if (root.right == null) return root; 

		// Zag-Zig (Right Left) 
		if (root.right.key > key) 
		{ 
			// Bring the key as root of right-left 
			root.right.left = splay(root.right.left, key); 

			// Do first rotation for root.right 
			if (root.right.left != null) 
				root.right = rightRotate(root.right); 
		} 
		else if (root.right.key < key)// Zag-Zag (Right Right) 
		{ 
			// Bring the key as root of 
			// right-right and do first rotation 
			root.right.right = splay(root.right.right, key); 
			root = leftRotate(root); 
		} 

		// Do second rotation for root 
		return (root.right == null) ? 
							root : leftRotate(root); 
	} 
} 

// The search function for Splay tree. 
// Note that this function returns the 
// new root of Splay Tree. If key is 
// present in tree then, it is moved to root. 
static node search(node root, int key) 
{ 
	return splay(root, key); 
} 

// A utility function to print 
// preorder traversal of the tree. 
// The function also prints height of every node 
static void preOrder(node root) 
{ 
	if (root != null) 
	{ 
		System.out.print(root.key + " "); 
		preOrder(root.left); 
		preOrder(root.right); 
	} 
} 

// Driver code 
public static void main(String[] args) 
{ 
	node root = newNode(100); 
	root.left = newNode(50); 
	root.right = newNode(200); 
	root.left.left = newNode(40); 
	root.left.left.left = newNode(30); 
	root.left.left.left.left = newNode(20); 

	root = search(root, 20); 
	System.out.print("Preorder traversal of the" + 
					" modified Splay tree is \n"); 
	preOrder(root); 
} 
} 

// This code is contributed by 29AjayKumar 

      
      



C#

// C# implementation for above approach 
using System; 

class GFG 
{ 

// An AVL tree node 
public class node 
{ 

	public int key; 
	public node left, right; 
}; 

/* Helper function that allocates 
a new node with the given key and 
null left and right pointers. */
static node newNode(int key) 
{ 
	node Node = new node(); 
	Node.key = key; 
	Node.left = Node.right = null; 
	return (Node); 
} 

// A utility function to right 
// rotate subtree rooted with y 
// See the diagram given above. 
static node rightRotate(node x) 
{ 
	node y = x.left; 
	x.left = y.right; 
	y.right = x; 
	return y; 
} 

// A utility function to left 
// rotate subtree rooted with x 
// See the diagram given above. 
static node leftRotate(node x) 
{ 
	node y = x.right; 
	x.right = y.left; 
	y.left = x; 
	return y; 
} 

// This function brings the key at 
// root if key is present in tree. 
// If key is not present, then it 
// brings the last accessed item at 
// root. This function modifies the 
// tree and returns the new root 
static node splay(node root, int key) 
{ 
	// Base cases: root is null or 
	// key is present at root 
	if (root == null || root.key == key) 
		return root; 

	// Key lies in left subtree 
	if (root.key > key) 
	{ 
		// Key is not in tree, we are done 
		if (root.left == null) return root; 

		// Zig-Zig (Left Left) 
		if (root.left.key > key) 
		{ 
			// First recursively bring the 
			// key as root of left-left 
			root.left.left = splay(root.left.left, key); 

			// Do first rotation for root, 
			// second rotation is done after else 
			root = rightRotate(root); 
		} 
		else if (root.left.key < key) // Zig-Zag (Left Right) 
		{ 
			// First recursively bring 
			// the key as root of left-right 
			root.left.right = splay(root.left.right, key); 

			// Do first rotation for root.left 
			if (root.left.right != null) 
				root.left = leftRotate(root.left); 
		} 

		// Do second rotation for root 
		return (root.left == null) ? 
							root : rightRotate(root); 
	} 
	else // Key lies in right subtree 
	{ 
		// Key is not in tree, we are done 
		if (root.right == null) return root; 

		// Zag-Zig (Right Left) 
		if (root.right.key > key) 
		{ 
			// Bring the key as root of right-left 
			root.right.left = splay(root.right.left, key); 

			// Do first rotation for root.right 
			if (root.right.left != null) 
				root.right = rightRotate(root.right); 
		} 
		else if (root.right.key < key)// Zag-Zag (Right Right) 
		{ 
			// Bring the key as root of 
			// right-right and do first rotation 
			root.right.right = splay(root.right.right, key); 
			root = leftRotate(root); 
		} 

		// Do second rotation for root 
		return (root.right == null) ? 
							root : leftRotate(root); 
	} 
} 

// The search function for Splay tree. 
// Note that this function returns the 
// new root of Splay Tree. If key is 
// present in tree then, it is moved to root. 
static node search(node root, int key) 
{ 
	return splay(root, key); 
} 

// A utility function to print 
// preorder traversal of the tree. 
// The function also prints height of every node 
static void preOrder(node root) 
{ 
	if (root != null) 
	{ 
		Console.Write(root.key + " "); 
		preOrder(root.left); 
		preOrder(root.right); 
	} 
} 

// Driver code 
public static void Main(String[] args) 
{ 
	node root = newNode(100); 
	root.left = newNode(50); 
	root.right = newNode(200); 
	root.left.left = newNode(40); 
	root.left.left.left = newNode(30); 
	root.left.left.left.left = newNode(20); 

	root = search(root, 20); 
	Console.Write("Preorder traversal of the" + 
				" modified Splay tree is \n"); 
	preOrder(root); 
} 
} 

// This code is contributed by 29AjayKumar 
      
      



:





Preorder traversal of the modified Splay tree is 20 50 30 40 100 200







1) Splay- . . .





2) splay- O(log n). , Splay- O(log n) ( , )





3) Splay- - -, splay- .





4) -, splay- , .





Splay-

Splay- , 30 , .





Splay- Windows NT ( , ), gcc GNU C++, sed, Fore Systems, Unix malloc, Linux (: http://www.cs.berkeley.edu/~jrs/61b/lec/36)





Splay Tree | Set 2 (Insert).





:





http://www.cs.berkeley.edu/~jrs/61b/lec/36





http://www.cs.cornell.edu/courses/cs3110/2009fa/recitations/rec-splay.html





http://courses.cs.washington.edu/courses/cse326/01au/lectures/SplayTrees.ppt






" ".



" ."









OTUS . .   OTUS.





, " " -   .












All Articles