二叉树的复制构造函数_从零开始学习数据结构>二叉树方法实现

对于二叉树,其常见操作方法的逻辑 + 实现,这些都是面试高频: 求节点个数 求树的高度 求根节点 求当前节点的左孩子 求当前节点的右孩子 查找当前节点 查找当前节点的父节点 将二叉树置空 两个二叉树是否相同的比较 复制一个二叉树 。。。。。。 1、二叉树上的操作 均是C++实现先根序创建二叉树及其其它方法。 我认为在二叉树的创建方法和遍历以外,以下方法值得我们关注:
 1public:
2    int size()const;  //求结点个数
3    int height()const;  //求树的高度
4    BinTreeNode* root_1()const; //求根节点 5    BinTreeNode* leftChild(BinTreeNode* cur)const;  //求当前结点的左孩子 6    BinTreeNode* rightChild(BinTreeNode* cur)const; //求当前结点的右孩子 7    BinTreeNode* find(const Type &key)const;              //查找当前结点 8    BinTreeNode* parent(BinTreeNode* cur)const;     //查找当前结点的父结点 9    void makeEmpty();                                           //将二叉树置空10    bool equal(const BinTree &t)const;                    //两个二叉树是否相同的比较11    BinTreeNode* copy(BinTreeNode *t)const;         //拷贝构造函数的方法,复制一个二叉树
2、方法一一实现 (1)、求结点个数
1template<typename Type>
2int BinTree::size(BinTreeNode *t)const{3    if(t == NULL){4        return 0;5    }67    return size(t->leftChild) + size(t->rightChild) + 1;8}
(2)、求树的高度
 1template<typename Type>
2int BinTree::height(BinTreeNode *t)const{ 3    if(t == NULL){ 4        return 0; 5    } 6    int leftHeight = height(t->leftChild); 7    int rightHeight = height(t->rightChild); 8 9    return (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;10}
(3)、查找当前结点
 1template<typename Type>
2BinTreeNode* BinTree::find(const Type &key, BinTreeNode *t)const{ 3    if(t == NULL){ 4        return NULL; 5    } 6    if(t->data == key){ 7        return t; 8    } 910    BinTreeNode *p = find(key, t->leftChild);11    if(p != NULL){12        return p;13    }1415    return find(key, t->rightChild);16}
(4)、查找当前结点的父结点
 1template<typename Type>
2BinTreeNode* BinTree::parent(BinTreeNode* cur, BinTreeNode *t)const{ 3    if(t == NULL || cur == NULL || cur == t){ 4        return NULL; 5    } 6    if(t->leftChild == cur || t->rightChild == cur){ 7        return t; 8    }        //思路:利用父的孩子节点和当前节点比较 9    BinTreeNode *p = parent(cur, t->leftChild);10    if(p != NULL){11        return p;12    }1314    return parent(cur, t->rightChild);15}
(5)、将二叉树置空
1template<typename Type>
2void BinTree::makeEmpty(BinTreeNode *t){3    if(t != NULL){4        makeEmpty(t->leftChild);5        makeEmpty(t->rightChild);6        delete t;7    }8}
(6)、两个二叉树是否相同的比较
 1template<typename Type>
2bool BinTree::equal(BinTreeNode *t, BinTreeNode *t1)const{ 3    if(t == NULL && t1 == NULL){  //取反判断与这个是一个道理 4        return true; 5    } 6    if(t != NULL && t1!= NULL && t->data == t1->data && equal(t->leftChild, t1->leftChild) 7        && equal(t->rightChild, t1->rightChild)){ 8        return true; 9    }else{1011        return false;12    }13}
(7)、拷贝一个二叉树
 1template<typename Type>
2BinTreeNode* BinTree::copy(BinTreeNode *t)const{ 3    BinTreeNode* tmp; 4 5    if(t == NULL){ 6        return NULL; 7    }else{ 8        tmp = new BinTreeNode(t->data); 9        tmp->leftChild = copy(t->leftChild);10        tmp->rightChild = copy(t->rightChild);11    }1213    return tmp;14}
以上的这些方法都是利用二叉树的性质递归实现,比较好想清楚,就不做解释了,实在有问题,画画图就会好很多。 3、二叉树的所有方法,测试,及测试结果如下 (1)、所有关于二叉树的代码:
  1#ifndef _BIN_TREE_H_
2#define _BIN_TREE_H_
3
4#include
5#include  //非递归遍历引入栈
6#include  //层次遍历引入队列
7using namespace std;
8
9template<typename Type> //为的是声明友元类,调用BinTreeNode的私有数据
10class BinTree;
11
12template<typename Type>  //BinTreeNode类
13class BinTreeNode{   
14    friend class BinTree;
15public:
16    BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL){}
17    BinTreeNode(Type value, BinTreeNode *left = NULL, BinTreeNode *right = NULL) : 18    data(value), leftChild(left), rightChild(right){} 19    ~BinTreeNode(){} 20private: 21    Type data; 22    BinTreeNode *leftChild; 23    BinTreeNode *rightChild; 24}; 25/// 26template<typename Type>   //BinTree类 27class BinTree{ 28public: 29    BinTree() : root(NULL){} 30    BinTree(Type ref) : root(NULL), refval(ref){} 31    BinTree(const BinTree &t){ 32        root = copy(t.root);  //调用拷贝方法 33    } 34    ~BinTree(){ 35        makeEmpty();  //析构函数这里将二叉树置空 36        root = NULL;     37    } 38public:                 //创建二叉树 39    void createBinTree(); 40    void createBinTree(const char *str); 41    void createBinTree(const char *VLR, const char *LVR, int n); 42    void createBinTree_1(const char *LVR, const char *LRV, int n); 43public:                //递归遍历 44    void prevOrder()const; 45    void inOrder()const; 46    void endOrder()const; 47public:               //各种方法的声明 48    int size()const; 49    int height()const; 50    BinTreeNode* root_1()const; //以下的三个方法比较简单,就不在进行调用保护方法了; 51    BinTreeNode* leftChild(BinTreeNode* cur)const; 52    BinTreeNode* rightChild(BinTreeNode* cur)const; 53    BinTreeNode* find(const Type &key)const; 54    BinTreeNode* parent(BinTreeNode* cur)const; 55    void makeEmpty(); 56    bool equal(const BinTree &t)const; 57    BinTreeNode* copy(BinTreeNode *t)const; 58public:              //非递归遍历 59    void prevOrder_1()const; 60    void inOrder_1()const; 61    void endOrder_1()const; 62    void levelOrder()const; //puublic:供外界提供的接口, 63 64protected:                 //protected:供自己函数内部调用,写保护方法 65    void prevOrder_1(BinTreeNode* t)const; 66    void inOrder_1(BinTreeNode* t)const; 67    void endOrder_1(BinTreeNode* t)const; 68    void levelOrder(BinTreeNode* t)const; 69protected: 70    int size(BinTreeNode *t)const; 71    int height(BinTreeNode *t)const; 72    BinTreeNode* find(const Type &key, BinTreeNode *t)const; 73    BinTreeNode* parent(BinTreeNode* cur, BinTreeNode *t)const; 74    void makeEmpty(BinTreeNode* t); 75    bool equal(BinTreeNode *t, BinTreeNode *t1)const; 76protected: 77    void prevOrder(BinTreeNode *t)const; 78    void inOrder(BinTreeNode *t)const; 79    void endOrder(BinTreeNode *t)const; 80protected : 81    void createBinTree(BinTreeNode *&t); 82    BinTreeNode* createBinTree_1(); 83    void createBinTree(const char *&str, BinTreeNode *&t); 84    BinTreeNode* createBinTree_1(const char *&str); 85    void createBinTree(BinTreeNode *&t, const char *VLR, const char *LVR, int n); 86    void createBinTree_1(BinTreeNode *&t, const char *LVR, const char *LRV, int n); 87                         //以上都只是在类内声明; 88private: 89    BinTreeNode *root; 90    Type               refval;  //'#' 91}; 92/// 93template<typename Type>  //类外实现公有方法的调用 94void BinTree::createBinTree(){  //创建二叉树 95    //createBinTree(root); 96    root = createBinTree_1(); 97} 98template<typename Type> 99void BinTree::prevOrder()const{ //先序递归遍历100    cout<<"先根序如下: "<<endl;101    prevOrder(root);102}103template<typename Type>104void BinTree::inOrder()const{ //中序递归遍历105    cout<<"中根序如下: "<<endl;106    inOrder(root);107}108template<typename Type>109void BinTree::endOrder()const{  //后序递归遍历110    cout<<"后根序如下: "<<endl;111    endOrder(root);112}113114template<typename Type>115void BinTree::createBinTree(const char *str){ //创建二叉树116//    createBinTree(str, root);117    root = createBinTree_1(str);118}119template<typename Type>120int BinTree::size()const{  //求结点个数121    return size(root);122}123template<typename Type>124int BinTree::height()const{ //求树的高度125    return height(root);126}127template<typename Type>128BinTreeNode* BinTree::root_1()const{ //求根节点129    return root;130}131template<typename Type>132BinTreeNode* BinTree::leftChild(BinTreeNode* cur)const{ //求当前结点的左孩子133    return cur->leftChild;134}135template<typename Type>136BinTreeNode* BinTree::rightChild(BinTreeNode* cur)const{  //求当前结点的右孩子137    return cur->rightChild;138}139template<typename Type>140BinTreeNode* BinTree::find(const Type &key)const{  //查找当前结点141    return find(key, root);142}143template<typename Type>144BinTreeNode* BinTree::parent(BinTreeNode* cur)const{ //查找当前结点的父结点145    return parent(cur, root);146}147template<typename Type>148void BinTree::makeEmpty(){ //将二叉树置空149    makeEmpty(root);150}151template<typename Type>152bool BinTree::equal(const BinTree &t)const{ //两个二叉树是否相同的比较153    return equal(t.root, root);154}155template<typename Type>156void BinTree::prevOrder_1()const{  //非递归先序157    prevOrder_1(root);158}159template<typename Type>160void BinTree::inOrder_1()const{   //非递归中序161    inOrder_1(root);162}163template<typename Type>164void BinTree::endOrder_1()const{   //非递归后序165    endOrder(root);166}167template<typename Type>168void BinTree::levelOrder()const{   //层次遍历169    levelOrder(root);170}171template<typename Type>172void BinTree::createBinTree(const char *VLR, const char *LVR, int n){ //创建二叉树173    createBinTree(root, VLR, LVR, n);174}175template<typename Type> 176void BinTree::createBinTree_1(const char *LVR, const char *LRV, int n){ //创建二叉树177    createBinTree_1(root, LVR, LRV, n);178}179//180template<typename Type>  //以下的都是写保护的方法,供自己使用181void BinTree::createBinTree_1(BinTreeNode *&t, const char *LVR, const char *LRV, int n){  //中序和后序创建二叉树182    if(n == 0){183        t = NULL;184        return;185    }186    int k = 0;187    while(LVR[k] != LRV[n-1]){188        k++;189    }190    t = new BinTreeNode(LVR[k]);191192    createBinTree_1(t->rightChild, LVR+k+1, LRV+k, n-k-1);193    createBinTree_1(t->leftChild, LVR, LRV, k);194}195template<typename Type>196void BinTree::createBinTree(BinTreeNode *&t, const char *VLR, const char *LVR, int n){   //先序和中序创建二叉树197    if(n == 0){198        t = NULL;199        return;200    }201    int k = 0;202    while(LVR[k] != VLR[0]){203        k++;204    }205    t = new BinTreeNode(LVR[k]);206    createBinTree(t->leftChild, VLR+1, LVR, k);207    createBinTree(t->rightChild, VLR+k+1, LVR+k+1, n-k-1);208}209template<typename Type>210void BinTree::levelOrder(BinTreeNode* t)const{  //层次遍历211    queue *> qu;212    BinTreeNode *p;213214    if(t != NULL){215        qu.push(t);216        while(!qu.empty()){217            p = qu.front();218            qu.pop();219            cout<data<<" ";220            if(p->leftChild){221                qu.push(p->leftChild);222            }223            if(p->rightChild){224                qu.push(p->rightChild);225            }226        }227    }228}229typedef enum{L, R}Tag;230template<typename Type>231class stkNode{232public:233    stkNode(BinTreeNode *p = NULL) : ptr(p), tag(L){}234public:235    BinTreeNode *ptr;236    Tag                   tag; //L R237};238template<typename Type>239void BinTree::endOrder_1(BinTreeNode* t)const{  //非递归后序240    stkNode n;241    stack> st;242    BinTreeNode *p = t;243244    do{245        while(p != NULL){246            n.ptr = p;247            n.tar = L;248            st.push(n);249            p = p->leftChild;250        }251        bool isRun = true;252        while(isRun && !st.empty()){253            n = st.top();254            st.pop();255256            switch(n.tag){257            case L:258                p = n.ptr;259                n.tag = R;260                st.push(n);261                p = p->rightChild;262                isRun = false;263                break;264            case R:265                cout<data<<" ";266                break;267            }268        }269    }while(!st.empty());//不用p1=NULL,因为当栈空时,最后一个节点刚好被访问完成。270}271template<typename Type>272void BinTree::inOrder_1(BinTreeNode* t)const{  //非递归中序273    stack *> st;274    BinTreeNode *p = t;275276    do{277        while(p != NULL){278            st.push(p);279            p = p->leftChild;280        }281        if(!st.empty()){282            p = st.top();283            st.pop();284            cout<data<<" ";285            p = p->rightChild;286        }//中序遍历时,当root出栈时,此时占空,287    }while(p != NULL || !st.empty()); //为根的时候右边还要入栈。288}289290template<typename Type>291void BinTree::prevOrder_1(BinTreeNode* t)const{  //非递归先序292    stack *> st;293    BinTreeNode *tmp;294295    if(t != NULL){296        st.push(t);297        while(!st.empty()){298            tmp = st.top();299            st.pop();300            cout<data<<" ";301            if(tmp->rightChild){302                st.push(tmp->rightChild);303            }304            if(tmp->leftChild){305                st.push(tmp->leftChild);306            }307        }308    }309}310template<typename Type>311BinTreeNode* BinTree::copy(BinTreeNode *t)const{  //拷贝函数312    BinTreeNode* tmp;313314    if(t == NULL){315        return NULL;316    }else{317        tmp = new BinTreeNode(t->data);318        tmp->leftChild = copy(t->leftChild);319        tmp->rightChild = copy(t->rightChild);320    }321322    return tmp;323}324template<typename Type>325bool BinTree::equal(BinTreeNode *t, BinTreeNode *t1)const{  //两个二叉树是否相同的比较326    if(t == NULL && t1 == NULL){  //取反判断与这个是一个道理327        return true;328    }329    if(t != NULL && t1!= NULL && t->data == t1->data && equal(t->leftChild, t1->leftChild)330        && equal(t->rightChild, t1->rightChild)){331        return true;332    }else{333334        return false;335    }336}337template<typename Type>338void BinTree::makeEmpty(BinTreeNode *t){  //将二叉树置空339    if(t != NULL){340        makeEmpty(t->leftChild);341        makeEmpty(t->rightChild);342        delete t;343    }344}345template<typename Type>346BinTreeNode* BinTree::parent(BinTreeNode* cur, BinTreeNode *t)const{  //查找当前结点的父结点347    if(t == NULL || cur == NULL || cur == t){348        return NULL;349    }350    if(t->leftChild == cur || t->rightChild == cur){351        return t;352    }        //思路:利用父的孩子节点和当前节点比较353    BinTreeNode *p = parent(cur, t->leftChild);354    if(p != NULL){355        return p;356    }357358    return parent(cur, t->rightChild);359}360template<typename Type>361BinTreeNode* BinTree::find(const Type &key, BinTreeNode *t)const{   //查找当前结点362    if(t == NULL){363        return NULL;364    }365    if(t->data == key){366        return t;367    }368369    BinTreeNode *p = find(key, t->leftChild);370    if(p != NULL){371        return p;372    }373374    return find(key, t->rightChild);375}376template<typename Type>377int BinTree::height(BinTreeNode *t)const{  //求树的高度378    if(t == NULL){379        return 0;380    }381    int leftHeight = height(t->leftChild);382    int rightHeight = height(t->rightChild);383384    return (leftHeight > rightHeight ? leftHeight : rightHeight) + 1;385}386template<typename Type>387int BinTree::size(BinTreeNode *t)const{  //求结点个数388    if(t == NULL){389        return 0;390    }391392    return size(t->leftChild) + size(t->rightChild) + 1;393}394template<typename Type>395BinTreeNode* BinTree::createBinTree_1(const char *&str){  //创建二叉树396    BinTreeNode *t;397398    if(refval == *str){399        t = NULL;400    }else{401        t = new BinTreeNode(*str);402        t->leftChild = createBinTree_1(++str);403        t->rightChild = createBinTree_1(++str);404    }405    return t;406}407408template<typename Type>409void BinTree::createBinTree(const char *&str, BinTreeNode *&t){  //创建二叉树410    if(*str == refval){411        t = NULL;412    }else{413        t = new BinTreeNode(*str);414        createBinTree(++str, t->leftChild);  //前加,后加不一样!!!在这里,就是传引用,保证每次字符串都是往后走的415        createBinTree(++str, t->rightChild);416    }417}418template<typename Type>419BinTreeNode* BinTree::createBinTree_1(){  //创建二叉树420    Type createData;421    cin>>createData;422    BinTreeNode *t;423424    if(refval == createData){425        t = NULL;426    }else{427        t = new BinTreeNode(createData);428        t->leftChild = createBinTree_1();429        t->rightChild = createBinTree_1();430    }431432    return t;433}434template<typename Type>435void BinTree::endOrder(BinTreeNode *t)const{  //后序递归遍历436    if(t == NULL){437        return;438    }else{439        endOrder(t->leftChild);440        endOrder(t->rightChild);441        cout<data<<" ";442    }443}444445template<typename Type> 446void BinTree::inOrder(BinTreeNode *t)const{  //中序递归遍历447    if(t == NULL){448        return;449    }else{450        inOrder(t->leftChild);451        cout<data<<" ";452        inOrder(t->rightChild);453    }454}455456template<typename Type>457void BinTree::prevOrder(BinTreeNode *t)const{  //先序递归遍历458    if(t == NULL){459        return;460    }else{461        cout<data<<" ";462        prevOrder(t->leftChild);463        prevOrder(t->rightChild);464    }465}466//根据先根序创建二叉树467template<typename Type>468void BinTree::createBinTree(BinTreeNode *&t){  //创建二叉树469    Type createData;470    cin>>createData;471472    if(refval == createData){473        t = NULL;474    }else{475        t = new BinTreeNode(createData);476        createBinTree(t->leftChild);477        createBinTree(t->rightChild);478    }479}480481#endif
以上代码我采用折叠的方式进行写的;类外公有调用下面紧跟保护方法的实现。 (2)、测试代码
 1#include"BinTree.h"
2//ABC##DE##F##G#H##
3/* 4先根序如下: 5A B C D E F G H 6中根序如下: 7C B E D F A G H 8后根序如下: 9C E F D B H G A10*/
11int main(void){
12//    char *VLR = "ABCDEFGH";
13//    char *LVR = "CBEDFAGH";
14//    char *LRV = "CEFDBHGA";
15
16//    BinTree bt; //对象初始化不写'#';
17//    int n = strlen(VLR);
18//    bt.createBinTree(VLR, LVR, n); //在这里创建二叉树不用'#'结束,因为是由先序和中序创建,不看结束标志'#';
19//    bt.createBinTree_1(LVR, LRV, n);
20//    bt.prevOrder();
21//    cout<2223    //bt.createBinTree(VLR, LRV, n); 不能创建2425/*26    BinTree bt('#');27    char *str = "ABC##DE##F##G#H##";28//    char *str = "ABC##DE###G#H##";29    bt.createBinTree(str);30    BinTree bt1(bt);31    bt1.levelOrder();32    cout<3334*/3536/*    3738//    st.createBinTree();39    BinTree bt('#');40    BinTree bt1('#');41    char *str = "ABC##DE##F##G#H##";42    bt.createBinTree(str);43    bt1.createBinTree(str);  //构建的是一颗空树,引用传递构建,原先字符串已经为空!4445    if(bt.equal(bt1)){46        cout<47    }else{48        cout<49    }50*/    51    BinTree<char> bt('#');52    char *str = "ABC##DE##F##G#H##";53    bt.createBinTree(str);54    cout<endl;
55    cout<endl;56    BinTreeNode<char> *p = bt.find('H');57    BinTreeNode<char> *t = bt.find('G');58    printf("%p\n", t);59    BinTreeNode<char> *q = bt.parent(p);60    printf("%p\n", q);6162    bt.prevOrder();63    cout<<endl;64    bt.inOrder();65    cout<<endl;66    bt.endOrder();67    cout<<endl;6869    return 0;70}
这是所有测试要用的代码,在编写时,写一个方法测试一个,将测试过的就注释起来了。        (3)、部分测试结果 d13227700e810fd0740b0f0b9b69e8f0.png          97898b960f81ddb912c8e49db8c437c8.png      ec42d78a6a4e95ec28d12d93e9fd90b3.png f2652abaa2a2cfec5a1a0e8e893dfae1.png b7cb3ae1ec8e2bb74597dadaac8e5bea.png 至于其它的测试结果就不在给出了,有兴趣可以在测测其它的方法。 推荐阅读: 从零开始学习数据结构-->入门篇 从零开始学习数据结构-->链表 从零开始学习数据结构-->线性表 从零开始学习数据结构-->栈 从零开始学习数据结构-->队列 从零开始学习数据结构-->矩阵+串 从零开始学习数据结构-->哈希表 从零开始学习数据结构-->散列桶 从零开始学习数据结构-->二叉树 认真的人 自带光芒

dc911c90ea130280081e00ed37a23b57.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值