treap实现

简介

Treap=Tree+Heap。Treap本身是一棵二叉搜索树,它的左子树和右子树也分别是一个Treap,和一般的二叉搜索树不同的是,Treap纪录一个额外的数据,就是优先级。Treap在以关键码构成二叉搜索树的同时,还满足堆的性质。这些优先级是是在结点插入时,随机赋予的,Treap根据这些优先级满足堆的性质。这样的话,Treap是有一个随机附加域满足堆的性质的二叉搜索树,其结构相当于以随机数据插入的二叉搜索树。其基本操作的期望时间复杂度为O(logn)。相对于其他的平衡二叉搜索树,Treap的特点是实现简单,且能基本实现随机平衡的结构。

Treap维护堆性质的方法只用到了旋转,只需要两种旋转

代码

头文件treap.h

#ifndef __TREAP_H__
#define __TREAP_H__

typedef int KEY_TYPE;
typedef struct treap{
	KEY_TYPE key;
	int priority;
	struct treap* lchild;
	struct treap* rchild;
}treap;

treap* RR_Rotate(treap* k2);
treap* LL_Rotate(treap* k2);
int Randint();
int Randint(int a, int b);
treap* New_Node(KEY_TYPE key);
treap* Insert(KEY_TYPE key, treap* root);
void Delete_Recur(KEY_TYPE key, treap* &Root);
void Delete_Non_Recur(KEY_TYPE key, treap* &Root);
void InOrder(treap* root);

#endif

实现代码treap.cpp

#include "treap.h"
#include <iostream>
#include <cstdlib>

/* RR(Y rotates to the right):
        k2                   k1
       /  \                 /  \
      k1   Z     ==>       X   k2
     / \                      /  \
    X   Y                    Y    Z
*/
/*
 Return which the root pointer(at a higher level) should point to
 */
treap* RR_Rotate(treap* k2)
{
	treap* k1 = k2->lchild;
	k2->lchild = k1->rchild;
	k1->rchild = k2;
	return k1;
}

/* LL(Y rotates to the left):
        k2                       k1
       /  \                     /  \
      X    k1         ==>      k2   Z
          /  \                /  \
         Y    Z              X    Y
 */
treap* LL_Rotate(treap* k2)
{
	treap* k1 = k2->rchild;
	k2->rchild = k1->lchild;
	k1->lchild = k2;
	return k1;
}


/* remember to add: srand(time(NULL)); in main.cpp */
inline int Randint()
{
	return rand();
}

inline int Randint(int a, int b)
{
	return a + rand() % (b-a+1);
}

treap* New_Node(KEY_TYPE key)
{
	treap* p_node = (treap*)malloc(sizeof(treap));
	if(!p_node)
	{
		fprintf(stderr, "Out of memory!\n");
		exit(1);
	}
	p_node->key = key;
	/* Note: the range of priority is very important, actually */
	p_node->priority = Randint(0, 100);
	p_node->lchild = p_node->rchild = NULL;
	return p_node;
}


/* Recursive implementation of Insertion in treap */
treap* Insert(KEY_TYPE key, treap* root)
{
	treap* p_node = New_Node(key);
	if(!root)
		return (root = p_node);
	if(key <= root->key)
	{
		root->lchild = Insert(key, root->lchild);
		if(root->lchild->priority < root->priority)
			root = RR_Rotate(root);
	}
	else
	{
		root->rchild = Insert(key, root->rchild);
		if(root->rchild->priority < root->priority)
			root = LL_Rotate(root);
	}
	return root;
}

/* Recursive implementation of Delete() */
void Delete_Recur(KEY_TYPE key, treap* &root)
{
	if(!root)
	{
		printf("treap empty, delete failed!\n");
		return;
	}
	if(key < root->key)
		Delete_Recur(key, root->lchild);
	else if(key > root->key)
		Delete_Recur(key, root->rchild);
	else
	{
		if(!root->lchild || !root->rchild)
		{
			treap* temp = root;
			if(!root->lchild)
				root = root->rchild;
			else
				root = root->lchild;
			free(temp);
		}
		else
		{
			if(root->lchild->priority < root->rchild->priority)
			{
				root = RR_Rotate(root);
				Delete_Recur(key, root->rchild);
			}
			else
			{
				root = LL_Rotate(root);
				Delete_Recur(key, root->lchild);
			}
		}
	}
}

/* Non-recursive implementation of Delete() */
void Delete_Non_Recur(KEY_TYPE key, treap* &Root)
{
	treap* parent = NULL;
	treap* root = Root;
	if(!root)
	{
		printf("treap empty, delete failed!\n");
		return;
	}
	while(root)
	{
		if(key < root->key)
		{
			parent = root;
			root = root->lchild;
		}
		else if(key > root->key)
		{
			parent = root;
			root = root->rchild;
		}
		else // now root is the node we want to delete
		{
			if(!root->lchild) // root's left child is empty
			{
				if(!parent)
					Root = root->rchild;
				else
				{
					if(parent->lchild == root)
						parent->lchild = root->rchild;
					else
						parent->rchild = root->rchild;
				}
			}
			else if(!root->rchild) // root's left is non-empty, its right child is empty.
			{
				if(!parent)
					Root = root->lchild;
				else
				{
					if(parent->lchild == root)
						parent->lchild = root->lchild;
					else
						parent->rchild = root->lchild;
				}
			}
			else /* root has two non-empty children, then using rotation to make it a 
					leaf node or a node with only one child. This is difference between
					BST delete and treap delete */
			{
				while(root->lchild && root->rchild)
				{
					if(root->lchild->priority < root->rchild->priority)
					{
						if(!parent)
						{
							Root = RR_Rotate(root);
							parent = Root;
						}
						else
						{
							if(parent->lchild == root)
							{
								parent->lchild = RR_Rotate(root);
								parent = parent->lchild;
							}
							else
							{
								parent->rchild = RR_Rotate(root);
								parent = parent->rchild;
							}
						}
					}
					else
					{
						if(!parent)
						{
							Root = LL_Rotate(root);
							parent = Root;
						}
						else
						{
							if(parent->lchild == root)
							{
								parent->lchild = LL_Rotate(root);
								parent = parent->lchild;
							}
							else
							{
								parent->rchild = LL_Rotate(root);
								parent = parent->rchild;
							}
						}
					}
				}
				if(!root->lchild)
				{
					if(parent->lchild == root)
						parent->lchild = root->rchild;
					else
						parent->rchild = root->rchild;
				}
				else // root->rchild == NULL
				{
					if(parent->lchild == root)
						parent->lchild = root->lchild;
					else
						parent->rchild = root->lchild;
				}
			}
			free(root);
			return;
		}
	}
	printf("key doesn't exist, delete failed!\n");
}


void InOrder(treap* root)
{
	if(root)
	{
		InOrder(root->lchild);
		printf("key: %d | priority: %d ", root->key, root->priority);
		if(root->lchild)
			printf(" | left child: %d ", root->lchild->key);
		if(root->rchild)
			printf(" | right child: %d ", root->rchild->key);
		printf("\n");
		InOrder(root->rchild);
	}
}

main.cpp测试文件,g++ main.cpp treap.cpp

#include <iostream>
#include "treap.h"
#include <ctime>

int main(int argc, char* argv[])
{
	srand(time(NULL));
	treap* root = NULL;
//	int vector[] = {15,6,18,3,7,17,20,2,4,13,9};
//	const int length = sizeof(vector)/sizeof(int);
	for(int i = 0; i< 10;i++)
		root = Insert(i, root);
	
	printf("\nInOrder: \n");
	InOrder(root);

	int input;
	printf("\nplease input the value you want to delete: ");
	scanf("%d",&input);
	
	while(1)
	{
		Delete_Non_Recur(input, root);
		printf("\nAfter delete %u:\n",input);
		InOrder(root);
		printf("\nplease input another value you want to delete: ");
		scanf("%u",&input);
	}
	printf("\n");
	return 0;
}

posted on 2021-07-01 16:32  tur  阅读(106)  评论(0)    收藏  举报

导航