您的位置:首页 > 其它

伸展树

2016-04-05 12:22 218 查看
数据结构与算法分析——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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: