二叉查找树

6/20/2022 algorithm

# 介绍

二叉查找树(Binary Search Tree),又被称为二叉搜索树。 它是特殊的二叉树:对于二叉树,假设x为二叉树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x]。如果y是x的左子树中的一个结点,则key[y] <= key[x];如果y是x的右子树的一个结点,则key[y] >= key[x]。那么,这棵树就是二叉查找树.

具体讲解见 https://www.cnblogs.com/skywang12345/p/3576373.html

需要注意的是插入删除

这里说一下链表实现。

#pragma once
#include <iostream>
#include <iomanip>

using namespace std;
template <typename T>
class BSTNode {
public:
    T key;
    BSTNode* parent = nullptr;
    BSTNode* left = nullptr;
    BSTNode* right = nullptr;
    BSTNode(T value) : key(value) {}
    ~BSTNode() {
        cout << "delete : " << key << endl;
    }
};

template <typename T>
class BSTTree {
public:
    BSTTree();
    ~BSTTree();

    // 三序遍历
    void preOrder();
    void inOrder();
    void postOrder();

    // (递归实现)查找"二叉树"中键值为key的节点
    BSTNode<T>* search(T key);
    // (非递归实现)查找"二叉树"中键值为key的节点
    BSTNode<T>* iterativeSearch(T key);
    // 查找最小结点:返回最小结点的键值。
    T minimum();
    // 查找最大结点:返回最大结点的键值。
    T maximum();

    // 找结点(x)的后继结点。即,查找"二叉树中数据值大于该结点"的"最小结点"。
    BSTNode<T>* successor(BSTNode<T>* x);
    // 找结点(x)的前驱结点。即,查找"二叉树中数据值小于该结点"的"最大结点"。
    BSTNode<T>* predecessor(BSTNode<T>* x);

    // 将结点(key为节点键值)插入到二叉树中
    void insert(T key);

    // 删除结点(key为节点键值)
    void remove(T key);

    // 销毁二叉树
    void destroy();

    // 打印二叉树
    void print();
    
private:
    // 前序遍历"二叉树"
    void preOrder(BSTNode<T>* tree) const;
    // 中序遍历"二叉树"
    void inOrder(BSTNode<T>* tree) const;
    // 后序遍历"二叉树"
    void postOrder(BSTNode<T>* tree) const;

    // (递归实现)查找"二叉树x"中键值为key的节点
    BSTNode<T>* search(BSTNode<T>* x, T key) const;
    // (非递归实现)查找"二叉树x"中键值为key的节点
    BSTNode<T>* iterativeSearch(BSTNode<T>* x, T key) const;

    // 查找最小结点:返回tree为根结点的二叉树的最小结点。
    BSTNode<T>* minimum(BSTNode<T>* tree);
    // 查找最大结点:返回tree为根结点的二叉树的最大结点。
    BSTNode<T>* maximum(BSTNode<T>* tree);
    // 将结点(z)插入到二叉树(tree)中
    void insert(BSTNode<T>*& tree, BSTNode<T>* z);
    // 删除二叉树(tree)中的结点(z),并返回被删除的结点
    BSTNode<T>* remove(BSTNode<T>*& tree, BSTNode<T>* z);
    // 销毁二叉树
    void destroy(BSTNode<T>*& tree);
    // 打印二叉树
    void print(BSTNode<T>* tree, T key, int direction);

    BSTNode<T>* mRoot = nullptr;
};

template<typename T>
inline BSTTree<T>::BSTTree()
{
}

template<typename T>
inline BSTTree<T>::~BSTTree()
{
    destroy();
}

template<typename T>
inline void BSTTree<T>::insert(T value)
{
    BSTNode<T>* node = new BSTNode<T>(value);
    if (node == nullptr) {
        return;
    }
    insert(mRoot, node);
}

template<typename T>
inline void BSTTree<T>::remove(T key)
{
    BSTNode<T>* z;
    BSTNode<T>* node;
    z = search(mRoot, key);
    if (z) {
        node = remove(mRoot, z);
        if (node) {
            delete node;
        }
    }
}

template<typename T>
inline void BSTTree<T>::destroy()
{
    if (mRoot) {
        destroy(mRoot);
    }
}

template<typename T>
inline void BSTTree<T>::print()
{
    if (mRoot) {
        print(mRoot, mRoot->key, 0);
    }
}

template<typename T>
inline void BSTTree<T>::preOrder(BSTNode<T>* tree) const
{
    if (tree) {
        cout << tree->key << " ";
        preOrder(tree->left);
        preOrder(tree->right);
    }
}

template<typename T>
inline void BSTTree<T>::inOrder(BSTNode<T>* tree) const
{
    if (tree) {
        inOrder(tree->left);
        cout << tree->key << " ";
        inOrder(tree->right);
    }
}

template<typename T>
inline void BSTTree<T>::postOrder(BSTNode<T>* tree) const
{
    if (tree) {
        postOrder(tree->left);
        postOrder(tree->right);
        cout << tree->key << " ";
    }
}

template<typename T>
inline void BSTTree<T>::preOrder()
{
    preOrder(mRoot);
    cout << endl;
}

template<typename T>
inline void BSTTree<T>::inOrder()
{
    inOrder(mRoot);
    cout << endl;
}

template<typename T>
inline void BSTTree<T>::postOrder()
{
    postOrder(mRoot);
    cout << endl;
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::search(T key)
{
    return search(mRoot, key);
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::iterativeSearch(T key)
{
    return iterativeSearch(mRoot, key);
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::search(BSTNode<T>* x, T key) const
{
    if (x == nullptr || x->key == key) {
        return x;
    }
    if (key < x->key) {
        return search(x->left, key);
    }
    else {
        return search(x->right, key);
    }
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::iterativeSearch(BSTNode<T>* x, T key) const
{
    while (x != nullptr && x->key != key) {
        if (key < x->key) {
            x = x->left;
        }
        else {
            x = x->right;
        }
    }
    return x;
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::minimum(BSTNode<T>* tree)
{
    if (tree == nullptr) {
        return nullptr;
    }
    while (tree->left) {
        tree = tree->left;
    }
    return tree;
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::maximum(BSTNode<T>* tree)
{
    if (tree == nullptr) {
        return nullptr;
    }
    while (tree->right) {
        tree = tree->right;
    }
    return tree;
}

template<typename T>
inline void BSTTree<T>::insert(BSTNode<T>*& tree, BSTNode<T>* z)
{
    BSTNode<T>* y = nullptr;
    BSTNode<T>* x = tree;
    while (x) {
        y = x;
        if (z->key < x->key) {
            x = x->left;
        }
        else {
            x = x->right;
        }
    }

    z->parent = y;
    if (y == nullptr) {
        tree = z;
    }
    else if (z->key < y->key) {
        y->left = z;
    }
    else {
        y->right = z;
    }
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::remove(BSTNode<T>*& tree, BSTNode<T>* z)
{
    BSTNode<T>* x = nullptr;
    BSTNode<T>* y = nullptr;
    if ((z->left == nullptr) || (z->right == nullptr)) {
        y = z;
    }
    else {
        y = successor(z);
    }

    if (y->left) {
        x = y->left;
    }
    else {
        x = y->right;
    }

    if (x) {
        x->parent = y->parent;
    }

    if (y->parent == nullptr) {
        tree = x;
    }
    else if (y == y->parent->left) {
        y->parent->left = x;
    }
    else {
        y->parent->right = x;
    }

    if (y != z) {
        z->key = y->key;
    }
    return y;
}

template<typename T>
inline void BSTTree<T>::destroy(BSTNode<T>*& tree)
{
    if (tree == nullptr) {
        return;
    }
    if (tree->left) {
        destroy(tree->left);
    }

    if (tree->right) {
        destroy(tree->right);
    }

    delete tree;
    tree = nullptr;
}

template<typename T>
inline void BSTTree<T>::print(BSTNode<T>* tree, T key, int direction)
{
    if (tree != nullptr)
    {
        if (direction == 0)    // tree是根节点
            cout << setw(2) << tree->key << " is root" << endl;
        else                // tree是分支节点
            cout << setw(2) << tree->key << " is " << setw(2) << key << "'s " << setw(12) << (direction == 1 ? "right child" : "left child") << endl;

        print(tree->left, tree->key, -1);
        print(tree->right, tree->key, 1);
    }
}

template<typename T>
inline T BSTTree<T>::minimum()
{
    BSTNode<T>* min = minimum(mRoot);
    if (min) {
        return min->key;
    }
    return T();
}

template<typename T>
inline T BSTTree<T>::maximum()
{
    BSTNode<T>* max = maximum(mRoot);
    if (max) {
        return max->key;
    }
    return T();
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::successor(BSTNode<T>* x)
{
    // 如果x存在左孩子,则"x的前驱结点"为 "以其左孩子为根的子树的最大结点"。
    if (x->left) {
        return maximum(x->left);
    }
    // 如果x没有左孩子。则x有以下两种可能:
    // (01) x是"一个右孩子",则"x的前驱结点"为 "它的父结点"。
    // (02) x是"一个左孩子",则查找"x的最低的父结点,并且该父结点要具有右孩子",找到的这个"最低的父结点"就是"x的前驱结点"
    BSTNode<T>* node = x->parent;
    while (node && x == node->left) {
        x = node;
        node = node->parent;
    }
    return node;
}

template<typename T>
inline BSTNode<T>* BSTTree<T>::predecessor(BSTNode<T>* x)
{
    // 如果x存在右孩子,则"x的后继结点"为 "以其右孩子为根的子树的最小结点"。
    if (x->right != nullptr) {
        return minimum(x->right);
    }
    // 如果x没有右孩子。则x有以下两种可能:
    // (01) x是"一个左孩子",则"x的后继结点"为 "它的父结点"。
    // (02) x是"一个右孩子",则查找"x的最低的父结点,并且该父结点要具有左孩子",找到的这个"最低的父结点"就是"x的后继结点"。
    BSTNode<T>* node = x->parent;
    while (node && node->right == x) {
        x = node;
        node = node->parent;
    }
    return node;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405

这里全部写在 .h文件的原因是使用了模板类,如果实现写在cpp文件中,使用的时候要加上#include "xxx.cpp"。因为模板类在使用的时候才知道具体要变成什么类型的函数。否则会报错

    int arr[] = { 1,5,4,3,2,6 };
    int i, ilen;
    BSTTree<int>* tree = new BSTTree<int>();

    cout << "== 依次添加: ";
    ilen = sizeof(arr) / sizeof(int);
    for (i = 0; i < ilen; i++)
    {
        cout << arr[i] << " ";
        tree->insert(arr[i]);
    }

    cout << "\n== 前序遍历: ";
    tree->preOrder();

    cout << "\n== 中序遍历: ";
    tree->inOrder();

    cout << "\n== 后序遍历: ";
    tree->postOrder();
    cout << endl;

    cout << "== 最小值: " << tree->minimum() << endl;
    cout << "== 最大值: " << tree->maximum() << endl;
    cout << "== 树的详细信息: " << endl;
    tree->print();

    cout << "\n== 删除根节点: " << arr[3];
    tree->remove(arr[3]);

    cout << "\n== 中序遍历: ";
    tree->inOrder();
    cout << endl;

    // 销毁二叉树
    tree->destroy();
    delete tree;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38