伸展树

数据结构与算法分析——c语言描述 第四章树 伸展树


看了书上的思路,全靠自己独立把代码写出来了,后来才发现书上给的代码实现是放到最后一章12章了。

写完我都为我的意志坚定而惊讶。花了一天和一个早上的一个小时。代码一定要靠自己写出来,很多时候代码一看就懂,但你是不知道怎么来的,架构思路方法怎么来的。不停debug不停修改代码就是一个创作思考的过程,don't be afraid.


说几点值得注意的

查找,插入,删除是会改变树的结构的。有时会把根节点也改变掉,所以调用的时候必须是t = findMax(t);,把返回值赋给t,当然也可以传入指针,但这样指针的地址更麻烦。旋转的时候不是每一个节点都旋转,所以返回的必须包含两个信息,要找的值和这一层的根节点,有时候相同(旋转的时候),有时候不同(不旋转的时候),所以返回一个结构体包含两个指针。

书上删除的思路假定了要找的节点必须有左子树的情况和findmax必须要最大值就是根节点。我考虑没有左子树和没有父亲的情况。

查找,找最大值,找最小值需要返回相应的节点的指针。但是树是自底向上旋转的,并且是有祖父的时候才旋转,那么再最上层的时候一定要把节点转到根节点上,不然你就会忽略上一层的节点。(t = findMax(t);)这是使用方法,也就是说必须要找的值放到第一个。插入则不需要放到根节点上。


SplayTree.h

typedef int ElementType;

#ifndef _SplayTree_H
#define _SplayTree_H

struct SplayNode;
typedef struct SplayNode *Position;
typedef struct SplayNode *SplayTree;

SplayTree createSplayTree();
SplayTree MakeEmpty(SplayTree T);
Position find(ElementType X, SplayTree t);
Position findMin(SplayTree t);
Position findMax(SplayTree t);
SplayTree insert(ElementType X, SplayTree t);
SplayTree Delete(ElementType X, SplayTree t);
ElementType retrieve(Position p);
void listDirectory(SplayTree t);
#endif

SplayTree.c

#include"SplayTree.h"
#include<stdlib.h>
#include"fatal.h"

struct SplayNode {
	ElementType element;
	SplayTree left;
	SplayTree right;
};

struct Pair {//用于返回的结构体
	Position pToX;
	Position pToNextLevelRootNode;
};

static Position singleRotateWithLeft(Position k2) {
	Position k1 = k2->left;
	Position y = k1->right;
	k2->left = y;
	k1->right = k2;
	return k1;
}


static Position singleRotateWithRight(Position k1) {
	Position k2 = k1->right;
	Position y = k2->left;
	k1->right = y;
	k2->left = k1;
	return k2;
}


static Position doubleRotateWithLeft(Position k3) {
	Position k1 = k3->left;
	k3->left = singleRotateWithRight(k1);
	return singleRotateWithLeft(k3);
}



static Position doubleRotateWithRight(Position k1) {
	Position k3 = k1->right;
	k1->right = singleRotateWithLeft(k3);
	return singleRotateWithRight(k1);
}

static Position zig_ZigRotateWithLeft(Position G) {
	Position P = G->left;
	Position X = P->left;
	Position B = X->right;
	Position C = P->right;
	X->right = P;
	P->left = B;
	P->right = G;
	G->left = C;
	return X;
}

static Position zig_ZigRotateWithRight(Position G) {
	Position P = G->right;
	Position X = P->right;
	Position B = P->left;
	Position C = X->left;
	X->left = P;
	P->left = G;
	P->right = C;
	G->right = B;
	return X;
}


SplayTree createSplayTree() {
	return NULL;
}

SplayTree MakeEmpty(SplayTree T) {
	if (T != NULL) {
		MakeEmpty(T->left);
		MakeEmpty(T->right);
		free(T);
	}
	return NULL;
}



static struct Pair find_internal(ElementType X, SplayTree t) {
	struct Pair ret;//返回上一层的包含指向X和旋转后的这层树根节点的指针的结构
	struct Pair receive;//下一层返回来的,指向X和旋转后的下一层树的根节点的指针的结构
	if (t == NULL) {//空树,空指针

		ret.pToNextLevelRootNode = NULL;
		ret.pToX = NULL;
	}
	else if (X < t->element) {
		receive = find_internal(X, t->left);
		t->left = receive.pToNextLevelRootNode;
		if (receive.pToX == NULL) {//没找到X
			ret.pToNextLevelRootNode = t;
			ret.pToX = NULL;
		}
		else {
			if (t->left->left == receive.pToX) {

				t = zig_ZigRotateWithLeft(t);
				ret.pToX = ret.pToNextLevelRootNode = t;
				printf("%d test\n", t->element);
			}
			else if (t->left->right == receive.pToX) {
				t = doubleRotateWithLeft(t);
				ret.pToX = ret.pToNextLevelRootNode = t;
			}
			else {
				ret.pToX = receive.pToX;
				ret.pToNextLevelRootNode = t;
			}
		}

	}
	else if (X > t->element) {
		receive = find_internal(X, t->right);
		t->right = receive.pToNextLevelRootNode;
		if (receive.pToX == NULL) {//没找到X
			ret.pToNextLevelRootNode = t;
			ret.pToX = NULL;
		}
		else {
			if (t->right->right == receive.pToX) {
				t = zig_ZigRotateWithRight(t);
				ret.pToX = ret.pToNextLevelRootNode = t;
			}
			else if (t->right->left == receive.pToX) {
				t = doubleRotateWithRight(t);
				ret.pToX = ret.pToNextLevelRootNode = t;
			}
			else {
				ret.pToX = receive.pToX;
				ret.pToNextLevelRootNode = t;
			}
		}

	}
	else {//相等的情况,就是要寻找的
		ret.pToX = t;
		ret.pToNextLevelRootNode = t;
	}
	return ret;
}

Position find(ElementType X, SplayTree t) {
	struct Pair receive;
	receive = find_internal(X,t);
	if (receive.pToNextLevelRootNode != receive.pToX)//要找的点不在根节点上,转换到根节点,在第二层
		if (receive.pToX->element < receive.pToNextLevelRootNode->element)
			return singleRotateWithLeft(receive.pToNextLevelRootNode);
		else
			return singleRotateWithRight(receive.pToNextLevelRootNode);

	return receive.pToNextLevelRootNode;
}

struct Pair findMin_internal(SplayTree t) {
	struct Pair receive, ret;
	if (t->left) {//存在左节点
		receive = findMin_internal(t->left);
		t->left = receive.pToNextLevelRootNode;
		if (t->left->left == receive.pToX) {//pToX为最小节点的指针
			t = zig_ZigRotateWithLeft(t);
			ret.pToNextLevelRootNode = t;
			ret.pToX = t;
		}
		else {
			ret.pToX = receive.pToX;
			ret.pToNextLevelRootNode = t;
		}

	}
	else {
		ret.pToX = t;
		ret.pToNextLevelRootNode = t;
	}
	return ret;
}

Position findMin(SplayTree t) {
	struct Pair receive;
	receive = findMin_internal(t);
	if (receive.pToNextLevelRootNode != receive.pToX)//最大的在第二层
		return singleRotateWithLeft(receive.pToNextLevelRootNode);
	return receive.pToNextLevelRootNode;
}

struct Pair findMax_internal(SplayTree t) {
	struct Pair receive, ret;
	if (t->right) {//存在左节点
		receive = findMax_internal(t->right);
		t->right = receive.pToNextLevelRootNode;
		if (t->right->right == receive.pToX) {//pToX为最小节点的指针
			t = zig_ZigRotateWithRight(t);
			ret.pToNextLevelRootNode = t;
			ret.pToX = t;
		}
		else {
			ret.pToX = receive.pToX;
			ret.pToNextLevelRootNode = t;
		}
	}
	else {
		ret.pToX = t;
		ret.pToNextLevelRootNode = t;
	}
	return ret;
}

Position findMax(SplayTree t) {
	struct Pair receive;
	receive = findMax_internal(t);
	if (receive.pToNextLevelRootNode != receive.pToX)//最大的在第二层
		return singleRotateWithRight(receive.pToNextLevelRootNode);
	return receive.pToNextLevelRootNode;
}

static Position makeNode(ElementType X) {
	Position t = malloc(sizeof(struct SplayNode));
	if (t == NULL)
		Error("OUT OF MEMORY");
	t->element = X;
	t->left = NULL;
	t->right = NULL;
	return t;
}

struct Pair insert_internal(ElementType X, SplayTree t) {
	struct Pair ret, receive;
	if (t == NULL) {//找到最底层
		t = makeNode(X);
		ret.pToX = t;
		ret.pToNextLevelRootNode = t;
	}

	else if (X < t->element) {//小于
		receive = insert_internal(X, t->left);
		t->left = receive.pToNextLevelRootNode;
		if (t->left->left == receive.pToX) {//一字型
			t = zig_ZigRotateWithLeft(t);
			ret.pToX = ret.pToNextLevelRootNode = t;//旋转了之后插入的节点编程这一层的根节点,下同
		}
		else if (t->left->right == receive.pToX) {//之子型
			t = doubleRotateWithLeft(t);
			ret.pToX = ret.pToNextLevelRootNode = t;
		}
		else {//这一层的下一个节点就是X,没必要旋转
			ret.pToX = receive.pToX;
			ret.pToNextLevelRootNode = t;
		}
	}
	else if (X > t->element) {
		receive = insert_internal(X, t->right);
		t->right = receive.pToNextLevelRootNode;
		if (t->right->right == receive.pToX) {
			t = zig_ZigRotateWithRight(t);
			ret.pToX = ret.pToNextLevelRootNode = t;
		}
		else if (t->right->left == receive.pToX) {
			t = doubleRotateWithRight(t);
			ret.pToX = ret.pToNextLevelRootNode = t;
		}
		else {
			ret.pToX = receive.pToX;
			ret.pToNextLevelRootNode = t;
		}
	}
	else {
		ret.pToNextLevelRootNode = t;
		ret.pToX = t;
	}
	return ret;
}

SplayTree insert(ElementType X, SplayTree t) {
	return insert_internal(X, t).pToNextLevelRootNode;
}

SplayTree Delete(ElementType X, SplayTree t) {
	Position father = NULL;
	Position p = t;
	while (p) {
		if (X < p->element) {
			father = p;
			p = p->left;
		}
		else if (X > p->element) {
			father = p;
			p = p->right;
		}
		else//相等,找到了
			break;
	}
	if (p) {//找到了
		Position MaxOf_T_Left;
		if (p->left) {//存在左子树的情况下
			MaxOf_T_Left = findMax(p->left);//把最大的放到左子树根节点上
			MaxOf_T_Left->right = p->right;//连接起来
			if (father) {//有父节点
				if (MaxOf_T_Left->element < father->element)
					father->left = MaxOf_T_Left;
				else//大于,不存在等于
					father->right = MaxOf_T_Left;
			}
			else//有左子树,没父节点
				t = MaxOf_T_Left;
		}
		else {//没有左子树
			if (father) {//有父节点
				if (p->element < father->element)
					father->left = p->right;//right可能空或者不空
				else//大于,不存在等于
					father->right = p->right;
			}
			else//没有父节点,没有左子树
				t = p->right;
		}
		free(p);
	}
	return t;
}

ElementType retrieve(Position p) {
	return p->element;
}

static void listDir(SplayTree t, int depth) {
	if (t) {
		int d = depth;
		while (d--)
			printf("	");
		printf("%d\n", t->element);
		if (t->left)
			listDir(t->left, depth + 1);
		if (t->right)
			listDir(t->right, depth + 1);


	}
}

void listDirectory(SplayTree t) {
	listDir(t, 0);
}


main.c

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

struct SplayNode {
	ElementType element;
	SplayTree left;
	SplayTree right;
};


int main() {
	SplayTree t = createSplayTree();


	for (int i = 0; i < 15; i++)
		t = insert(rand(), t);
	listDirectory(t);

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值