找回密码
 欢迎注册
查看: 12216|回复: 2

[提问] 红黑树删除操作的疑问

[复制链接]
发表于 2010-1-11 20:00:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
我照着<算法导论>上关于红黑树删除操作的伪代码编写了一个红黑树删除操作,但是测试的时候发现一直出现指针为空操作的异常,算法是完全照着书上的,不知道是书上的算法有问题还是怎么回事. 以下是红黑树的相关代码:
  1. #define and &&
  2. #define or ||
  3. #define NIL NULL
  4. class Node
  5. {
  6. public:
  7. int key;
  8. Node* left; //左孩子
  9. Node* right; //右孩子
  10. Node* parent; //父节点
  11. // int item;
  12. int color;
  13. Node()
  14. {
  15. left=NIL;
  16. right=NIL;
  17. parent=NIL;
  18. color=-1;
  19. }
  20. Node(int key)
  21. {
  22. this->key=key;
  23. left=NIL;
  24. right=NIL;
  25. parent=NIL;
  26. color=-1;
  27. }
  28. };
  29. class RedBlackTree
  30. {
  31. public:
  32. Node *root;
  33. Node* Successor(Node* node);
  34. void Insert(Node* node);
  35. void LeftRotate(Node* node);
  36. void RightRotate(Node* node);
  37. Node* Delete(Node* node);
  38. void InsertFixUp(Node* node);
  39. void DeleteFixUp(Node *node);
  40. Node* Search(int key);
  41. int getNodeNum()
  42. {
  43. return totalNodes;
  44. }
  45. RedBlackTree()
  46. {
  47. root=NIL;
  48. }
  49. };
复制代码
树的相关操作
  1. Node* RedBlackTree::Successor(Node* node)
  2. {
  3. Node* x=node;
  4. Node* y;
  5. if(node->right!=NIL)
  6. return Minimum(node->right);
  7. y=x->parent;
  8. while(y!=NIL and x==y->right)
  9. {
  10. x=y;
  11. y=y->parent;
  12. }
  13. return y;
  14. }
  15. Node* RedBlackTree::Search(int key)
  16. {
  17. Node* x=root;
  18. while((x!=NIL) and (x->key!=key))
  19. {
  20. if(key<x->key)
  21. x=x->left;
  22. else
  23. x=x->right;
  24. }
  25. return x;
  26. }
  27. void RedBlackTree::LeftRotate(Node* node)
  28. {
  29. Node* x=node;
  30. Node* y=node->right;
  31. if(x->right!=NIL and y!=NIL)
  32. x->right=y->left;//Turn y's left subtree into x's subtree
  33. if(y!=NIL and y->left!=NIL)
  34. y->left->parent=x;
  35. if(y!=NIL)
  36. y->parent=x->parent;//Link x's parent to y
  37. if(x->parent==NIL)
  38. root=y;
  39. else
  40. {
  41. if(x==x->parent->left)
  42. x->parent->left=y;
  43. else x->parent->right=y;
  44. }
  45. y->left=x;
  46. x->parent=y;
  47. }
  48. void RedBlackTree::RightRotate(Node* node)
  49. {
  50. Node* y=node;
  51. Node* x=node->left;
  52. y->left=x->right;
  53. if(x->right!=NIL)
  54. x->right->parent=y;
  55. x->parent=y->parent;
  56. if(y->parent==NIL)
  57. root=x;
  58. else
  59. {
  60. if(y==y->parent->left)
  61. y->parent->left=x;
  62. else y->parent->right=x;
  63. }
  64. x->right=y;
  65. y->parent=x;
  66. }
  67. void RedBlackTree::Insert(Node* node)
  68. {
  69. Node* x=root;
  70. Node* y=NIL;
  71. while(x!=NIL)
  72. {
  73. y=x;
  74. if(node->key<x->key)
  75. x=x->left;
  76. else x=x->right;
  77. }
  78. node->parent=y;
  79. if(y==NIL)
  80. root=node;
  81. else
  82. {
  83. if(node->key<y->key)
  84. y->left=node;
  85. else y->right=node;
  86. }
  87. node->left=NIL;
  88. node->right=NIL;
  89. node->color=RED;
  90. InsertFixUp(node);
  91. totalNodes++;
  92. }
  93. void RedBlackTree::InsertFixUp(Node* node)
  94. {
  95. Node* z=node;
  96. Node* y;
  97. while(z->parent!=NIL and z->parent->color==RED)
  98. {
  99. if(z->parent==z->parent->parent->left)
  100. {
  101. y=z->parent->parent->right;
  102. if(y!=NIL and y->color==RED)
  103. {
  104. z->parent->color=BLACK;
  105. y->color=BLACK;
  106. z->parent->parent->color=RED;
  107. z=z->parent->parent;
  108. }
  109. else
  110. {
  111. if(z==z->parent->right)
  112. {
  113. z=z->parent;
  114. LeftRotate(z);
  115. }
  116. z->parent->color=BLACK;
  117. z->parent->parent->color=RED;
  118. RightRotate(z->parent->parent);
  119. }
  120. }
  121. else
  122. {
  123. y=z->parent->parent->left;
  124. if(y!=NIL and y->color==RED)
  125. {
  126. z->parent->color=BLACK;
  127. y->color=BLACK;
  128. z->parent->parent->color=RED;
  129. z=z->parent->parent;
  130. }
  131. else
  132. {
  133. if(z==z->parent->left)
  134. {
  135. z=z->parent;
  136. RightRotate(z);
  137. }
  138. z->parent->color=BLACK;
  139. z->parent->parent->color=RED;
  140. LeftRotate(z->parent->parent);
  141. }
  142. }
  143. }
  144. root->color=BLACK;
  145. }
  146. Node* RedBlackTree::Delete(Node* node)
  147. {
  148. Node* z=node;
  149. Node* x;
  150. Node* y;
  151. if(z->left==NIL or z->right==NIL)
  152. y=z;
  153. else y=Successor(z);
  154. if(y->left!=NIL)
  155. x=y->left;
  156. else x=y->right;
  157. if(x!=NIL)
  158. x->parent=y->parent;
  159. if(y->parent==NIL)
  160. root=x;
  161. else
  162. {
  163. if(y==y->parent->left)
  164. y->parent->left=x;
  165. else y->parent->right=x;
  166. }
  167. if(y!=z)
  168. {
  169. z->key=y->key;
  170. z->color=y->color;
  171. //copy y's satellite data into z
  172. }
  173. if(y->color==BLACK)
  174. DeleteFixUp(x);
  175. totalNodes--;
  176. return y;
  177. }
  178. void RedBlackTree::DeleteFixUp(Node* node)
  179. {
  180. Node* x=node;
  181. Node* w;
  182. while(x!=root and x->color==BLACK)
  183. {
  184. if(x==x->parent->left)
  185. {
  186. w=x->parent->right;
  187. if(w->color==RED)
  188. {
  189. w->color=BLACK;
  190. x->parent->color=RED;
  191. LeftRotate(x->parent);
  192. w=x->parent->right;
  193. }
  194. if(w->left->color==BLACK and w->right->color==BLACK)
  195. {
  196. w->color=RED;
  197. x=x->parent;
  198. }
  199. else
  200. {
  201. if(w->right->color==BLACK)
  202. {
  203. w->left->color=BLACK;
  204. w->color=RED;
  205. RightRotate(w);
  206. w=x->parent->right;
  207. }
  208. w->color=x->parent->color;
  209. x->parent->color=BLACK;
  210. w->right->color=BLACK;
  211. LeftRotate(x->parent);
  212. x=root;
  213. }
  214. }
  215. else
  216. {
  217. w=x->parent->left;
  218. if(w->color==RED)
  219. {
  220. w->color=BLACK;
  221. x->parent->color=RED;
  222. RightRotate(x->parent);
  223. w=x->parent->left;
  224. }
  225. if(w->right->color==BLACK and w->left->color==BLACK)
  226. {
  227. w->color=RED;
  228. x=x->parent;
  229. }
  230. else
  231. {
  232. if(w->left->color==BLACK)
  233. {
  234. w->right->color=BLACK;
  235. w->color=RED;
  236. LeftRotate(w);
  237. w=x->parent->left;
  238. }
  239. w->color=x->parent->color;
  240. x->parent->color=BLACK;
  241. w->left->color=BLACK;
  242. RightRotate(x->parent);
  243. x=root;
  244. }
  245. }
  246. x->color=BLACK;
  247. }
  248. }
复制代码
测试函数:
  1. void main()
  2. {
  3. Node *node[100];
  4. Node *x;
  5. RedBlackTree t;
  6. //BinarySearchTree t;
  7. int key[]={5,3,8,2,4,7,9,1,6,10};
  8. int i,j,k;
  9. int n=sizeof(key)/sizeof(*key);
  10. for(i=0;i<n;i++)
  11. {
  12. node[i]=new Node(key[i]);
  13. t.Insert(node[i]);
  14. }
  15. printf("root->key=%d\n",t.root->key);
  16. printf("\n");//i=0;
  17. for(i=0;i<n;i++)
  18. {
  19. x=t.Delete(t.Search(i+1));
  20. printf("delete key=%d\n",x->key);
  21. printf("root->key=%d\n",t.root->key);
  22. printf("\n\n");
  23. }
  24. }
复制代码
每次运行循环进行了两次就出现了异常,通过Debug发现在第2轮循环DeleteFixUp操作中node为空指针,由此出现了异常.以上的DeleteFixUp是照着书上编的, 估计伪代码也有问题, 不知道如何改正
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-1-11 20:03:36 | 显示全部楼层
昨天在测试Insert操作时也出现了同样的情况,但是今天重新运行昨天的代码却又没有问题了.但是Delete操作一直有问题.
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-1-11 20:35:35 | 显示全部楼层
以下是仅能正常输出的部分,由于输出树形结构的代码很长,所以这里给出的代码仅输出根结点
bug.PNG
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-25 11:21 , Processed in 0.030106 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表