创建一颗二叉链表的树 5个域 中序线索化_从零开始学习数据结构>二叉搜索树(BST)...

BST(Binary Search Tree):核心是为了提高查找性能,其查找时间复杂度在log(N) 级别,接近二分查找,查询效率相当高。 1、二叉搜索树

(1)、逼近二分查找的查找算法;

(2)、一般不允许出现重复数字,不然没法存储;

(3)、满足:左孩子数据 < 根结点数据 < 右孩子数据;根(父)结点比左孩子的大,比右孩子的小;

(4)、左子树和右子树也是二叉搜索树。

2、为什么叫二叉搜索树

如果对一颗二叉搜索树进行中序遍历,可以按从小到大的顺序输出,此时又叫做二叉排序树。

如图:

88471dd9faa2bb38026c961918694731.png

3、小堆

堆的构造,i>数组直接生成堆(向下调整),ii>插入创建堆(向上调整);

(1)、怎么实现一次调整?

9396262955e437e11c946b9760ecd27f.png

找到最后一个非叶子结点,n/2-1;一直往下调整即可!

(2)、堆排----->优先级队列

堆的删除,只能是堆顶元素,再拿最后一个元素补充上去。在向下做一次调整。形成新的堆结构(满足堆的性质),将删除的数字输出就是堆排。

小堆:根(父)小于左右结点;最小的数字先出;

大堆:根(父)大于左右结点;最大的数字先出;因而,进行堆排序就是优先级队列!

859f5d4ea66355d07554c07bbe8ca601.png

4、线索二叉树的查找父结点图形解释

利用空指针指向前驱、后继结点。

2e39665e2f39bf8112576b9dc8a2873e.png

5、编程时 const 一些注意

(1)、在C++中,当我们传的是常量时,引用接收时,形参必须const类型接受,否则出错!

常量必须常引用接受。

1int find(32);   23int find(const int &value);

(2)、typedef void  *IP

const IP m;怎么理解?

因为IP是数据类型,const和数据类型可以互换位置;const IP m; <==> IP const m;  即 void *const m; m 是一个指针,其指向不能更改,其指向的空间数据可以更改!

6、搜索二叉树上的操作

全部用 C++ 实现的。

(1)、之前学习二叉树,并没有说什么插入,删除操作,那是因为,没有规律而言,怎么进行操作呢?搜索二叉树的规律如此明显,那么插入,删除必是重中之重!

(2)、我们输入相同的数字,但是顺序不同的话,生成的搜索二叉树是不一样的!  

例:int ar[] = {3, 7, 9, 1, 0, 6, 4, 2,}; 和int ar[] = {7, 3, 9, 1, 0, 6, 4, 2,}; 生成的搜索二叉树不一样。

39e5e8885efd8c3ba208f0653e21fabd.png

(3)、插入函数

利用搜索二叉树的性质:

 1void insert(BSTreeNode *&t, const Type &x){
2    if(t == NULL){
3        t = new BSTreeNode(x); 4        return; 5    }else if(x data){ 6        insert(t->leftChild, x); 7    }else if(x > t->data){ 8        insert(t->rightChild, x); 9    }else{10        return;11    }    12}

(4)、删除函数

思想:要删除一个有左孩子或右孩子或是叶子结点,看成一种情况,做法:保存要删除的结点,因为传的是引用,可以直接修改上一个结点的左孩子或右孩子,使其跨过当前的直指下一个结点,在释放当前的结点空间。

第二种情况:就是要删除的既有左子树,又有右子树,此时可以有两种做法:i>找左子树最大的数字,覆盖要删除的数字,在往左子树找这个数字删除-->递归!ii>找右子树最小的数字,覆盖要删除的数字,在往右子树找这个数字删除-->递归!

第一种情况图形想法如下:

d993ff1d5175af4c9ff42ae289abaa2b.png

删除左边和删除右边,还有是叶子结点,想法一样。

第二种情况图形想法如下:

be2860321437af38f3a65cd56c48668e.png

代码如下:

 1bool remove(BSTreeNode *&t, const Type &key){
2    if(t == NULL){  //t传的是引用,每次可以进行直接更改!
3        return false;
4    }
5
6    if(key data){
7        remove(t->leftChild, key);
8    }else if(key > t->data){
9        remove(t->rightChild, key);
10    }else{
11        if(t->leftChild != NULL && t->rightChild != NULL){  //第二种情况
12            BSTreeNode *p = t->rightChild;13            while(p->leftChild != NULL){14                p = p->leftChild;15            }16            t->data = p->data;17            remove(t->rightChild, p->data);  //在右树找p->data的数字进行删除;18        }else{     //第一种情况19            BSTreeNode *p = t;20            if(t->leftChild == NULL){21                t = t->rightChild; //引用的好处体现出来了;22            }else{ 23                t = t->leftChild;  //引用的好处体现出来了;24            }25                delete p;26        }27    }        28    return true;29}30/*  以下这个代码是先想到的,比较容易,上面这个是经过思考的,将三种情况看成一种情况来处理。31bool remove(BSTreeNode *&t, const Type &key){32    if(t == NULL){33        return false;34    }3536    if(key data){37        remove(t->leftChild, key);38    }else if(key > t->data){39        remove(t->rightChild, key);40    }else{  //以下三种情况可以看成一种;41        if(t->leftChild == NULL && t->rightChild == NULL){42            delete t;43            t = NULL;44        }else if(t->leftChild != NULL && t->rightChild == NULL){45            BSTreeNode *p = t;46            t = t->leftChild;47            delete p;48        }else if(t->leftChild == NULL && t->rightChild != NULL){49            BSTreeNode *p = t;50            t = t->rightChild;51            delete p;52        }else{53            BSTreeNode *p = t->rightChild;54            while(p->leftChild != NULL){55                p = p->leftChild;56            }57            t->data = p->data;58            remove(t->rightChild, p->data);59        }60    }    61    return true;62}63*/

7、搜索二叉树的完整代码、测试代码、测试结果  

(1)、完整代码

  1#ifndef _BSTREE_H_
2#define _BSTREE_H_
3
4#include
5using namespace std;
6
7#define MIN_NUMBER    -8937589
8#define MAX_NUMBER    99999999
9
10
11template<typename Type>
12class BSTree;
13
14template<typename Type>
15class BSTreeNode{
16    friend class BSTree;
17public:
18    BSTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL){}
19    BSTreeNode(Type d, BSTreeNode *left = NULL, BSTreeNode *right = NULL) 
20        : data(d), leftChild(left), rightChild(right){}
21    ~BSTreeNode(){}
22private:
23    Type data;
24    BSTreeNode *leftChild;
25    BSTreeNode *rightChild;
26};
27
28template<typename Type>
29class BSTree{
30public:
31    BSTree() : root(NULL){}
32    BSTree& operator=(const BSTree &bst){ 33        if(this != &bst){ 34            root = copy(bst.root); 35        } 36 37        return *this; 38    } 39    ~BSTree(){} 40public: 41    void insert(const Type &x){ 42        insert(root, x); 43    } 44    void inOrder()const{ 45        inOrder(root); 46    } 47    Type Min()const{ 48        return Min(root); 49    } 50    Type Max()const{ 51        return Max(root); 52    } 53    BSTreeNode* find(const Type &key)const{ 54        return find(root, key); 55    } 56    BSTreeNode *copy(const BSTreeNode *t){ 57        if(t == NULL){ 58            return NULL; 59        } 60        BSTreeNode *tmp = new BSTreeNode(t->data); 61        tmp->leftChild = copy(t->leftChild); 62        tmp->rightChild = copy(t->rightChild); 63 64        return tmp; 65    } 66    BSTreeNode* parent(const Type &key)const{ 67        return parent(root, key); 68    } 69    bool remove(const Type &key){ 70        return remove(root, key); 71    } 72protected: 73    bool remove(BSTreeNode *&t, const Type &key){ 74        if(t == NULL){     //重点:传的是引用 75            return false; 76        } 77 78        if(key data){ 79            remove(t->leftChild, key); 80        }else if(key > t->data){ 81            remove(t->rightChild, key); 82        }else{ 83            if(t->leftChild != NULL && t->rightChild != NULL){ 84                BSTreeNode *p = t->rightChild; 85                while(p->leftChild != NULL){ 86                    p = p->leftChild; 87                } 88                t->data = p->data; 89                remove(t->rightChild, p->data); 90            }else{ 91                BSTreeNode *p = t; 92                if(t->leftChild == NULL){ 93                    t = t->rightChild;  //可以直接更改左右孩子 94                }else{ 95                    t = t->leftChild;   //可以直接更改左右孩子 96                } 97                    delete p; 98 99            }100        }101102        return true;103    }104/*  105    bool remove(BSTreeNode *&t, const Type &key){106        if(t == NULL){107            return false;108        }109110        if(key data){111            remove(t->leftChild, key);112        }else if(key > t->data){113            remove(t->rightChild, key);114        }else{  //以下三种情况可以看成一种;115            if(t->leftChild == NULL && t->rightChild == NULL){116                delete t;117                t = NULL;118            }else if(t->leftChild != NULL && t->rightChild == NULL){119                BSTreeNode *p = t;120                t = t->leftChild;121                delete p;122            }else if(t->leftChild == NULL && t->rightChild != NULL){123                BSTreeNode *p = t;124                t = t->rightChild;125                delete p;126            }else{127                BSTreeNode *p = t->rightChild;128                while(p->leftChild != NULL){129                    p = p->leftChild;130                }131                t->data = p->data;132                remove(t->rightChild, p->data);133            }134        }135136        return true;137    }*/138    BSTreeNode* parent(BSTreeNode *t, const Type &key)const{139        if(t == NULL || t->data == key){140            return NULL;141        }142        if(t->leftChild->data == key || t->rightChild->data == key){143            return t;144        }145        if(key data){146            return parent(t->leftChild, key);147        }else{148            return parent(t->rightChild, key);149        }150    }151    BSTreeNode* find(BSTreeNode *t, const Type &key)const{152        if(t == NULL){153            return NULL;154        }155156        if(t->data == key){157            return t;158        }else if(key data){159            return find(t->leftChild, key);160        }else{161            return find(t->rightChild, key);162        }163    }164    Type Max(BSTreeNode *t)const{165        if(t != NULL){166            while(t->rightChild){167                t = t->rightChild;168            }169170            return t->data;171        }172173        return MAX_NUMBER;174    }175    Type Min(BSTreeNode *t)const{176        if(t != NULL){177            while(t->leftChild){178                t = t->leftChild;179            }180181            return t->data;182        }183        return MIN_NUMBER;184    }185    void inOrder(BSTreeNode *t)const{186        if(t != NULL){187            inOrder(t->leftChild);188            cout<data<<" ";189            inOrder(t->rightChild);190        }191    }192    void insert(BSTreeNode *&t, const Type &x){193        if(t == NULL){194            t = new BSTreeNode(x);195            return;196        }else if(x data){197            insert(t->leftChild, x);198        }else if(x > t->data){199            insert(t->rightChild, x);200        }else{201            return;202        }    203    }204private:205    BSTreeNode *root;206};207#endif

(2)、测试代码

 1#include"bstree.h"
2
3int main(void){
4    int ar[] = {3, 7, 9, 1, 0, 6, 4, 2,};
5    int n = sizeof(ar) / sizeof(int);
6    BSTree<int> bst;
7    for(int i = 0; i  8        bst.insert(ar[i]);
9    }
10
11    bst.inOrder();
12    cout<<endl;
13    cout<endl;14    cout<endl;15    BSTreeNode<int> *p = bst.find(6);16    BSTreeNode<int> *q = bst.parent(4);17    printf("%p %p\n", p, q);18    bst.remove(0);19    bst.inOrder();20    cout<<endl;21    return 0;22}

(3)、测试结果

1a27696bbfb12369443786578e523621.png

推荐阅读:

从零开始学习数据结构-->入门篇 从零开始学习数据结构-->链表 从零开始学习数据结构-->线性表 从零开始学习数据结构-->栈 从零开始学习数据结构-->队列 从零开始学习数据结构-->矩阵+串 从零开始学习数据结构-->哈希表 从零开始学习数据结构-->散列桶 从零开始学习数据结构-->二叉树

从零开始学习数据结构-->二叉树方法实现

从零开始学习数据结构-->线索二叉树

从零开始学习数据结构-->树、森林与二叉树的转换

从零开始学习数据结构-->大堆+小堆

认真的人 自带光芒

57f4d177c7d896b201ac8a411b547a4d.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值