码迷,mamicode.com
首页 > 编程语言 > 详细

[C++]封装二叉树(附例题)

时间:2016-05-13 00:29:23      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

[C++]封装二叉树

题目要求

(简单的说,就是把二叉树的功能封装起来)

binary tree is a tree data structure in which each node has at most two children, which are referred to as the left child and the right child.

Three Constructor:

creat a tree by copy.
creat a tree by a array.(using BFS)
creat a tree by preorder and inorder.
Methods:

clear: clear the tree.
copyTree: input old tree root and new tree root, copy get a new tree.
Static Methods:

three way to search tree.

测试文件:

#include <iostream>
#include "BinaryTree.hpp"

using namespace std;

void print(BinaryTree::Node * temp) {
    cout << temp->val << " ";
}

std::vector<char> pre;
std::vector<char> in;

void getPreOrder(BinaryTree::Node * temp) {
    pre.push_back(temp->val);
}

void getInOrder(BinaryTree::Node * temp) {
    in.push_back(temp->val);
}

void testTree() {
    cout << "test Tree" << endl;
    int n = 1;
    std::vector<char> tree;
    cin >> n;
    while (n--) {
        char temp = ‘\0‘;
        cin >> temp;
        tree.push_back(temp);
    }

    BinaryTree x = BinaryTree(tree);

    BinaryTree::preOrder(print, x.getRoot());
    cout << endl;
    BinaryTree::inOrder(print, x.getRoot());
    cout << endl;
    BinaryTree::postOrder(print, x.getRoot());
    cout << endl;

    BinaryTree::preOrder(getPreOrder, x.getRoot());
    BinaryTree::inOrder(getInOrder, x.getRoot());

    BinaryTree t = BinaryTree(pre, in);
    BinaryTree::postOrder(print, t.getRoot());
    cout << endl;

    BinaryTree y = BinaryTree(t);

    BinaryTree::preOrder(print, y.getRoot());
    cout << endl;
    BinaryTree::inOrder(print, y.getRoot());
    cout << endl;
    BinaryTree::postOrder(print, y.getRoot());

    BinaryTree::preOrder(getPreOrder, y.getRoot());
    BinaryTree::inOrder(getInOrder, y.getRoot());
}

int main() {
    testTree();
}

接口文件:

//
//  BinaryTree.hpp
//  C++
//
//  Created by 李天培 on 16/5/4.
//  Copyright ? 2016年 lee. All rights reserved.
//

#ifndef BinaryTree_hpp
#define BinaryTree_hpp

#include <iostream>
#include <vector>
#include <queue>
#include <stack>

#define EMPTY_ELE ‘#‘

class BinaryTree {
public:
    struct Node {
        char val;
        Node* left;
        Node* right;
        Node(char v, Node* l = NULL, Node* r = NULL):
        val(v), left(l), right(r) {
        }
    };
    BinaryTree(const BinaryTree&);
    BinaryTree(std::vector<char>&);
    // created by preorder and inorder
    BinaryTree(const std::vector<char>& preOrder,
               const std::vector<char>& inOrder);
    ~BinaryTree();

    Node* getRoot() const;
    void clear();

    static void preOrder(void (*visite)(BinaryTree::Node*), Node*);
    static void inOrder(void (*visite)(BinaryTree::Node*), Node*);
    static void postOrder(void (*visite)(BinaryTree::Node*), Node*);


private:
    Node * copyNode(Node * oldNode, Node * newNode);

    Node * root;
};

#endif /* BinaryTree_hpp */

问题分析

先来讨论相对简单的访问二叉树问题。

遍历问题

前(先)序遍历

技术分享

中序遍历

技术分享

后序遍历

技术分享

代码实现:

void BinaryTree::preOrder(void (*visite)(BinaryTree::Node *),
                          BinaryTree::Node * treeNode) {
    if (treeNode != NULL) {
        visite(treeNode);
        preOrder(visite, treeNode->left);
        preOrder(visite, treeNode->right);
    }
}
void BinaryTree::inOrder(void (*visite)(BinaryTree::Node *),
                         BinaryTree::Node * treeNode) {
    if (treeNode != NULL) {
        inOrder(visite, treeNode->left);
        visite(treeNode);
        inOrder(visite, treeNode->right);
    }
}
void BinaryTree::postOrder(void (*visite)(BinaryTree::Node *),
                           BinaryTree::Node * treeNode) {
    if (treeNode != NULL) {
        postOrder(visite, treeNode->left);
        postOrder(visite, treeNode->right);
        visite(treeNode);
    }
}

根据前序后序求中序

已知前序遍历为GDAFEMHZ,中序遍历为ADEFGHMZ,请画出这棵二叉树。

①根据前序遍历特征,我们知道根结点必在首位置,所以为G;

②根据中序遍历特征。其中根节点G左侧的ADEF必然是根节点的左子树,G右侧的HMZ必然是根节点的右子树;

③根据前序中序特征,重复以上步骤。递归找到子树根节点;

那么,我们可以画出这个二叉树:

技术分享

由图可知,后序遍历顺序为:AEFDHZMG

代码实现

BinaryTree::Node* recursionBuild(const std::vector<char>& preorder,
                                 unsigned long preLeft,
                                 unsigned long preRight,
                                 const std::vector<char>& inorder,
                                 unsigned long inLeft,
                                 unsigned long inRight) {
    if (preLeft > preRight || preRight == preorder.size() ||
        inLeft > inRight || inRight == inorder.size())
        return NULL;

    unsigned long i = 0;

    BinaryTree::Node* node = new BinaryTree::Node(preorder[preLeft]);

    for (i = inLeft; i <= inRight; i++) {
        if (inorder[i] == node->val) {
            break;
        }
    }

    node->left =  recursionBuild(preorder,
                                 preLeft + 1, preLeft + i -inLeft,
                                 inorder,
                                 inLeft, i - 1);
    node->right = recursionBuild(preorder,
                                 preLeft + i - inLeft + 1, preRight,
                                 inorder,
                                 i + 1, inRight);

    return node;
}
BinaryTree::BinaryTree(const std::vector<char> & preorder,
                       const std::vector<char> & inorder) {
    root = NULL;
    unsigned long preSize = preorder.size();
    unsigned long inSize = inorder.size();
    if (preSize == 0 || preSize != inSize) {
        return;
    }

    root = recursionBuild(preorder, 0, preSize - 1,
                          inorder, 0, inSize - 1);
}

根据后序中序求前序

已知一棵二叉树的中序序列和后序序列分别是BDCEAFHG 和 DECBHGFA,请画出这棵二叉树。
分析:

  • ①由后序遍历特征,根结点必在后序序列尾部(即A);
  • ②由中序遍历特征,根结点必在其中间,而且其左部必全部是左子树的子孙(即BDCE),其右部必全部是右子树的子孙(即FHG);
  • ③递归找出子树根节点。

那么,我们可以画出这个二叉树:

技术分享

注意事项:

左子树中序为BDCE,后序为DECB,说明B为A的左子树根节点,C为B的右子树(从BDCE看出)根节点(从DCE及DEC看出);

右子树中序为FHG,后序为HGF,说明F为A的右子树的根节点,H为G的左子树根节点。

构造过程

接下来讨论在构造过程中出现的难点。

用队列让vector构造二叉树

用队列可以实现FIFO,从而让每一个节点都依次赋值。但必须注意在queue中要存储_Node**,就是存储一个指向指针的指针。(因为在其内部应该实现了深复制。所以如果只用_Node*会就会复制指针所指向的对象(都为NULL),这与我们的算法就想违背了。)

BinaryTree::BinaryTree(std::vector<char>& orig) {
    std::queue<_Node**> queue_Node;
    if (!orig.empty() && orig[0] != EMPTY_ELE) {
        root = new _Node(orig[0]);
        queue_Node.push(&root->left);
        queue_Node.push(&root->right);
        int i = 1;
        while (!queue_Node.empty()) {
            _Node** temp = queue_Node.front();
            queue_Node.pop();
            if (i >= orig.size()) {
                temp = NULL;
                i++;
            } else if (orig[i] == EMPTY_ELE) {
                temp = NULL;
                i++;
            } else {
                *temp = new _Node(orig[i++]);
                queue_Node.push(&((*temp)->left));
                queue_Node.push(&((*temp)->right));
            }
        }
    } else {
        root = NULL;
    }
}

第二种方法:(更细致的实现方法。)

BinaryTree::BinaryTree(std::vector<char> & elements) {
    unsigned long size = elements.size();
    int index = 0;
    std::queue<Node*> queue;
    if (elements.empty() || elements[index] == EMPTY_ELE) {
        root = NULL;
    } else {
        root = new Node(elements[index]);
        queue.push(root);
        index += 1;
        while (index < size) {
            Node* temp = queue.front();
            queue.pop();
            if (elements[index] != EMPTY_ELE) {
                temp->left = new Node(elements[index]);
                queue.push(temp->left);
            }
            index += 1;
            if (index >= size) {
                break;
            }
            if (elements[index] != EMPTY_ELE) {
                temp->right = new Node(elements[index]);
                queue.push(temp->right);
            }
            index += 1;
        }
    }
}

copy构造函数(递归实现)

BinaryTree::Node* BinaryTree::copyNode(BinaryTree::Node *oldNode,
                                       BinaryTree::Node *newNode) {
    if (oldNode == NULL) {
        newNode = NULL;
        return newNode;
    }

    newNode = new Node(oldNode->val);
    newNode->left = copyNode(oldNode->left, newNode->left);
    newNode->right = copyNode(oldNode->right, oldNode->right);
    return newNode;
}
BinaryTree::BinaryTree(const BinaryTree &old) {
    root = NULL;
    root = copyNode(old.getRoot(), root);
}

问题解决


//
//  BinaryTree.cpp
//  C++
//
//  Created by 李天培 on 16/5/4.
//  Copyright ? 2016年 lee. All rights reserved.
//

#include "BinaryTree.hpp"
BinaryTree::Node* recursionBuild(const std::vector<char>& preorder,
                                 unsigned long preLeft,
                                 unsigned long preRight,
                                 const std::vector<char>& inorder,
                                 unsigned long inLeft,
                                 unsigned long inRight) {
    if (preLeft > preRight || preRight == preorder.size() ||
        inLeft > inRight || inRight == inorder.size())
        return NULL;

    unsigned long i = 0;

    BinaryTree::Node* node = new BinaryTree::Node(preorder[preLeft]);

    for (i = inLeft; i <= inRight; i++) {
        if (inorder[i] == node->val) {
            break;
        }
    }

    node->left =  recursionBuild(preorder,
                                 preLeft + 1, preLeft + i -inLeft,
                                 inorder,
                                 inLeft, i - 1);
    node->right = recursionBuild(preorder,
                                 preLeft + i - inLeft + 1, preRight,
                                 inorder,
                                 i + 1, inRight);

    return node;
}


BinaryTree::BinaryTree(const BinaryTree &old) {
    root = NULL;
    root = copyNode(old.getRoot(), root);
}

BinaryTree::BinaryTree(const std::vector<char> & preorder,
                       const std::vector<char> & inorder) {
    root = NULL;
    unsigned long preSize = preorder.size();
    unsigned long inSize = inorder.size();
    if (preSize == 0 || preSize != inSize) {
        return;
    }

    root = recursionBuild(preorder, 0, preSize - 1,
                          inorder, 0, inSize - 1);
}
BinaryTree::BinaryTree(std::vector<char> & elements) {
    unsigned long size = elements.size();
    int index = 0;
    std::queue<Node*> queue;
    if (elements.empty() || elements[index] == EMPTY_ELE) {
        root = NULL;
    } else {
        root = new Node(elements[index]);
        queue.push(root);
        index += 1;
        while (index < size) {
            Node* temp = queue.front();
            queue.pop();
            if (elements[index] != EMPTY_ELE) {
                temp->left = new Node(elements[index]);
                queue.push(temp->left);
            }
            index += 1;
            if (index >= size) {
                break;
            }
            if (elements[index] != EMPTY_ELE) {
                temp->right = new Node(elements[index]);
                queue.push(temp->right);
            }
            index += 1;
        }
    }
}

BinaryTree::Node* BinaryTree::copyNode(BinaryTree::Node *oldNode,
                                       BinaryTree::Node *newNode) {
    if (oldNode == NULL) {
        newNode = NULL;
        return newNode;
    }

    newNode = new Node(oldNode->val);
    newNode->left = copyNode(oldNode->left, newNode->left);
    newNode->right = copyNode(oldNode->right, oldNode->right);
    return newNode;
}


BinaryTree::Node* BinaryTree::getRoot() const {
    return root;
}

BinaryTree::~BinaryTree() {
    clear();
}
void BinaryTree::clear() {
    std::queue<Node*> queue;
    if (root != NULL) {
        queue.push(root);
    }
    while (!queue.empty()) {
        Node * temp = queue.front();
        queue.pop();
        if (temp->left != NULL)
            queue.push(temp->left);
        if (temp->right != NULL)
            queue.push(temp->right);
        delete temp;
    }
}

void BinaryTree::preOrder(void (*visite)(BinaryTree::Node*), Node* r = NULL) {
    Node *temp = r;
    if (temp == NULL) {
        return;
    } else {
        visite(temp);
        preOrder(visite, temp->left);
        preOrder(visite, temp->right);
    }
}

void BinaryTree::inOrder(void (*visite)(BinaryTree::Node*), Node* r = NULL) {
    Node *temp = r;
    if (temp == NULL) {
        return;
    } else {
        inOrder(visite, temp->left);
        visite(temp);
        inOrder(visite, temp->right);
    }
}

void BinaryTree::postOrder(void (*visite)(BinaryTree::Node*), Node* r = NULL) {
    Node *temp = r;
    if (temp == NULL) {
        return;
    } else {
        postOrder(visite, temp->left);
        postOrder(visite, temp->right);
        visite(temp);
    }
}

[C++]封装二叉树(附例题)

标签:

原文地址:http://blog.csdn.net/stary_yan/article/details/51347423

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!