二叉树查找结点c语言_从零开始学习数据结构>线索二叉树

线索二叉树作为二叉树的进阶,不仅仅是面试高频,Linux 内核中不少地方使用到这个数据结构(比如:文件管理系统的实现)。 1、什么是线索二叉树 线索化的二叉树就是:在原有的二叉树基础上有些改动,将没有孩子结点的链域声明为线,左孩子指向前驱,右孩子指向后继节点。 有孩子结点的为链,表示指向原先的左右孩子。 线索二叉树的基本存储结构如下: e6edb22cf4b0f069e8039f2dc10bcd67.png 2、中序二叉树的图形 2dae73e174a473324b1ff19b8fff1ac1.png 线索二叉树无需遍历,可以很方便的得到其任一结点的前驱、后继。 3、中序线索二叉树的建立 必须先建立好二叉树(根据先序序列),在其基础上创建中序线索二叉树; 核心程序:最好画图跟踪一下,才能弄得清楚; 注意:最后一个结点在函数结束时为LINK,没有更改过来!
 1template<typename Type>
2void BinTree::createInThread(BinTreeNode *t, BinTreeNode *&pre){ //创建中序线索二叉树 3    if(t == NULL){                        //pre必须引用传递,的保证及时的更改!!! 4        return;  //空树直接返回 5    } 6    createInThread(t->leftChild, pre);  //pre一直为空,一直在往左走; 7    if(t->leftChild == NULL){ 8        t->ltag = THREAD;  //将左孩子设置为线 9        t->leftChild = pre;  //因为是第一个,无前驱,所以置空10    }11    if(pre != NULL && pre->rightChild == NULL){ 12        pre->rtag = THREAD;  //将右孩子设置为线;13        pre->rightChild = t;  //此时指向后继结点,t已经回到了上一层14    }15    pre = t;  //将当前结点给pre;16    createInThread(t->rightChild, pre); //往右边递归17}
完整创建程序:
 1#ifndef _THREAD_BIN_TREE_H_
2#define _THREAD_BIN_TREE_H_
3
4#include
5using namespace std;
6
7typedef enum{LINK, THREAD}TAG;  //定义枚举标记链和线
8
9template<typename Type>
10class BinTree;
11
12template<typename Type>  //结点类,多了两个标记链和线的;
13class BinTreeNode{
14    friend class BinTree;
15public:
16    BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL), ltag(LINK), rtag(LINK){}
17    BinTreeNode(Type value, BinTreeNode *left = NULL, BinTreeNode *right = NULL) :18    data(value), leftChild(left), rightChild(right), ltag(LINK), rtag(LINK){}19    ~BinTreeNode(){}20private:21    Type data;22    BinTreeNode *leftChild;23    BinTreeNode *rightChild;24    TAG            ltag;          //左标记25    TAG            rtag;         //右标记26};27///28template<typename Type>29class BinTree{30public:31    BinTree() : root(NULL){}32    BinTree(Type ref) : root(NULL), refval(ref){}33    BinTree(const BinTree &t){}34    ~BinTree(){35    }36public:37    void createBinTree(const char *str);  //的先建立二叉树38    void createInThread();39protected :40    void createBinTree(const char *&str, BinTreeNode *&t);41    void createInThread(BinTreeNode *t, BinTreeNode *&pre);42template<typename Type>43void BinTree::createBinTree(const char *str){44    createBinTree(str, root);45}46template<typename Type>47void BinTree::createInThread(){  //在二叉树已经建立起来,创建中序线索二叉树;48    BinTreeNode *pre = NULL;  //得弄一个前驱节点,做为参数传递过去49    createInThread(root, pre);   //真正的创建中序线索二叉树50    pre->rtag = THREAD;  //最后一个应该为线51}52template<typename Type>53void BinTree::createInThread(BinTreeNode *t, BinTreeNode *&pre){ //创建中序线索二叉树54    if(t == NULL){55        return;56    }57    createInThread(t->leftChild, pre);58    if(t->leftChild == NULL){59        t->ltag = THREAD;60        t->leftChild = pre;61    }62    if(pre != NULL && pre->rightChild == NULL){63        pre->rtag = THREAD;64        pre->rightChild = t;65    }66    pre = t;67    createInThread(t->rightChild, pre);68}69template<typename Type>  //创建二叉树70void BinTree::createBinTree(const char *&str, BinTreeNode *&t){71    if(*str == refval){72        t = NULL;73    }else{74        t = new BinTreeNode(*str);75        createBinTree(++str, t->leftChild);76        createBinTree(++str, t->rightChild);77    }78}7980#endif
4、其它方法的实现 中序线索二叉树
1public:
2    BinTreeNode* first()const;  //查找中序的第一个结点3    BinTreeNode* last()const;   //查找中序的最后一个结点4    BinTreeNode* prev(BinTreeNode *cur)const; //查找当前结点的前驱5    BinTreeNode* next(BinTreeNode *cur)const; //查找当前结点的后继6    BinTreeNode* parent(BinTreeNode *cur)const; //查找当前结点的父结点7    void inOrder()const;  //中序遍历线索二叉树8    BinTreeNode* find(const Type &key); //查找某一结点
关于还有些方法: 求树高,求结点个数,这些其实跟前面写的差不多,将结束条件换为:
1if(t->ltag == THREAD) {
2    return 0;
3}
(1)、查找第一个结点
 1template<typename Type>
2BinTreeNode* BinTree::first(BinTreeNode *t)const{ 3    if(t == NULL){ 4        return NULL; 5    } 6    while(t->ltag == LINK){ 7        t = t->leftChild; 8    } 9    return t;10}
(2)、查找最后一个结点
 1template<typename Type>
2BinTreeNode* BinTree::last(BinTreeNode *t)const{ 3    if(t == NULL){ 4        return NULL; 5    } 6    while(t->rtag == LINK){ 7        t = t->rightChild; 8    } 910    return t;
(3)、查找当前结点的前驱
 1template<typename Type>
2BinTreeNode* BinTree::prev(BinTreeNode *t, BinTreeNode *cur)const{ 3    if(t == NULL || cur == NULL){ 4        return NULL; 5    } 6    if(cur->ltag == THREAD){ 7        return cur->leftChild; 8    }else{ 9        return last(cur->leftChild);  //当前结点的前驱是:左树的最后一个结点;10    }11}
(4)、查找当前结点的后继
 1template<typename Type>
2BinTreeNode* BinTree::next(BinTreeNode *t, BinTreeNode *cur)const{ 3    if(t == NULL || cur == NULL){ 4        return NULL; 5    } 6    if(cur->rtag == THREAD){ 7        return cur->rightChild; 8    }else{ 9        return first(cur->rightChild);  //当前结点的后继是:右树的第一个结点;10    }   11}
(5)、中序遍历线索化二叉树
 1template<typename Type>
2void BinTree::inOrder(BinTreeNode *t)const{ 3    BinTreeNode *p; 4 5    if(t == NULL){ 6        return; 7    } 8    for(p = first(t); p != NULL; p = next(t, p)){ 9        cout<data<<" ";10    }11    cout<<endl;12}
(6)、查找某一结点
 1template<typename Type>
2BinTreeNode* BinTree::find(BinTreeNode *t, const Type &key){ 3    if(t == NULL){ 4        return NULL; 5    } 6    if(t->data == key){ 7        return t; 8    } 910    BinTreeNode *p;11    for(p = first(t); p != NULL; p = next(t, p)){12        if(p->data == key){13            return p;14        }15    }16    return NULL;17}
(7) 、查找当前结点的父结点,分析如下: a、为空,或当前为根结点,其父结点----->NULL;
b、看看根是否为父结点;
c、就是图中E、D这种情况,其父----->后继结点;
d、就是图中H、G这种情况,其父----->前驱结点;
以上就是针对存在线的求法;
针对没有线的求法: (一)、例如求D:看的是其右的最后一个,因为线,走了一圈,就是确定B是其父;
(二)、找当前结点的左树的第一个,在返回其左孩子(此时这个线就是父节点)。
 1template<typename Type>
2BinTreeNode* BinTree::parent(BinTreeNode *t, BinTreeNode *cur)const{ 3    if(t == NULL || cur == NULL || cur == t){ 4        return NULL;   //父为空 5    } 6    if(t->ltag == LINK && t->leftChild == cur){  //父为根节点 7        return t; 8    }  9    if(t->rtag == LINK && t->rightChild == cur){10        return t;11    } 1213    if(cur->rtag == THREAD && cur->rightChild->leftChild == cur){ //线的找14        return cur->rightChild;15    }16    if(cur->ltag == THREAD && cur->leftChild->rightChild == cur){  //线的找17        return cur->leftChild;18    }1920    BinTreeNode *p = last(cur->rightChild);  //往右找最后一个,21    p = p->rightChild;22    if(p != NULL && p->leftChild->rightChild == cur){23        return p->leftChild;24    }2526    p = first(cur->leftChild);  //换换思路,往左找第一个。27    return p->leftChild;28}
f45792b83e3bd2f866d17918a86af8c3.png 5、完整代码、调试程序,测试结果 (1)、代码
  1#ifndef _THREAD_BIN_TREE_H_
2#define _THREAD_BIN_TREE_H_
3
4#include
5using namespace std;
6
7typedef enum{LINK, THREAD}TAG;
8
9template<typename Type>
10class BinTree;
11
12template<typename Type>
13class BinTreeNode{
14    friend class BinTree;
15public:
16    BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL), ltag(LINK), rtag(LINK){}
17    BinTreeNode(Type value, BinTreeNode *left = NULL, BinTreeNode *right = NULL) : 18    data(value), leftChild(left), rightChild(right), ltag(LINK), rtag(LINK){} 19    ~BinTreeNode(){} 20private: 21    Type data; 22    BinTreeNode *leftChild; 23    BinTreeNode *rightChild; 24    TAG            ltag;          //左标记 25    TAG            rtag;         //右标记 26}; 27/// 28template<typename Type> 29class BinTree{ 30public: 31    BinTree() : root(NULL){} 32    BinTree(Type ref) : root(NULL), refval(ref){} 33    BinTree(const BinTree &t){} 34    ~BinTree(){ 35    } 36public: 37    void createBinTree(const char *str); 38    void createInThread(); 39public: 40    BinTreeNode* first()const; 41    BinTreeNode* last()const; 42    BinTreeNode* prev(BinTreeNode *cur)const; 43    BinTreeNode* next(BinTreeNode *cur)const; 44    BinTreeNode* parent(BinTreeNode *cur)const; 45    void inOrder()const; 46    BinTreeNode* find(const Type &key); 47protected: 48    BinTreeNode* first(BinTreeNode *t)const; 49    BinTreeNode* last(BinTreeNode *t)const; 50    BinTreeNode* prev(BinTreeNode *t, BinTreeNode *cur)const; 51    BinTreeNode* next(BinTreeNode *t, BinTreeNode *cur)const; 52    BinTreeNode* parent(BinTreeNode *t, BinTreeNode *cur)const; 53    void inOrder(BinTreeNode *t)const; 54    BinTreeNode* find(BinTreeNode *t, const Type &key); 55protected : 56    void createBinTree(const char *&str, BinTreeNode *&t); 57    void createInThread(BinTreeNode *t, BinTreeNode *&pre); 58private: 59    BinTreeNode *root; 60    Type               refval;  //'#' 61}; 62template<typename Type> 63void BinTree::createBinTree(const char *str){ 64    createBinTree(str, root); 65} 66template<typename Type> 67void BinTree::createInThread(){ 68    BinTreeNode *pre = NULL; 69    createInThread(root, pre); 70    pre->rtag = THREAD;  //最后一个应该为线 71} 72template<typename Type> 73BinTreeNode* BinTree::first()const{ 74    return first(root); 75} 76template<typename Type> 77BinTreeNode* BinTree::last()const{ 78    return last(root); 79} 80template<typename Type> 81BinTreeNode* BinTree::prev(BinTreeNode *cur)const{ 82    return prev(root, cur); 83} 84template<typename Type> 85BinTreeNode* BinTree::next(BinTreeNode *cur)const{ 86    return next(root, cur); 87} 88template<typename Type> 89BinTreeNode* BinTree::parent(BinTreeNode *cur)const{ 90    return parent(root, cur); 91} 92template<typename Type> 93void BinTree::inOrder()const{ 94    inOrder(root); 95} 96template<typename Type> 97BinTreeNode* BinTree::find(const Type &key){ 98    return find(root, key); 99}100//101template<typename Type>102BinTreeNode* BinTree::find(BinTreeNode *t, const Type &key){103    if(t == NULL){104        return NULL;105    }106    if(t->data == key){107        return t;108    }109110    BinTreeNode *p;111    for(p = first(t); p != NULL; p = next(t, p)){112        if(p->data == key){113            return p;114        }115    }116    return NULL;117}118template<typename Type>119void BinTree::inOrder(BinTreeNode *t)const{120    BinTreeNode *p;121122    if(t == NULL){123        return;124    }125    for(p = first(t); p != NULL; p = next(t, p)){126        cout<data<<" ";127    }128    cout<<endl;129}130template<typename Type>131BinTreeNode* BinTree::parent(BinTreeNode *t, BinTreeNode *cur)const{132    if(t == NULL || cur == NULL || cur == t){133        return NULL;134    }135    if(t->ltag == LINK && t->leftChild == cur){136        return t;137    } 138    if(t->rtag == LINK && t->rightChild == cur){139        return t;140    } 141142    if(cur->rtag == THREAD && cur->rightChild->leftChild == cur){143        return cur->rightChild;144    }145    if(cur->ltag == THREAD && cur->leftChild->rightChild == cur){146        return cur->leftChild;147    }148149    BinTreeNode *p = last(cur->rightChild);150    p = p->rightChild;151    if(p != NULL && p->leftChild->rightChild == cur){152        return p->leftChild;153    }154155    p = first(cur->leftChild);156    return p->leftChild;157}158template<typename Type>159BinTreeNode* BinTree::next(BinTreeNode *t, BinTreeNode *cur)const{160    if(t == NULL || cur == NULL){161        return NULL;162    }163    if(cur->rtag == THREAD){164        return cur->rightChild;165    }else{166        return first(cur->rightChild);167    }168169}170template<typename Type>171BinTreeNode* BinTree::prev(BinTreeNode *t, BinTreeNode *cur)const{172    if(t == NULL || cur == NULL){173        return NULL;174    }175    if(cur->ltag == THREAD){176        return cur->leftChild;177    }else{178        return last(cur->leftChild);179    }180}181template<typename Type>182BinTreeNode* BinTree::last(BinTreeNode *t)const{183    if(t == NULL){184        return NULL;185    }186    while(t->rtag == LINK){187        t = t->rightChild;188    }189190    return t;191}192template<typename Type>193BinTreeNode* BinTree::first(BinTreeNode *t)const{194    if(t == NULL){195        return NULL;196    }197    while(t->ltag == LINK){198        t = t->leftChild;199    }200    return t;201}202template<typename Type>203void BinTree::createInThread(BinTreeNode *t, BinTreeNode *&pre){204    if(t == NULL){205        return;206    }207    createInThread(t->leftChild, pre);208    if(t->leftChild == NULL){209        t->ltag = THREAD;210        t->leftChild = pre;211    }212    if(pre != NULL && pre->rightChild == NULL){213        pre->rtag = THREAD;214        pre->rightChild = t;215    }216    pre = t;217    createInThread(t->rightChild, pre);218219}220template<typename Type>221void BinTree::createBinTree(const char *&str, BinTreeNode *&t){222    if(*str == refval){223        t = NULL;224    }else{225        t = new BinTreeNode(*str);226        createBinTree(++str, t->leftChild);227        createBinTree(++str, t->rightChild);228    }229}230231#endif
(2)、测试代码
 1#include"threadBinTree.h"
2
3int main(void){
4    char *str = "ABC##DE##F##G#H##";
5    BinTree<char> bt('#');
6    bt.createBinTree(str);
7    bt.createInThread();
8
9    bt.inOrder();
10    BinTreeNode<char> *k = bt.find('A'); //直接输入字符查找,其方法find(const Type &key)中的const万万不可少
11    BinTreeNode<char> *p = bt.first();  //C
12    printf("%p\n", k);  //A
13    BinTreeNode<char> *m;
14    m = bt.parent(p);   
15//    printf("%p\n", m);  //B
16    BinTreeNode<char> *n;
17    n = bt.parent(m);
18    printf("%p\n", n);  //A
19    return 0;
20}
(3)、测试结果 1303d44d03d8d7b24cb48b0baea77a7d.png 推荐阅读: 从零开始学习数据结构-->入门篇 从零开始学习数据结构-->链表 从零开始学习数据结构-->线性表 从零开始学习数据结构-->栈 从零开始学习数据结构-->队列 从零开始学习数据结构-->矩阵+串 从零开始学习数据结构-->哈希表 从零开始学习数据结构-->散列桶 从零开始学习数据结构-->二叉树

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

认真的人 自带光芒

09ea70f57c6b10e2534336a9064cda7d.png

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值