一種伸展樹實現

伸展樹的優點:1、數據結構較簡單,不需要保存AVL平衡相關信息,可以節省空間

                        2、不存在壞的輸入序列,它可以保證任意連續M次對樹的操作最多花費O(M log N)時間

                        3、一棵伸展樹每次操作的攤還時間爲O(log N)

伸展樹的基本思想:當一個基點被訪問後,它就要經過一系列旋轉處理,直至將該節點放到根上,便於下次再次訪問。

#include<stdio.h>
#include<stdlib.h>

struct splay_tree {
	char data;
	struct splay_tree *lchild;
	struct splay_tree *rchild;
	struct splay_tree *parent;//爲了便於尋找其父節點及其祖父節點,故添加一個前向類型指針
};

struct splay_tree *global_X;//爲了記錄插入位置,故添加一個全局指針

//zig-zag format
//P是X的父節點,G是X的祖父節點
struct splay_tree *zig_zag_rotate(struct splay_tree *X, struct splay_tree *P, struct splay_tree *G)
{
	//	G
	//P
	//	X
	if((X->data > P->data) && (P->data < G->data))
	{
		P->rchild = X->lchild;
		G->lchild = X->rchild;
		X->lchild = P;
		X->rchild = G;
		X->parent = G->parent;
		P->parent = X;
		G->parent = X;
	}
	//G
	//	P
	//X
	if((X->data < P->data) && (P->data > G->data))
	{
		P->lchild = X->rchild;
		G->rchild = X->lchild;
		X->rchild = P;
		X->lchild = G;
		X->parent = G->parent;
		P->parent = X;
		G->parent = X;
	}
	return X;
}

//zig-zig format
//P是X的父節點,G是X的祖父節點
struct splay_tree *zig_zig_rotate(struct splay_tree *X, struct splay_tree *P, struct splay_tree *G)
{
	//		G
	//	P	
	//X
	if((X->data < P->data) && (P->data < G->data))
	{
		G->lchild = P->rchild;
		P->rchild = G;
		P->lchild = X->rchild;
		X->rchild = P;
		X->parent = G->parent;
		P->parent = X;
		G->parent = P;
	}
	//G
	//	P
	//		X
	if((X->data > P->data) && (P->data > G->data))
	{
		G->rchild = P->lchild;
		P->lchild = G;
		P->rchild = X->lchild;
		X->lchild = P;
		X->parent = G->parent;
		P->parent = X;
		G->parent = P;
	}
	return X;
}

//zig format
struct splay_tree *zig_rotate(struct splay_tree *X, struct splay_tree *P)
{
	//	P
	//X	
	if(X->data < P->data)
	{
		P->lchild = X->rchild;
		X->rchild->parent = P;
		X->parent = P->parent;
		X->rchild = P;
		P->parent = X;
	}
	//P
	//	X
	if(X->data > P->data)
	{
		P->rchild = X->lchild;
		X->lchild->parent = P;
		X->parent = P->parent;
		X->lchild = P;
		P->parent = X;
	}
	return X;
}

//構建一顆二叉查找樹
struct splay_tree *insert_binary_search_tree(struct splay_tree *T,char c)
{
	if(NULL == T)
	{
		T = malloc(sizeof(struct splay_tree));
		if(NULL == T)
		{
			printf("Failed: no memory to malloc!\n");
			return NULL;
		}
		T->data = c;
		T->lchild = NULL;
		T->rchild = NULL;
		T->parent = NULL;
		global_X = T;
	}
	else
	{
		if(c < T->data)
		{
			T->lchild = insert_binary_search_tree(T->lchild,c);
			if(T->lchild)
				T->lchild->parent = T;
		}
		else if(c > T->data)
		{
			T->rchild = insert_binary_search_tree(T->rchild,c);
			if(T->rchild)
				T->rchild->parent = T;
		}
		else
			printf("%d is already in current tree\n",c);
	}
	return T;
}

struct splay_tree *process_splay_tree(struct splay_tree *T)
{
	struct splay_tree *X,*P,*G;
	if(NULL == T)
		return NULL;
	if(NULL == T->parent)
		return T;
	if(NULL == T->parent->parent)
	{
		X = T;
		P = T->parent;
		T = zig_rotate(X,P);
	}
	else
	{
		X = T;
		P = T->parent;
		G = P->parent;

		while(NULL != X && NULL != P && NULL != G)
		{
			if((X->data < P->data)&&(P->data < G->data))
				T = zig_zig_rotate(X,P,G);
			else if((X->data > P->data)&&(P->data < G->data))
				T = zig_zag_rotate(X,P,G);
			else if((X->data < P->data)&&(P->data > G->data))
				T = zig_zag_rotate(X,P,G);
			else if((X->data > P->data)&&(P->data > G->data))
				 T = zig_zig_rotate(X,P,G);
			X = T;
			P = T->parent;
			if(NULL == P)
				break;
			G = P->parent;
		}
		
		if(NULL == G)
		{
			T = zig_rotate(X,P);
			return;
		}
	}
	return T;
}

struct splay_tree *find_splay_tree(struct splay_tree *T,char c)
{
	if(NULL == T)
	{
		printf("Not Found: there isn't' %c in current tree\n",c);
		return T;
	}
	if(c < T->data)
		return find_splay_tree(T->lchild,c);
	else if(c > T->data)
		return find_splay_tree(T->rchild,c);
	else
	{
		printf("Found: there is %c in current tree\n",c);
		T = process_splay_tree(T);
		return T;
	}
}

struct splay_tree *insert_splay_tree(struct splay_tree *T,char c)
{
	T = insert_binary_search_tree(T,c);
	T = process_splay_tree(global_X);
	return T;
}

struct splay_tree *find_max_binary_search_tree(struct splay_tree *T)
{
	if(NULL == T)
		return T;
	while(NULL != T->rchild)
		T = T->rchild;
	return T;
}

struct splay_tree *delete_splay_tree(struct splay_tree *T,char c)
{
	struct splay_tree *find_temp;
	struct splay_tree *find_max_temp;
	find_temp = find_splay_tree(T,c);
	//判斷所要刪除的字符是否在當前樹中
	if(find_temp)
	{
		//先找到左子樹中的最大值位置
		find_max_temp = find_max_binary_search_tree(find_temp->lchild);
		//將最大值放到根上
		find_temp->lchild->parent = NULL;//將左子樹的根的parent設置爲NULL,否則會影響後面的操作
		find_max_temp = find_splay_tree(find_temp->lchild,find_max_temp->data);
		//將原右子樹合併到根上
		find_max_temp->rchild = find_temp->rchild;
		return find_max_temp;
	}
	//如果所有刪除的字符不在當前樹中,提示用戶並返回
	else
	{
		printf("Delete failed: there isn't %c in current tree\n",c);
		return T;
	}
}

void print_preorder(struct splay_tree *T)
{
	if(NULL == T)
		return;
	printf("%c ",T->data);
	print_preorder(T->lchild);
	print_preorder(T->rchild);
}

void print_midorder(struct splay_tree *T)
{
	if(NULL == T)
		return;
	print_midorder(T->lchild);
	printf("%c ",T->data);
	print_midorder(T->rchild);
}

void print_postorder(struct splay_tree *T)
{
	if(NULL == T)
		return;
	print_postorder(T->lchild);
	print_postorder(T->rchild);
	printf("%c ",T->data);
}

void print_allorder(struct splay_tree *T)
{
	print_preorder(T);
	printf("\n");
	print_midorder(T);
	printf("\n");
	print_postorder(T);
	printf("\n");
}

int main(void)
{
	char c;
	struct splay_tree *T = NULL;
	struct splay_tree *temp = NULL;
	scanf("%c",&c);
	while(c != '#')
	{
		T = insert_binary_search_tree(T,c);
		scanf("%c",&c);
	}
	print_allorder(T);
	//測試find操作
	getchar();
	printf("請輸入查找的字符:");
	scanf("%c",&c);
	printf("-----start----find-%c---------\n",c);
	temp = find_splay_tree(T,c);
	if(temp)
		T = temp;
	printf("-----end----find---%c------\n",c);
	print_allorder(T);
	//測試insert操作
	getchar();
	printf("請輸入插入的字符:");
	scanf("%c",&c);
	printf("-----start----insert---%c---------\n",c);
	T = insert_splay_tree(T,c);
	printf("-----end------insert---%c---------\n",c);
	print_allorder(T);
	//測試delete操作
	getchar();
	printf("請輸入刪除的字符:");
	scanf("%c",&c);
	printf("-----start----delete---%c---------\n",c);
	T = delete_splay_tree(T,c);
	printf("-----end------delete---%c---------\n",c);
	print_allorder(T);
	return 0;
}

運行結果如下:



發佈了36 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章