手植这棵自顶向下伸展树,何时亭亭如盖呢?

举报
看,未来 发表于 2020/12/29 22:53:13 2020/12/29
【摘要】 文章目录 前言自顶向下原理图说在前头zig(单旋转)zig-zig(一字型旋转)zig-zag(之字型旋转)合并树我一直没看懂的示例 自顶向下伸展树代码实现 前言 伸展树,解释起来真的很晕。先看一下我写的关于伸展树的理论部分吧:伸展树,据说比AVL树要简单一些。简单个球啊,写完了我还是晕晕的,所以又看了很久。 但是,总有那么一瞬,总有那么一句话...

在这里插入图片描述

前言

伸展树,解释起来真的很晕。先看一下我写的关于伸展树的理论部分吧:伸展树,据说比AVL树要简单一些。简单个球啊,写完了我还是晕晕的,所以又看了很久。

但是,总有那么一瞬,总有那么一句话,会让你茅塞顿开。
所以,我再简单讲一遍自顶向下伸展树原理,自底向上是真的,好理解,但是实现成本太高。

自顶向下原理图

说在前头

在这里插入图片描述为了叙述的方便,上图的右旋叫做X绕Y右旋,左旋叫做Y绕X左旋。

当我们沿着树向下搜索某个节点X的时候,我们将搜索路径上的节点及其子树移走。我们构建两棵临时的树──左树和右树。没有被移走的节点构成的树称作中树。在伸展操作的过程中:
1、当前节点X是中树的根。
2、左树L保存小于X的节点。
3、右树R保存大于X的节点。
开始时候,X是树T的根,左右树L和R都是空的。

和自底向上一样,自顶向下也分了三种情况。

zig(单旋转)

在这里插入图片描述如上图,在搜索到X的时候,所查找的节点比X小,将Y旋转到中树的树根。旋转之后,X及其右子树被移动到右树上。很显然,右树上的节点都大于所要查找的节点。注意X被放置在右树的最小的位置,也就是X及其子树比原先的右树中所有的节点都要小。这是由于越是在路径前面被移动到右树的节点,其值越大。读者可以分析一下树的结构,原因很简单。(就这句,给我点醒了)

通了一点之后,后面就好办了。

zig-zig(一字型旋转)

在这里插入图片描述在这种情况下,所查找的节点在Z的子树中,也就是,所查找的节点比X和Y都小。所以要将X,Y及其右子树都移动到右树中。首先是Y绕X右旋,然后Z绕Y右旋,最后将Z的右子树(此时Z的右子节点为Y)移动到右树中。注意右树中挂载点的位置。

zig-zag(之字型旋转)

在这里插入图片描述 在这种情况中,首先将Y右旋到根。这和Zig的情况是一样的。然后变成上图右边所示的形状。接着,对Z进行左旋,将Y及其左子树移动到左树上。这样,这种情况就被分成了两个Zig情况。这样,在编程的时候就会简化,但是操作的数目增加(相当于两次Zig情况)。

合并树

在这里插入图片描述

将中树的左右子树分别连接到左树的右子树和右树的左子树上。将左右树作为X的左右子树。重新最成了一所查找的节点为根的树。

我一直没看懂的示例

下面是一个查找节点19的例子:
在例子中,树中并没有节点19,最后,距离节点最近的节点18被旋转到了根作为新的根。节点20也是距离节点19最近的节点,但是节点20没有成为新根,这和节点20在原来树中的位置有关系。

而一直困扰我的,就是第二步到第三步的转化,为什么要把20提上去,现在明白了。

在这里插入图片描述

自顶向下伸展树代码实现

#include <stdlib.h>
#include <stdio.h>
	int size;  /* number of nodes in the tree */ /* Not actually needed for any of the operations */
typedef struct tree_node Tree;
struct tree_node
{ Tree * left, * right; int item;
};

Tree * splay (int i, Tree * t)
{
 /* Simple top down splay, not requiring i to be in the tree t.  */
 /* What it does is described above. */ Tree N, *l, *r, *y; if (t == NULL) return t; N.left = N.right = NULL; l = r = &N; for (;;) { if (i < t->item) { if (t->left == NULL) break; if (i < t->left->item) { y = t->left; /* rotate right */ t->left = y->right; y->right = t; t = y; if (t->left == NULL) break; } r->left = t; /* link right */ r = t; t = t->left; } else if (i > t->item) { if (t->right == NULL) break; if (i > t->right->item) { y = t->right; /* rotate left */ t->right = y->left; y->left = t; t = y; if (t->right == NULL) break; } l->right = t; /* link left */ l = t; t = t->right; } else break; } l->right = t->left; /* assemble */ r->left = t->right; t->left = N.right; t->right = N.left; return t;
}
/* Here is how sedgewick would have written this. */
/* It does the same thing. */
Tree * sedgewickized_splay (int i, Tree * t)
{ Tree N, *l, *r, *y; if (t == NULL) return t; N.left = N.right = NULL; l = r = &N; for (;;) { if (i < t->item) { if (t->left != NULL && i < t->left->item) { y = t->left; t->left = y->right; y->right = t; t = y; } if (t->left == NULL) break; r->left = t; r = t; t = t->left; } else if (i > t->item) { if (t->right != NULL && i > t->right->item) { y = t->right; t->right = y->left; y->left = t; t = y; } if (t->right == NULL) break; l->right = t; l = t; t = t->right; } else break; } } l->right=t->left; r->left=t->right; t->left=N.right; t->right=N.left; return t;
}

Tree * insert(int i, Tree * t)
{
/* Insert i into the tree t, unless it's already there. */
/* Return a pointer to the resulting tree. */ Tree * new_node; new_node = (Tree *) malloc (sizeof (Tree)); if (new_node == NULL) { printf("Ran out of space\n"); exit(1); } new_node ->item = i; if (t == NULL) { new_node->left = new_node->right = NULL; size = 1; return new_node; } t = splay(i,t); if (i < t->item) { new_node->left = t->left; new_node->right = t; t->left = NULL; size ++; return new_node; } else if (i > t->item) { new_node->right = t->right; new_node->left = t; t->right = NULL; size++; return new_node; } else { /* We get here if it's already in the tree */ /* Don't add it again */ free(new_node); return t; }
}

Tree * delete(int i, Tree * t)
{
/* Deletes i from the tree if it's there. */
/* Return a pointer to the resulting tree. */ Tree * x; if (t==NULL) return NULL; t = splay(i,t); if (i == t->item) { /* found it */ if (t->left == NULL) x = t->right; else { x = splay(i, t->left); x->right = t->right; } size--; free(t); return x; } return t; /* It wasn't there */
}

int main(int argv, char *argc[])
{
/* A sample use of these functions.  Start with the empty tree, */
/* insert some stuff into it, and then delete it */ Tree * root; int i; root = NULL; /* the empty tree */ size = 0; for (i = 0; i < 1024; i++) { root = insert((541*i) & (1023), root); } printf("size = %d\n", size); for (i = 0; i < 1024; i++) { root = delete((541*i) & (1023), root); } printf("size = %d\n", size);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205

文章来源: lion-wu.blog.csdn.net,作者:看,未来,版权归原作者所有,如需转载,请联系作者。

原文链接:lion-wu.blog.csdn.net/article/details/107376602

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。