您的位置:首页 > 其它

[转载]伸展树

2015-01-29 11:22 78 查看
一、简介:
伸展树,或者叫自适应查找树,是一种用于保存有序集合的简单高效的数据结构。伸展树实质上是一个二叉查找树。允许查找,插入,删除,删除最小,删除最大,分割,合并等许多操作,这些操作的时间复杂度为O(logN)。由于伸展树可以适应需求序列,因此他们的性能在实际应用中更优秀。
伸展树支持所有的二叉树操作。伸展树不保证最坏情况下的时间复杂度为O(logN)。伸展树的时间复杂度边界是均摊的。尽管一个单独的操作可能很耗时,但对于一个任意的操作序列,时间复杂度可以保证为O(logN)。
二、自调整和均摊分析:
平衡查找树的一些限制:
1、平衡查找树每个节点都需要保存额外的信息。
2、难于实现,因此插入和删除操作复杂度高,且是潜在的错误点。
3、对于简单的输入,性能并没有什么提高。
平衡查找树可以考虑提高性能的地方:
1、平衡查找树在最差、平均和最坏情况下的时间复杂度在本质上是相同的。
2、对一个节点的访问,如果第二次访问的时间小于第一次访问,将是非常好的事情。
3、90-10法则。在实际情况中,90%的访问发生在10%的数据上。
4、处理好那90%的情况就很好了。
三、均摊时间边界:
在一颗二叉树中访问一个节点的时间复杂度是这个节点的深度。因此,我们可以重构树的结构,使得被经常访问的节点朝树根的方向移动。尽管这会引入额外的操作,但是经常被访问的节点被移动到了靠近根的位置,因此,对于这部分节点,我们可以很快的访问。根据上面的90-10法则,这样做可以提高性能。
为了达到上面的目的,我们需要使用一种策略──旋转到根(rotate-to-root)。具体实现如下:
旋转分为左旋和右旋,这两个是对称的。图示:

1 /*
2                 An implementation of top-down splaying
3                     D. Sleator <sleator@cs.cmu.edu>
4                              March 1992
5  */
6 #include <stdlib.h>
7 #include <stdio.h>
8  int size;  /* number of nodes in the tree */
9            /* Not actually needed for any of the operations */
10 typedef struct tree_node Tree;
11  struct tree_node
12 {
13     Tree * left, * right;
14     int item;
15 };
16
17 Tree * splay (int i, Tree * t)
18 {
19  /* Simple top down splay, not requiring i to be in the tree t.  */
20  /* What it does is described above.                             */
21     Tree N, *l, *r, *y;
22     if (t == NULL)
23         return t;
24     N.left = N.right = NULL;
25     l = r = &N;
26     for (;;)
27     {
28         if (i < t->item)
29         {
30             if (t->left == NULL)
31             {
32                 break;
33             }
34             if (i < t->left->item)
35             {
36                 y = t->left;                           /* rotate right */
37                 t->left = y->right;
38                 y->right = t;
39                 t = y;
40                 if (t->left == NULL)
41                 {
42                     break;
43                 }
44             }
45             r->left = t;                               /* link right */
46             r = t;
47             t = t->left;
48         }
49         else if (i > t->item)
50         {
51             if (t->right == NULL)
52             {
53                 break;
54             }
55             if (i > t->right->item)
56             {
57                 y = t->right;                          /* rotate left */
58                 t->right = y->left;
59                 y->left = t;
60                 t = y;
61                 if (t->right == NULL)
62                 {
63                     break;
64                 }
65             }
66             l->right = t;                              /* link left */
67             l = t;
68             t = t->right;
69         }
70         else
71         {
72             break;
73         }
74     }
75     l->right = t->left;                                /* assemble */
76     r->left = t->right;
77     t->left = N.right;
78     t->right = N.left;
79     return t;
80 }
81  /* Here is how sedgewick would have written this.                    */
82 /* It does the same thing.                                           */
83 Tree * sedgewickized_splay (int i, Tree * t)
84 {
85     Tree N, *l, *r, *y;
86     if (t == NULL)
87     {
88         return t;
89     }
90     N.left = N.right = NULL;
91     l = r = &N;
92     for (;;)
93     {
94         if (i < t->item)
95         {
96             if (t->left != NULL && i < t->left->item)
97             {
98                 y = t->left;
99                 t->left = y->right;
100                 y->right = t;
101                 t = y;
102             }
103             if (t->left == NULL)
104             {
105                 break;
106             }
107             r->left = t;
108             r = t;
109             t = t->left;
110         }
111         else if (i > t->item)
112         {
113             if (t->right != NULL && i > t->right->item)
114             {
115                 y = t->right;
116                 t->right = y->left;
117                 y->left = t;
118                 t = y;
119             }
120             if (t->right == NULL)
121             {
122                 break;
123             }
124             l->right = t;
125             l = t;
126             t = t->right;
127         }
128         else
129         {
130             break;
131         }
132     }
133     l->right=t->left;
134     r->left=t->right;
135     t->left=N.right;
136     t->right=N.left;
137     return t;
138 }
139
140 Tree * insert(int i, Tree * t)
141 {
142 /* Insert i into the tree t, unless it's already there.    */
143 /* Return a pointer to the resulting tree.                 */
144     Tree * new;
145
146     new = (Tree *) malloc (sizeof (Tree));
147     if (new == NULL)
148     {
149         printf("Ran out of space\n");
150         exit(1);
151     }
152     new->item = i;
153     if (t == NULL)
154     {
155         new->left = new->right = NULL;
156         size = 1;
157         return new;
158     }
159     t = splay(i,t);
160     if (i < t->item)
161     {
162         new->left = t->left;
163         new->right = t;
164         t->left = NULL;
165         size ++;
166         return new;
167     }
168     else if (i > t->item)
169     {
170         new->right = t->right;
171         new->left = t;
172         t->right = NULL;
173         size++;
174         return new;
175     }
176     else
177     {
178         /* We get here if it's already in the tree */
179         /* Don't add it again                      */
180         free(new);
181         return t;
182     }
183 }
184
185 Tree * delete(int i, Tree * t)
186 {
187 /* Deletes i from the tree if it's there.               */
188 /* Return a pointer to the resulting tree.              */
189     Tree * x;
190     if (t==NULL)
191     {
192         return NULL;
193     }
194     t = splay(i,t);
195     if (i == t->item)
196     {               /* found it */
197         if (t->left == NULL)
198         {
199             x = t->right;
200         }
201         else
202         {
203             x = splay(i, t->left);
204             x->right = t->right;
205         }
206         size--;
207         free(t);
208         return x;
209     }
210     return t;                         /* It wasn't there */
211 }
212
213 int main(int argv, char *argc[])
214 {
215 /* A sample use of these functions.  Start with the empty tree,         */
216 /* insert some stuff into it, and then delete it                        */
217     Tree * root;
218     int i;
219     root = NULL;              /* the empty tree */
220     size = 0;
221     for (i = 0; i < 1024; i++)
222     {
223         root = insert((541*i) & (1023), root);
224     }
225     printf("size = %d\n", size);
226     for (i = 0; i < 1024; i++)
227     {
228         root = delete((541*i) & (1023), root);
229     }
230     printf("size = %d\n", size);
231 }
232


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