红黑树的实现(C++)

 

 

红黑树
  1// 红黑树的实现,详见《算法导论第二版》第163页。
  2#ifndef RBT_H
  3#define RBT_H
  4
  5namespace NTCI
  6{
  7    template<typename Type>
  8    class RBT
  9    {
 10    public:
 11        enum Color {RED, BLACK};
 12        class Node
 13        {
 14        public:
 15            Node() : color(BLACK), left(0), right(0), parent(0{}
 16            Type item;
 17            Color color;
 18            Node* left;
 19            Node* right;
 20            Node* parent;
 21        }
;
 22        typedef Node* Link;
 23
 24    public:
 25        RBT(Link r = Nil()) : root(r) {}
 26        template<typename InputIterator>
 27        RBT(InputIterator start, InputIterator end) : root(Nil())
 28        {
 29            for (InputIterator i = start; i != end; ++i)
 30                Insert(*i);
 31        }

 32
 33        virtual ~RBT()
 34        {
 35            Clear();
 36        }

 37
 38        static Link Nil()
 39        {
 40            static Node nil;
 41
 42            return &nil;
 43        }

 44
 45        void LeftRotate(Link link)
 46        {
 47            Link subr = link->right;
 48            if (subr == Nil())
 49                throw std::invalid_argument("待左旋的结点其右子树必须不为空");
 50
 51            subr->parent = link->parent;
 52            if (link->parent == Nil())
 53                root = subr;
 54            else if (link == link->parent->left)
 55                link->parent->left = subr;
 56            else
 57                link->parent->right = subr;
 58
 59            link->right = subr->left;
 60            if (subr->left != Nil())
 61                subr->left->parent = link;
 62
 63            subr->left = link;
 64            link->parent = subr;
 65        }

 66
 67        void RightRotate(Link link)
 68        {
 69            Link subl = link->left;
 70            if (subl == Nil())
 71                throw std::invalid_argument("待右旋的结点其左子树必须不为空");
 72
 73            subl->parent = link->parent;
 74            if (link->parent == Nil())
 75                root = subl;
 76            else if (link == link->parent->left)
 77                link->parent->left = subl;
 78            else
 79                link->parent->right = subl;
 80
 81            link->left = subl->right;
 82            if (subl->right != Nil())
 83                subl->right->parent = link;
 84
 85            subl->right = link;
 86            link->parent = subl;
 87        }

 88
 89        void Insert(Type item)
 90        {
 91            Link n = new Node();
 92            n->item = item;
 93            n->color = RED;
 94            n->left = Nil();
 95            n->right = Nil();
 96            n->parent = Nil();
 97
 98            InsertRBT(root, n);
 99            RBInsertFixup(n);
100        }

101
102        void RBInsertFixup(Link link)
103        {
104            while (link->parent->color == RED)
105            {
106                if (link->parent == link->parent->parent->left)
107                {
108                    Link runcle = link->parent->parent->right;
109
110                    if (runcle->color == RED)   // Case1
111                    {
112                        link->parent->color = BLACK;
113                        runcle->color = BLACK;
114                        link->parent->parent->color = RED;
115                        link = link->parent->parent;
116                    }

117                    else
118                    {
119                        if (link == link->parent->right)   // Case2
120                        {
121                            link = link->parent;
122                            LeftRotate(link);
123                        }

124
125                        link->parent->color = BLACK;
126                        link->parent->parent->color = RED;
127                        RightRotate(link->parent->parent);
128                    }

129                }

130                else
131                {
132                    Link luncle = link->parent->parent->left;
133
134                    if (luncle->color == RED)   // Case1
135                    {
136                        link->parent->color = BLACK;
137                        luncle->color = BLACK;
138                        link->parent->parent->color = RED;
139                        link = link->parent->parent;
140                    }

141                    else
142                    {
143                        if (link == link->parent->left)   // Case2
144                        {
145                            link = link->parent;
146                            RightRotate(link);
147                        }

148                        // Case3
149                        link->parent->color = BLACK;
150                        link->parent->parent->color = RED;
151                        LeftRotate(link->parent->parent);
152                    }

153                }

154            }

155
156            root->color = BLACK;
157        }

158
159        Link Remove(Link link)
160        {
161            // 删除空节点时抛出参数无效的异常。
162            if (link == Nil())
163                throw std::invalid_argument("待删除的结点为空");
164
165            // 先确定将要被删除的结点。如果结点只有一个或零个子结点,则原元素将被删除,
166            // 否侧其后继结点将被删除。
167            Link removed;
168            if (link->left == Nil() || link->right == Nil())
169                removed = link;
170            else
171                removed = Successor(link);
172
173            // 待删除的元素至多只有一个子结点。
174            Link child;
175            if (link->left != Nil())
176                child = removed->left;
177            else
178                child = removed->right;
179
180            // 先设置子结点的新的父节点。
181            child->parent = removed->parent;
182
183            // 如果待删除的结点为根节点,直接将根结点设置为子结点,
184            if (removed->parent == Nil())
185                root = child;
186            // 否则将待删除结点的父节点的子结点指向待删除结点的子结点。
187            else if (removed == removed->parent->left)
188                removed->parent->left = child;
189            else
190                removed->parent->right = child;
191
192            // 如果原结点和被删除的结点不同,则说明原结点具有两个子结点,此时需要将
193            // 被删除结点的值复制到原结点。
194            if (link != removed)
195                link->item = removed->item;
196
197            if (removed->color == BLACK)
198                RBRemoveFixup(child);
199            return removed;
200        }

201
202        void RBRemoveFixup(Link link)
203        {
204            while (link != root && link->color == BLACK)
205            {
206                if (link == link->parent->left)
207                {
208                    Link rbro = link->parent->right;
209                    if (rbro->color == RED) // Case1
210                    {
211                        rbro->color = BLACK;
212                        link->parent->color = RED;
213                        LeftRotate(link->parent);
214                        rbro = link->parent->right;
215                    }

216                    if (rbro->left->color == BLACK && rbro->right->color == BLACK)  // Case2
217                    {
218                        rbro->color = RED;
219                        link = link->parent;
220                    }

221                    else
222                    {
223                        if (rbro->right->color == BLACK)
224                        {
225                            rbro->left->color = BLACK;
226                            rbro->color = RED;
227                            RightRotate(rbro);
228                            rbro = link->parent->right;
229                        }

230                        rbro->color = link->parent->color;
231                        link->parent->color = BLACK;
232                        rbro->right->color = BLACK;
233                        LeftRotate(link->parent);
234                        link = root;
235                    }

236                }

237                else
238                {
239                    Link lbro = link->parent->left;
240                    if (lbro->color == RED) // Case1
241                    {
242                        lbro->color = BLACK;
243                        link->parent->color = RED;
244                        RightRotate(link->parent);
245                        lbro = link->parent->left;
246                    }

247                    if (lbro->right->color == BLACK && lbro->left->color == BLACK)  // Case2
248                    {
249                        lbro->color = RED;
250                        link = link->parent;
251                    }

252                    else
253                    {
254                        if (lbro->left->color == BLACK)
255                        {
256                            lbro->right->color = BLACK;
257                            lbro->color = RED;
258                            LeftRotate(lbro);
259                            lbro = link->parent->left;
260                        }

261                        lbro->color = link->parent->color;
262                        link->parent->color = BLACK;
263                        lbro->left->color = BLACK;
264                        RightRotate(link->parent);
265                        link = root;
266                    }

267                }

268            }

269            link->color = BLACK;
270        }

271
272        Link Remove(Type item)
273        {
274            Link link = Search(item);
275            return Remove(link);
276        }

277
278        Link Search(Type item)
279        {
280            return SearchRBT(root, item);
281        }

282
283        int Maximum()
284        {
285            Link max = MaximumRBT(root);
286            if (max == 0)
287                throw std::out_of_range("红黑树为空");
288            return max->item;
289        }

290
291        int Minimun()
292        {
293            Link min = MinimunRBT(root);
294            if (min == 0)
295                throw std::out_of_range("红黑树为空");
296            return min->item;
297        }

298
299        void InorderWalk(std::ostream& out)
300        {
301            InorderWalkRBT(root, out);
302        }

303
304        Link Successor(Link link)
305        {
306            // 如果右子结点不为空,则返回右子树的最小结点,
307            if (link->right != Nil())
308                return MinimunRBT(link->right);
309
310            // 否则后继元素是一个祖先结点,该结点的左子结点也是祖先结点。
311            Link p = link->parent;
312            while (p != Nil() && link == p->right)
313            {
314                link = p;
315                p = link->parent;
316            }

317
318            return p;
319        }

320
321        Link Predecessor(Link link)
322        {
323            if (link->left != Nil())
324                return MaximumRBT(link->left);
325
326            Link p = link->parent;
327            while (p != Nil() && link == p->left)
328            {
329                link = p;
330                p = link->parent;
331            }

332
333            return p;
334        }

335
336        int Heigth()
337        {
338            return HeightRBT(root);
339        }

340
341        int Length()
342        {
343            return LengthRBT(root);
344        }

345
346        void Clear()
347        {
348            ClearRBT(root);
349        }

350
351    private:
352        void InsertRBT(Link& link, Link n)
353        {
354            if (link == RBT::Nil())
355            {
356                link = n;
357                return;
358            }

359
360            if (n->item < link->item)
361            {
362                if (link->left == RBT::Nil())
363                {
364                    n->parent = link;
365                    link ->left = n;
366                }

367                else
368                    InsertRBT(link->left, n);
369            }

370            else
371            {
372                if (link->right == RBT::Nil())
373                {
374                    n->parent = link;
375                    link->right = n;
376                }

377                else
378                    InsertRBT(link->right, n);
379            }

380
381        }

382
383        Link SearchRBT(Link link, Type item)
384        {
385            if (link == Nil() || link->item == item)
386                return link;
387            if (link->item > item)
388                return SearchRBT(link->left, item);
389            else
390                return SearchRBT(link->right, item);
391        }

392
393        void InorderWalkRBT(Link link, std::ostream& out)
394        {
395            if (link == Nil())
396                return;
397
398            InorderWalkRBT(link->left, out);
399            out << link->item << " ";
400            InorderWalkRBT(link->right, out);
401        }

402
403        Link MaximumRBT(Link link)
404        {
405            while (link->right != Nil())
406                link = link->right;
407            return link;
408        }

409
410        Link MinimunRBT(Link link)
411        {
412            while (link->left != Nil())
413                link = link->left;
414            return link;
415        }

416
417        int HeightRBT(Link link)
418        {
419            if (link == Nil())
420                return 0;
421
422            int lh, rh;
423            lh = HeightRBT(link->left);
424            rh = HeightRBT(link->right);
425            return std::max(lh, rh) + 1;
426        }

427
428
429        int LengthRBT(Link link)
430        {
431            if (link == Nil())
432                return 0;
433            return LengthRBT(link->left) + LengthRBT(link->right) + 1;
434        }

435
436        void ClearRBT(Link& link)
437        {
438            if (link == Nil())
439                return;
440            ClearRBT(link->left);
441            ClearRBT(link->right);
442            delete link;
443
444            link = Nil();
445        }

446
447    private:
448        Link root;
449    }
;
450}

451
452#endif // RBT_H
453

 

 

测试代码
 1#include <iostream>
 2#include <cassert>
 3#include <stdexcept>
 4#include "RBT.h"
 5
 6using namespace std;
 7using namespace NTCI;
 8
 9int main()
10{
11    try
12    {
13        int array[] = {54726892012161114};
14        RBT<int> rbt(array, array + 12);
15
16        cout << "排序后:";
17        rbt.InorderWalk(cout);
18        cout << endl;
19
20        RBT<int>::Link link = rbt.Search(5);
21        assert(rbt.Successor(link)->item == 6);
22        assert(rbt.Predecessor(link)->item == 4);
23        cout << "红黑树高度:" << rbt.Heigth() << endl;
24        cout << "最大值:" << rbt.Maximum() << endl;
25        cout << "最小值:" << rbt.Minimun() << endl;
26
27        rbt.Remove(9);
28
29        link = rbt.Search(7);
30        assert(link->item == 7);
31
32        link = rbt.Remove(link);
33        delete link;
34        assert(rbt.Length() == 10);
35        cout << "删除元素7后:";
36        rbt.InorderWalk(cout);
37        cout << endl;
38
39        rbt.Clear();
40        assert(rbt.Length() == 0);
41
42    }

43    catch (exception& e)
44    {
45        cout << "发生异常:" << e.what() << endl;
46    }

47    return 0;
48}

 

 

你可能感兴趣的:(红黑树的实现(C++))