当一个结点被访问时,它很可能不久再被访问到,伸展树就是为了达到这个目的的,其基本想法是通过一系列AVL树的旋转使被访问的结点被放到根上。如果这个结点很深,那么其路径上的许多结点也相对较深,通过重新构造可以使对这些结点的进一步访问花费的时间减少。
代码如下:
1 #include <iostream> 2 #include <stdlib.h> 3 using namespace std; 4 5 struct SplayTreeNode 6 { 7 int data; 8 struct SplayTreeNode* left; 9 struct SplayTreeNode* right; 10 }; 11 typedef struct SplayTreeNode* tree; 12 typedef struct SplayTreeNode* position; 13 14 position rotate_left(position K2); 15 position rotate_right(position K2); 16 17 //查找 18 position find(tree T, int x) 19 { 20 if (T == NULL) 21 return NULL; 22 if (x < T->data) 23 find(T->left, x); 24 else if (x > T->data) 25 find(T->right, x); 26 else 27 return T; 28 } 29 //插入,返回根节点 30 position insert(tree &T, int data) 31 { 32 if (T == NULL) 33 { 34 T = (position)malloc(sizeof(SplayTreeNode)); 35 T->data = data; 36 T->left = T->right = NULL; 37 } 38 else if (data < T->data) 39 T->left = insert(T->left, data); 40 else if (data > T->data) 41 T->right = insert(T->right, data); 42 43 return T; 44 } 45 //创建二叉树 46 tree create_tree(int data[],int n) 47 { 48 tree T=NULL; 49 for (int i = 0; i < n; i++) 50 insert(T, data[i]); 51 return T; 52 } 53 //判断指针到父结点没,到则返回false,没到返回true 54 bool pre_data(tree T,int data) 55 { 56 if (T->left == NULL) 57 return T->right->data != data; 58 else if (T->right == NULL) 59 return T->left->data != data; 60 else 61 return (T->left->data != data && T->right->data != data); 62 } 63 //找父节点 64 position find_parent(tree T, int data) 65 { 66 if (T == NULL|| T->data == data) 67 return NULL; 68 while (pre_data(T, data)) 69 { 70 if (data < T->data) 71 T = T->left; 72 else if (data > T->data) 73 T = T->right; 74 } 75 return T; 76 } 77 //判断是否为之字形(zig-zag) 78 int zhi(tree T, int data) 79 { 80 position p,p1,p2; 81 p = find(T, data); 82 p1=find_parent(T,data); 83 p2 = find_parent(T, p1->data); 84 if (p2->left == p1 && p1->right == p) 85 return 1; 86 else if (p2->right == p1 && p1->left == p) 87 return 2; 88 else 89 return 0; 90 } 91 //判断是否为一字形(zig-zig) 92 int yi(tree T, int data) 93 { 94 position p, p1, p2; 95 p = find(T, data); 96 p1 = find_parent(T, data); 97 p2 = find_parent(T, p1->data); 98 if (p2->left == p1 && p1->left == p) 99 return 1; 100 else if (p2->right == p1 && p1->right == p) 101 return 2; 102 else 103 return 0; 104 } 105 //avl左单旋 106 position single_left(position K2) 107 { 108 position K1 = K2->left; 109 K2->left = K1->right; 110 K1->right = K2; 111 return K1; 112 } 113 //avl右单旋 114 position single_right(position K2) 115 { 116 position K1 = K2->right; 117 K2 ->right = K1->left; 118 K1->left = K2; 119 return K1; 120 } 121 //avl左右双旋 122 position double_left(position K3) 123 { 124 K3->left = single_right(K3->left); 125 return single_left(K3); 126 } 127 //avl右左双旋 128 position double_right(position K3) 129 { 130 K3->right = single_left(K3->right); 131 return single_right(K3); 132 } 133 //情况1:单旋左 134 position rotate_left(position K2) 135 { 136 position K1 = K2->left; 137 K2->left = K1->left; 138 K1->left = K2->right; 139 K2->right = K1->right; 140 K1->right = K2; 141 return K1; 142 } 143 //情况1:单旋右 144 position rotate_right(position K2) 145 { 146 position K1 = K2->right; 147 K2->right = K1->right; 148 K1->right = K2->left; 149 K2->right = K1->left; 150 K1->left = K2; 151 return K1; 152 } 153 //一字形左 154 position yi_rotate_left(tree T, int data) 155 { 156 position p, p1, p2; 157 p = find(T, data); 158 p1 = find_parent(T, data); 159 p2 = find_parent(T, p1->data); 160 single_left(p2); 161 single_left(p1); 162 return p; 163 } 164 //一字形右 165 position yi_rotate_right(tree T, int data) 166 { 167 position p, p1, p2; 168 p = find(T, data); 169 p1 = find_parent(T, data); 170 p2 = find_parent(T, p1->data); 171 single_right(p2); 172 single_right(p1); 173 return p; 174 } 175 //旋转 176 tree SplayTree_Splay(tree T, int data) 177 { 178 //情况1:data的父结点是树根时,进行单旋 179 if (T == find(T,data) && data < T->data) 180 T=rotate_left(T); 181 else if (T == find(T, data) && data > T->data) 182 T=rotate_right(T); 183 else 184 { 185 position p, p1, p2,p3; 186 p = find(T, data); 187 p1 = find_parent(T, data); 188 p2 = find_parent(T, p1->data); 189 p3 = find_parent(T, p2->data); 190 //情况2:之字形 191 if (zhi(T, data)) 192 { 193 switch (zhi(T, data)) 194 { 195 case 1: 196 p = double_left(p2); 197 if (p3 != NULL) 198 { 199 if (p2->data < p3->data) 200 p3->left = p; 201 else 202 p3->right = p; 203 } 204 else 205 T = p; 206 break; 207 case 2: 208 p = double_right(p2); 209 if (p3 != NULL) 210 { 211 if (p2->data < p3->data) 212 p3->left = p; 213 else 214 p3->right = p; 215 } 216 else 217 T = p; 218 break; 219 } 220 } 221 //情况3:一字形 222 else 223 { 224 switch(yi(T,data)) 225 { 226 case 1: 227 p = yi_rotate_left(T, data); 228 if (p3 != NULL) 229 { 230 if (p2->data < p3->data) 231 p3->left = p; 232 else 233 p3->right = p; 234 } 235 else 236 T = p; 237 break; 238 case 2: 239 p = yi_rotate_right(T, data); 240 if (p3 != NULL) 241 { 242 if (p2->data < p3->data) 243 p3->left = p; 244 else 245 p3->right = p; 246 } 247 else 248 T = p; 249 break; 250 } 251 } 252 } 253 return T; 254 } 255 256 //后序遍历 257 void post_order(tree T) 258 { 259 if (T != NULL) 260 { 261 post_order(T->left); 262 post_order(T->right); 263 cout << T->data << " "; 264 } 265 } 266 267 int main() 268 { 269 tree T = NULL, T1 = NULL; 270 int data2[] = { 8,4,1,7,5,10,9 }; 271 T = create_tree(data2, 7); 272 T1 = create_tree(data2, 7); 273 while (find_parent(T, 1) != NULL) 274 T = SplayTree_Splay(T, 1); 275 post_order(T); 276 cout << endl; 277 while (find_parent(T1, 7) != NULL) 278 T1 = SplayTree_Splay(T1, 7); 279 post_order(T1); 280 system("pause"); 281 return 0; 282 }
创建了如下的二叉树:
运行结果(后序遍历):