二叉查找树(BST)的实现(C++)

ContractedBlock.gif ExpandedBlockStart.gif 二叉搜索树的实现
  1//二叉搜索树的实现,其原理参见《算法导论第二版》第151页。
  2
  3#ifndef BST_H
  4#define BST_H
  5
  6#include <iostream>
  7#include <stdexcept>
  8
  9namespace NTCI
 10ExpandedBlockStart.gifContractedBlock.gif{
 11    template<typename Type>
 12    class BST
 13ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 14    public:
 15        struct Node
 16ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 17            Type item;
 18            Node* left;
 19            Node* right;
 20            Node* parent;
 21        }
;
 22        typedef Node* Link;
 23
 24    public:
 25ExpandedSubBlockStart.gifContractedSubBlock.gif        BST(Link r = 0) : root(r) {}
 26        template<typename InputIterator>
 27        BST(InputIterator start, InputIterator end) : root(0)
 28ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 29            for (InputIterator i = start; i != end; ++i)
 30                Insert(*i);
 31        }

 32
 33        virtual ~BST()
 34ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 35            Clear();
 36        }

 37        void Insert(Type item)
 38ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 39            Link n = new Node();
 40            n->item = item;
 41            InsertBST(root, n);
 42        }

 43
 44        Link Remove(Link link)
 45ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 46            // 删除空节点时抛出参数无效的异常。
 47            if (link == 0)
 48                throw std::invalid_argument("待删除的结点为空");
 49
 50            // 先确定将要被删除的结点。如果结点只有一个或零个子结点,则原元素将被删除,
 51            // 否侧其后继结点将被删除。
 52            Link removed;
 53            if (link->left == 0 || link->right == 0)
 54                removed = link;
 55            else
 56                removed = Successor(link);
 57
 58            // 待删除的元素至多只有一个子结点。
 59            Link child = 0;
 60            if (link->left != 0)
 61                child = removed->left;
 62            else
 63                child = removed->right;
 64
 65            // 先设置子结点的新的父节点。
 66            if (child != 0)
 67                child->parent = removed->parent;
 68
 69            // 如果待删除的结点为根节点,直接将根结点设置为子结点,
 70            if (removed->parent == 0)
 71                root = child;
 72            // 否则将待删除结点的父节点的子结点指向待删除结点的子结点。
 73            else if (removed == removed->parent->left)
 74                removed->parent->left = child;
 75            else
 76                removed->parent->right = child;
 77
 78            // 如果原结点和被删除的结点不同,则说明原结点具有两个子结点,此时需要将
 79            // 被删除结点的值复制到原结点。
 80            if (link != removed)
 81                link->item = removed->item;
 82
 83            return removed;
 84        }

 85
 86        Link Remove(Type item)
 87ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 88            Link link = Search(item);
 89            return Remove(link);
 90        }

 91
 92        Link Search(Type item)
 93ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 94            return SearchBST(root, item);
 95        }

 96
 97        int Maximum()
 98ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 99            Link max = MaximumBST(root);
100            if (max == 0)
101                throw std::out_of_range("二叉搜索树为空");
102            return max->item;
103        }

104
105        int Minimun()
106ExpandedSubBlockStart.gifContractedSubBlock.gif        {
107            Link min = MinimunBST(root);
108            if (min == 0)
109                throw std::out_of_range("二叉搜索树为空");
110            return min->item;
111        }

112
113        void InorderWalk(std::ostream& out)
114ExpandedSubBlockStart.gifContractedSubBlock.gif        {
115            InorderWalkBST(root, out);
116        }

117
118        Link Successor(Link link)
119ExpandedSubBlockStart.gifContractedSubBlock.gif        {
120            // 如果右子结点不为空,则返回右子树的最小结点,
121            if (link->right != 0)
122                return MinimunBST(link->right);
123
124            // 否则后继元素是一个祖先结点,该结点的左子结点也是祖先结点。
125            Link p = link->parent;
126            while (p != 0 && link == p->right)
127ExpandedSubBlockStart.gifContractedSubBlock.gif            {
128                link = p;
129                p = link->parent;
130            }

131
132            return p;
133        }

134
135        Link Predecessor(Link link)
136ExpandedSubBlockStart.gifContractedSubBlock.gif        {
137            if (link->left != 0)
138                return MaximumBST(link->left);
139
140            Link p = link->parent;
141            while (p != 0 && link == p->left)
142ExpandedSubBlockStart.gifContractedSubBlock.gif            {
143                link = p;
144                p = link->parent;
145            }

146
147            return p;
148        }

149
150        int Heigth()
151ExpandedSubBlockStart.gifContractedSubBlock.gif        {
152            return HeightBST(root);
153        }

154
155        int Length()
156ExpandedSubBlockStart.gifContractedSubBlock.gif        {
157            return LengthBST(root);
158        }

159
160        void Clear()
161ExpandedSubBlockStart.gifContractedSubBlock.gif        {
162            ClearBST(root);
163        }

164
165        void InsertBST(Link& root, Link n)
166ExpandedSubBlockStart.gifContractedSubBlock.gif        {
167            if (root == 0)
168ExpandedSubBlockStart.gifContractedSubBlock.gif            {
169                root = n;
170                return;
171            }

172
173            if (n->item < root->item)
174ExpandedSubBlockStart.gifContractedSubBlock.gif            {
175                if (root->left == 0)
176ExpandedSubBlockStart.gifContractedSubBlock.gif                {
177                    n->parent = root;
178                    root ->left = n;
179                }

180                else
181                    InsertBST(root->left, n);
182            }

183            else
184ExpandedSubBlockStart.gifContractedSubBlock.gif            {
185                if (root->right == 0)
186ExpandedSubBlockStart.gifContractedSubBlock.gif                {
187                    n->parent = root;
188                    root->right = n;
189                }

190                else
191                    InsertBST(root->right, n);
192            }

193
194        }

195    private:
196        Link SearchBST(Link root, Type item)
197ExpandedSubBlockStart.gifContractedSubBlock.gif        {
198            if (root == 0 || root->item == item)
199                return root;
200            if (root->item > item)
201                return SearchBST(root->left, item);
202            else
203                return SearchBST(root->right, item);
204        }

205
206        void InorderWalkBST(Link root, std::ostream& out)
207ExpandedSubBlockStart.gifContractedSubBlock.gif        {
208            if (root == 0)
209                return;
210
211            InorderWalkBST(root->left, out);
212            out << root->item << " ";
213            InorderWalkBST(root->right, out);
214        }

215
216        Link MaximumBST(Link link)
217ExpandedSubBlockStart.gifContractedSubBlock.gif        {
218            while (link->right != 0)
219                link = link->right;
220            return link;
221        }

222
223        Link MinimunBST(Link link)
224ExpandedSubBlockStart.gifContractedSubBlock.gif        {
225            while (link->left != 0)
226                link = link->left;
227            return link;
228        }

229
230        int HeightBST(Link root)
231ExpandedSubBlockStart.gifContractedSubBlock.gif        {
232            if (root == 0)
233                return 0;
234
235            int lh, rh;
236            lh = HeightBST(root->left);
237            rh = HeightBST(root->right);
238            return std::max(lh, rh) + 1;
239        }

240
241
242        int LengthBST(Link root)
243ExpandedSubBlockStart.gifContractedSubBlock.gif        {
244            if (root == 0)
245                return 0;
246            return LengthBST(root->left) + LengthBST(root->right) + 1;
247        }

248
249        void ClearBST(Link& root)
250ExpandedSubBlockStart.gifContractedSubBlock.gif        {
251            if (root == 0)
252                return;
253            ClearBST(root->left);
254            ClearBST(root->right);
255            delete root;
256
257            root = 0;
258        }

259
260    private:
261        Link root;
262    }
;
263}

264
265#endif // BST_H
266

 

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

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

46
47    return 0;
48}

49

 

要实现随机构造的二叉查找树很容易,先调用标准库的random_shuffle函数对数组进行随机重排,然后再构造二叉搜索树就OK了~

欢迎大家就程序正确性以及代码风格等方面提出建议~

转载于:https://www.cnblogs.com/zyobi/archive/2009/05/06/1451006.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内含资源如下: 1.基本数据结构 1.1.Array ........... 动态数组 1.2.LinkedList ... 链表 1.3.BST .............. 二分搜索树 1.4.MapBST ..... 二分搜索树(用于实现映射) 1.5.AVLTree ...... AVL树 2.接口 2.1.Queue ........... 队列接口 2.2.Stack .............. 栈接口 2.3.Set .................. 集合接口 2.4.Map ............... 映射接口 2.5.Merger .......... 自定义函数接口 2.6.UnionFind ..... 并查集接口 3.高级数据结构 3.1.ArrayQueue .......................... 队列_基于动态数组实现 3.2.LinkedListQueue .................. 队列__基于链表实现 3.3.LoopQueue ........................... 循环队列_基于动态数组实现 3.4.PriorityQueue ....................... 优先队列_基于最大二叉堆实现 3.5.ArrayPriorityQueue ............. 优先队列_基于动态数组实现 3.6.LinkedListPriorityQueue ..... 优先队列_基于链表实现 3.7.ArrayStack ............................. 栈_基于动态数组实现 3.8.LinkedListStack ..................... 栈_基于链表实现 3.9.BSTSet ..................................... 集合_基于二分搜索树实现 3.10.LinkedListSet ....................... 集合_基于链表实现 3.11.BSTMap ................................ 映射_基于二分搜索树实现 3.12.AVLTreeMap ....................... 映射_ 基于AVL树实现 3.13.LinkedListMap .................... 映射_基于链表实现 3.14.MaxHeap ............................. 最大二叉堆 3.15.SegmentTree ...................... 线段树 3.16.Trie ......................................... 字典树 3.17.QuickFind ............................ 并查集_基于数组实现 3.18.QuickUnion ......................... 并查集_基于树思想实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值