ACM常用模板——伸展树

  
  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct node *position;
  4. typedef int ElementTP;
  5. struct node {
  6. int depth;
  7. position parent;
  8. ElementTP element;
  9. position lchild;
  10. position rchild;
  11. };
  12. /* pointer => root node of the tree */
  13. typedef struct node *TREE;
  14. position insert_value(TREE, ElementTP);
  15. int depth(TREE);
  16. static void insert_node_to_nonempty_tree(TREE, position);
  17. static void update_root_depth(TREE);
  18. static TREE recover_avl(TREE, position);
  19. static int depth_diff(TREE);
  20. static position insert_leaf(TREE, ElementTP);
  21. static void insert_node_to_nonempty_tree(TREE, position);
  22. static TREE left_single_rotate(TREE);
  23. static TREE left_double_rotate(TREE);
  24. static TREE right_single_rotate(TREE);
  25. static TREE right_double_rotate(TREE);
  26. int main(void)
  27. {
  28. TREE tr;
  29. position np;
  30. ElementTP element;
  31. tr = NULL;
  32. tr = insert_value(tr, 18);
  33. tr = insert_value(tr, 5);
  34. printf("root: %d\n", tr->element);
  35. printf("depth: %d\n", depth(tr));
  36. tr = insert_value(tr, 2);
  37. printf("root: %d\n", tr->element);
  38. printf("depth: %d\n", depth(tr));
  39. tr = insert_value(tr, 4);
  40. printf("root: %d\n", tr->element);
  41. printf("depth: %d\n", depth(tr));
  42. printf("root->lchild: %d\n", tr->lchild->element);
  43. tr = insert_value(tr, 3);
  44. printf("root: %d\n", tr->element);
  45. printf("depth: %d\n", depth(tr));
  46. printf("root->lchild: %d\n", tr->lchild->element);
  47. printf("root->lchild->lchild: %d\n", tr->lchild->lchild->element);
  48. }
  49. /*
  50. * insert value
  51. *
  52. */
  53. position insert_value(TREE tr, ElementTP value)//插入叶子节点
  54. {
  55. position New;
  56. /* insert a value to a binary search tree */
  57. New = insert_leaf(tr, value);
  58. update_root_depth(New);
  59. if (tr == NULL) {
  60. tr = New;
  61. }
  62. else {
  63. tr = recover_avl(tr, New);
  64. }
  65. return tr;
  66. }
  67. /*
  68. * get the depth of the tree
  69. * use this function to access depth
  70. */
  71. int depth(TREE tr) {
  72. if (tr == NULL) {
  73. return 0;
  74. }
  75. else {
  76. return tr->depth;
  77. }
  78. }
  79. //========================================
  80. // static functions: for internal use
  81. /*
  82. * traverse the path from new node to root node
  83. * make one rotation, recover AVL and stop
  84. */
  85. static TREE recover_avl(TREE tr, position np)
  86. {
  87. int myDiff;
  88. while (np != NULL) {
  89. update_root_depth(np);
  90. myDiff = depth_diff(np);
  91. if (myDiff > 1 || myDiff < -1) {
  92. if (myDiff > 1) {
  93. /* left rotate needed */
  94. if(depth_diff(np->rchild) > 0) {
  95. np = left_single_rotate(np);
  96. }
  97. else {
  98. np = left_double_rotate(np);
  99. }
  100. }
  101. if (myDiff < -1) {
  102. if(depth_diff(np->lchild) < 0) {
  103. np = right_single_rotate(np);
  104. }
  105. else {
  106. np = right_double_rotate(np);
  107. }
  108. }
  109. /* if rotation changes root node */
  110. if (np->parent == NULL) tr = np;
  111. break;
  112. }
  113. np = np->parent;
  114. }
  115. return tr;
  116. }
  117. /*
  118. * difference of rchild->depth and lchild->depth
  119. */
  120. static int depth_diff(TREE tr)
  121. {
  122. if (tr == NULL) {
  123. return 0;
  124. }
  125. else {
  126. return depth(tr->rchild) - depth(tr->lchild);
  127. }
  128. }
  129. /*
  130. * left single rotation
  131. * return the new root
  132. */
  133. static TREE left_single_rotate(TREE tr)
  134. {
  135. TREE newRoot, parent;
  136. parent = tr->parent;
  137. newRoot = tr->rchild;
  138. /* detach & attach */
  139. if (newRoot->lchild != NULL) newRoot->lchild->parent = tr;
  140. tr->rchild = newRoot->lchild;
  141. update_root_depth(tr);
  142. /* raise new root node */
  143. newRoot->lchild = tr;
  144. newRoot->parent = parent;
  145. if (parent != NULL) {
  146. if (parent->lchild == tr) {
  147. parent->lchild = newRoot;
  148. }
  149. else {
  150. parent->rchild = newRoot;
  151. }
  152. }
  153. tr->parent = newRoot;
  154. update_root_depth(newRoot);
  155. return newRoot;
  156. }
  157. /*
  158. * right single rotation
  159. * return the new root
  160. */
  161. static TREE right_single_rotate(TREE tr)
  162. {
  163. TREE newRoot, parent;
  164. parent = tr->parent;
  165. newRoot = tr->lchild;
  166. /* detach & attach */
  167. if (newRoot->rchild != NULL) newRoot->rchild->parent = tr;
  168. tr->lchild = newRoot->rchild;
  169. update_root_depth(tr);
  170. /* raise new root node */
  171. newRoot->rchild = tr;
  172. newRoot->parent = parent;
  173. if (parent != NULL) {
  174. if (parent->lchild == tr) {
  175. parent->lchild = newRoot;
  176. }
  177. else {
  178. parent->rchild = newRoot;
  179. }
  180. }
  181. tr->parent = newRoot;
  182. update_root_depth(newRoot);
  183. return newRoot;
  184. }
  185. /*
  186. * left double rotation
  187. * return
  188. */
  189. static TREE left_double_rotate(TREE tr)
  190. {
  191. right_single_rotate(tr->rchild);
  192. return left_single_rotate(tr);
  193. }
  194. /*
  195. * right double rotation
  196. * return
  197. */
  198. static TREE right_double_rotate(TREE tr)
  199. {
  200. left_single_rotate(tr->lchild);
  201. return right_single_rotate(tr);
  202. }
  203. /*
  204. * update tr->depth
  205. * assume lchild->depth and rchild->depth are correct
  206. */
  207. static void update_root_depth(TREE tr)
  208. {
  209. int maxChildDepth;
  210. int depLChild, depRChild;
  211. if (tr==NULL) return;
  212. else {
  213. depLChild = depth(tr->lchild);
  214. depRChild = depth(tr->rchild);
  215. maxChildDepth = depLChild > depRChild ? depLChild : depRChild;
  216. tr->depth = maxChildDepth + 1;
  217. }
  218. }
  219. /*
  220. * insert a new value into the tree as a leaf
  221. * return address of the new node
  222. */
  223. static position insert_leaf(TREE tr, ElementTP value)
  224. {
  225. position np;
  226. /* prepare the node */
  227. np = (position) malloc(sizeof(struct node));
  228. np->element = value;
  229. np->parent = NULL;
  230. np->lchild = NULL;
  231. np->rchild = NULL;
  232. if (tr != NULL) {
  233. insert_node_to_nonempty_tree(tr, np);
  234. }
  235. return np;
  236. }
  237. /*
  238. * insert a node to a non-empty tree
  239. * called by insert_value()
  240. */
  241. static void insert_node_to_nonempty_tree(TREE tr, position np)
  242. {
  243. /* insert the node */
  244. if(np->element <= tr->element) {
  245. if (tr->lchild == NULL) {
  246. /* then tr->lchild is the proper place */
  247. tr->lchild = np;
  248. np->parent = tr;
  249. return;
  250. }
  251. else {
  252. insert_node_to_nonempty_tree(tr->lchild, np);
  253. }
  254. }
  255. else if(np->element > tr->element) {
  256. if (tr->rchild == NULL) {
  257. tr->rchild = np;
  258. np->parent = tr;
  259. return;
  260. }
  261. else {
  262. insert_node_to_nonempty_tree(tr->rchild, np);
  263. }
  264. }
  265. }

输出如下:

root: 18
depth: 2

root: 5
depth: 2

root: 5
depth: 3
root->lchild: 2

depth: 3
root->lchild: 3
root->lchild->lchild: 2

模板二:

   
   
  1. #ifndef HEAD_H_
  2. #define HEAD_H_
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. typedef int ElementType;
  6. typedef struct AvlNode // AVL树的节点
  7. {
  8. ElementType data;
  9. struct AvlNode *left; // 左孩子
  10. struct AvlNode *right; // 右孩子
  11. int Height;
  12. }*Position,*AvlTree;
  13. AvlTree MakeEmpty(AvlTree T);
  14. Position Find(ElementType x,AvlTree T);
  15. Position FindMin(AvlTree T);
  16. Position FindMax(AvlTree T);
  17. AvlTree Insert(ElementType x,AvlTree T);
  18. AvlTree Delete(ElementType x,AvlTree T);
  19. ElementType Retrieve(Position P);
  20. void Display(AvlTree T);
  21. #endif /* HEAD_H_ */
  22. /*
  23. * 初始化AVL树
  24. */
  25. AvlTree MakeEmpty(AvlTree T)
  26. {
  27. if( T != NULL)
  28. {
  29. MakeEmpty(T->left);
  30. MakeEmpty(T->right);
  31. free(T);
  32. }
  33. return NULL;
  34. }
  35. /*
  36. * 查找 可以像普通二叉查找树一样的进行,所以耗费O(log n)时间,因为AVL树总是保持平衡的。
  37. * 不需要特殊的准备,树的结构不会由于查找而改变。(这是与伸展树查找相对立的,它会因为查找而变更树结构。)
  38. */
  39. Position Find(ElementType x,AvlTree T)
  40. {
  41. if(T == NULL)
  42. return NULL;
  43. if(x < T->data)
  44. return Find(x,T->left);
  45. else if(x > T->data)
  46. return Find(x,T->right);
  47. else
  48. return T;
  49. }
  50. /*
  51. * FindMax,FindMin 查找最大和最小值,
  52. */
  53. Position FindMin(AvlTree T)
  54. {
  55. if(T == NULL)
  56. return NULL;
  57. if( T->left == NULL)
  58. return T;
  59. else
  60. return FindMin(T->left);
  61. }
  62. Position FindMax(AvlTree T)
  63. {
  64. if(T != NULL)
  65. while(T->right != NULL)
  66. T=T->right;
  67. return T;
  68. }
  69. /*
  70. * 返回节点的高度
  71. */
  72. static int Height(Position P)
  73. {
  74. if(P == NULL)
  75. return -1;
  76. else
  77. return P->Height;
  78. }
  79. static int Max(int h1,int h2)
  80. {
  81. return h1 > h2 ?h1:h2;
  82. }
  83. /*
  84. * 此函数用于k2只有一个左孩子的单旋转,
  85. * 在K2和它的左孩子之间旋转,
  86. * 更新高度,返回新的根节点
  87. */
  88. static Position SingleRotateWithLeft(Position k2) // LL旋转
  89. {
  90. Position k1;
  91. k1=k2->left;
  92. k2->left=k1->right;
  93. k1->right=k2;
  94. // 因为比较的是左右孩子的高度,所以求父节点的高度要加1
  95. k2->Height=Max(Height(k2->left),Height(k2->right)) + 1;
  96. k1->Height=Max(Height(k1->left),Height(k2->right)) + 1;
  97. return k1;
  98. }
  99. /*
  100. * 此函数用于k1只有一个右孩子的单旋转,
  101. * 在K1和它的右孩子之间旋转,
  102. * 更新高度,返回新的根节点
  103. */
  104. static Position SingleRotateWithRight(Position k1) // RR旋转
  105. {
  106. Position k2;
  107. k2=k1->right;
  108. k1->right=k2->left;
  109. k2->left=k1;
  110. /*结点的位置变了, 要更新结点的高度值*/
  111. k1->Height=Max(Height(k1->left),Height(k1->right)) + 1;
  112. k2->Height=Max(Height(k2->left),Height(k2->right)) + 1;
  113. return k2;
  114. }
  115. /*
  116. * 此函数用于当 如果 k3有一个左孩子,以及
  117. * 它的左孩子又有右孩子,执行这个双旋转
  118. * 更新高度,返回新的根节点
  119. */
  120. static Position DoubleRotateLeft(Position k3) // LR旋转
  121. {
  122. //在 k3 的左孩子,执行右侧单旋转
  123. k3->left=SingleRotateWithRight(k3->left);
  124. // 再对 k3 进行 左侧单旋转
  125. return SingleRotateWithLeft(k3);
  126. }
  127. /*
  128. * 此函数用于当 如果 k4有一个右孩子,以及
  129. * 它的右孩子又有左孩子,执行这个双旋转
  130. * 更新高度,返回新的根节点
  131. */
  132. static Position DoubleRotateRight(Position k4) // RL旋转
  133. {
  134. //在 k4 的右孩子,执行左侧单旋转
  135. k4->right = SingleRotateWithLeft(k4->right);
  136. // 再对 k4 进行 右侧单旋转
  137. return SingleRotateWithRight(k4);
  138. }
  139. /*
  140. * 向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,
  141. * 接着自底向上向根节点折回,于在插入期间成为不平衡的所有节点上进行旋转来完成。
  142. * 因为折回到根节点的路途上最多有1.5乘log n个节点,而每次AVL旋转都耗费恒定的时间,
  143. * 插入处理在整体上耗费O(log n) 时间。
  144. */
  145. AvlTree Insert(ElementType x,AvlTree T)
  146. {
  147. //如果T不存在,则创建一个节点树
  148. if(T == NULL)
  149. {
  150. T = (AvlTree)malloc(sizeof(struct AvlNode));
  151. {
  152. T->data = x;
  153. T->Height = 0;
  154. T->left = T->right = NULL;
  155. }
  156. }
  157. // 如果要插入的元素小于当前元素
  158. else if(x < T->data)
  159. {
  160. //递归插入
  161. T->left=Insert(x,T->left);
  162. //插入元素之后,若 T 的左子树比右子树高度 之差是 2,即不满足 AVL平衡特性,需要调整
  163. if(Height(T->left) - Height(T->right) == 2)
  164. {
  165. //把x插入到了T->left的左侧,只需 左侧单旋转
  166. if(x < T->left->data)
  167. T = SingleRotateWithLeft(T); // LL旋转
  168. else
  169. // x 插入到了T->left的右侧,需要左侧双旋转
  170. T = DoubleRotateLeft(T); // LR旋转
  171. }
  172. }
  173. // 如果要插入的元素大于当前元素
  174. else if(x > T->data)
  175. {
  176. T->right=Insert(x,T->right);
  177. if(Height(T->right) - Height(T->left) == 2)
  178. {
  179. if(x > T->right->data)
  180. T = SingleRotateWithRight(T); //RR 旋转
  181. else
  182. T = DoubleRotateRight(T); //RL旋转
  183. }
  184. }
  185. T->Height=Max(Height(T->left),Height(T->right)) + 1;
  186. return T;
  187. }
  188. /*
  189. * 对单个节点进行的AVL调整
  190. */
  191. AvlTree Rotate(AvlTree T)
  192. {
  193. if(Height(T->left) - Height(T->right) == 2)
  194. {
  195. if(Height(T->left->left) >= Height(T->left->right))
  196. T = SingleRotateWithLeft(T); // LL旋转
  197. else
  198. T = DoubleRotateLeft(T); // LR旋转
  199. }
  200. if(Height(T->right) - Height(T->left) == 2)
  201. {
  202. if(Height(T->right->right) >= Height(T->right->left))
  203. T = SingleRotateWithRight(T); // RR旋转
  204. else
  205. T = DoubleRotateRight(T); // RL旋转
  206. }
  207. return T;
  208. }
  209. /*
  210. * 首先定位要删除的节点,然后用该节点的右孩子的最左孩子替换该节点,
  211. * 并重新调整以该节点为根的子树为AVL树,具体调整方法跟插入数据类似
  212. * 删除处理在整体上耗费O(log n) 时间。
  213. */
  214. AvlTree Delete(ElementType x,AvlTree T)
  215. {
  216. if(T == NULL)
  217. return NULL;
  218. if(T->data == x) // 要删除的 x 等于当前节点元素
  219. {
  220. if(T->right == NULL ) // 若所要删除的节点 T 的右孩子为空,则直接删除
  221. {
  222. AvlTree tmp = T;
  223. T = T->left;
  224. free(tmp);
  225. }
  226. else /* 否则找到 T->right 的最左儿子代替 T */
  227. {
  228. AvlTree tmp = T->right;
  229. while(tmp->left)
  230. tmp=tmp->left;
  231. T->data = tmp->data;
  232. /* 对于替代后的T 即其字节点进行调整*/
  233. T->right = Delete(T->data,T->right);
  234. T->Height = Max(Height(T->left),Height(T->right))+1;
  235. }
  236. return T;
  237. }
  238. else if(x > T->data) // 要删除的 x 大于当前节点元素,在T的右子树中查找删除
  239. {
  240. T->right=Delete(x,T->right);
  241. }
  242. else // 要删除的 x 小于当前节点元素,在T的左子树中查找删除
  243. {
  244. T->left=Delete(x,T->left);
  245. }
  246. /*
  247. * 当删除元素后调整平衡
  248. */
  249. T->Height=Max(Height(T->left),Height(T->right)) + 1;
  250. if(T->left != NULL)
  251. T->left = Rotate(T->left);
  252. if(T->right != NULL)
  253. T->right = Rotate(T->right);
  254. if(T)
  255. T=Rotate(T);
  256. return T;
  257. }
  258. /*
  259. * 返回当前位置的元素
  260. */
  261. ElementType Retrieve(Position P)
  262. {
  263. return P->data;
  264. }
  265. /*
  266. * 遍历输出
  267. */
  268. void Display(AvlTree T)
  269. {
  270. static int n=0;
  271. if(NULL != T)
  272. {
  273. Display(T->left);
  274. printf("[%d] ndata=%d \n",++n,T->data);
  275. Display(T->right);
  276. }
  277. }
  278. #define N 15
  279. int main(void) {
  280. AvlTree T=NULL;
  281. int i;
  282. int j = 0;
  283. T = MakeEmpty( NULL );
  284. for( i = 0; i < N; i++, j = ( j + 7 ) % 50 )
  285. {
  286. printf("j=%d \n",j);
  287. T = Insert( j, T );
  288. }
  289. puts("插入 4 \n");
  290. T = Insert( 4, T );
  291. Display(T);
  292. for( i = 0; i < N; i += 2 )
  293. {
  294. printf("delelte: %d \n",i);
  295. T = Delete( i, T );//删除元素为i的节点
  296. }
  297. printf("detele:\n");
  298. printf("height=%d \n",T->Height);
  299. Display(T);
  300. printf( "Min is %d, Max is %d\n", Retrieve( FindMin( T ) ),
  301. Retrieve( FindMax( T ) ) );
  302. return 0;
  303. }
输出:
j=0
j=7
j=14
j=21
j=28
j=35
j=42
j=49
j=6
j=13
j=20
j=27
j=34
j=41
j=48
插入 4

[1] ndata=0
[2] ndata=4
[3] ndata=6
[4] ndata=7
[5] ndata=13
[6] ndata=14
[7] ndata=20
[8] ndata=21
[9] ndata=27
[10] ndata=28
[11] ndata=34
[12] ndata=35
[13] ndata=41
[14] ndata=42
[15] ndata=48
[16] ndata=49
delelte: 0
delelte: 2
delelte: 4
delelte: 6
delelte: 8
delelte: 10
delelte: 12
delelte: 14
detele:
height=3
[17] ndata=7
[18] ndata=13
[19] ndata=20
[20] ndata=21
[21] ndata=27
[22] ndata=28
[23] ndata=34
[24] ndata=35
[25] ndata=41
[26] ndata=42
[27] ndata=48
[28] ndata=49
Min is 7, Max is 49
     
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值