数据结构、算法与应用 C++语言描述 第11章部分习题

// binaryTreeNode.h


//
// Created by Dell on 2021/6/9.
//

#ifndef CHAPTER11_BINARYTREENODE_H
#define CHAPTER11_BINARYTREENODE_H

#include "string"
#include "stack"
#include "queue"
#include "vector"

using namespace std;

template<class T>
struct binaryTreeNode
{
    T element;
    binaryTreeNode<T> *leftChild, *rightChild;

    binaryTreeNode() {leftChild=rightChild=NULL;}
    binaryTreeNode(const T& theElement){
        element = theElement;
        leftChild=rightChild=NULL;
    }
    binaryTreeNode(const T& theElement, binaryTreeNode<T>* theLeft, binaryTreeNode<T>*theRight):element(theElement), leftChild(theLeft), rightChild(theRight) {}
};

// 输出测试
template<class T>
void visit(binaryTreeNode<T>* x)
{
    std::cout << x->element << " ";
}

template<class T>
void inOrder(binaryTreeNode<T>* x)
{
    if(x!=NULL){
        inOrder(x->leftChild);
        visit(x);
        inOrder(x->rightChild);
    }
}

// Q25(1)
template<class T>
void postCopyTreeNode(binaryTreeNode<T>* sourceNode, binaryTreeNode<T>* targetNode)
{
    if (sourceNode!=NULL){
        if (sourceNode->leftChild!=NULL) {
            targetNode->leftChild = new binaryTreeNode<T>();
            preCopyTreeNode(sourceNode->leftChild, targetNode->leftChild);
        }
        if (sourceNode->rightChild!=NULL) {
            targetNode->rightChild = new binaryTreeNode<T>();
            preCopyTreeNode(sourceNode->rightChild, targetNode->rightChild);
        }
        targetNode->element = sourceNode->element;
    }
}

// Q25(2)
template<class T>
void preCopyTreeNode(binaryTreeNode<T>* sourceNode, binaryTreeNode<T>* targetNode)
{
    if (sourceNode!=NULL){
        targetNode->element = sourceNode->element;
        if (sourceNode->leftChild!=NULL) {
            targetNode->leftChild = new binaryTreeNode<T>();
            preCopyTreeNode(sourceNode->leftChild, targetNode->leftChild);
        }
        if (sourceNode->rightChild!=NULL) {
            targetNode->rightChild = new binaryTreeNode<T>();
            preCopyTreeNode(sourceNode->rightChild, targetNode->rightChild);
        }
    }
}

// Q26 后序的方法,这里应该可以把两个程序优化成一个,
template<class T>
void calculateGetNum(binaryTreeNode<T>* sourceNode, std::stack<int>& numStack)
{
    if (sourceNode!=NULL){
        calculateGetNum(sourceNode->leftChild, numStack);
        calculateGetNum(sourceNode->rightChild, numStack);

        int num1, num2;
        if (sourceNode->element != "+" && sourceNode->element != "-" && sourceNode->element != "*" && sourceNode->element != "/"){
            num1 = atoi(sourceNode->element.c_str());
            numStack.push(num1);
        } else{
            num1 = numStack.top();
            numStack.pop();
            num2 = numStack.top();
            numStack.pop();
            if(sourceNode->element== "+")
                numStack.push(num2 + num1);
            else if(sourceNode->element == "-")
                numStack.push(num2 - num1);
            else if(sourceNode->element== "*")
                numStack.push(num2 * num1);
            else if(sourceNode->element == "/")
                numStack.push(num2 / num1);
        }
    }
}
template<class T>
int calculateNum(binaryTreeNode<T>* sourceNode)
{
    std::stack<int> numStack;
    calculateGetNum(sourceNode, numStack);
    return numStack.top();
}

// Q27 依然是递归
template<class T>
int getDepth(binaryTreeNode<T>* sourceNode){
    if (sourceNode!=NULL){
        int numLeft = getDepth(sourceNode->leftChild);
        int numRight = getDepth(sourceNode->rightChild);
        return numLeft > numRight ? numLeft+1 : numRight+1;
    }
    return 0;
}

// Q28 计算节点个数
template<class T>
int getNodeCount(binaryTreeNode<T>* sourceNode){
    if (sourceNode!=NULL){
        int numLeft = getNodeCount(sourceNode->leftChild);
        int numRight = getNodeCount(sourceNode->rightChild);
        return numLeft + numRight + 1;
    }
    return 0;
}

// Q29 节点最多的层数
template<class T>
int nodeMostLayer(binaryTreeNode<T>* sourceNode){
    std::queue<binaryTreeNode<T>* > q;
    int totalLayer = getDepth(sourceNode);
    int *layerCounts = new int[totalLayer+1]{0}; // 没有第0层,全部初始化为0

    if (sourceNode==NULL) return 0;
    else layerCounts[1]=1; // 根节点一定是1个

    int mostLayer=0, mostLayerCount=0, currentLayer=1;
    binaryTreeNode<T> *currentNode = sourceNode;
    while (currentNode != NULL){
        if (currentNode->leftChild != NULL){
            q.push(currentNode->leftChild);
            ++layerCounts[currentLayer+1]; // 更新下一层的个数
        }
        if (currentNode->rightChild != NULL){
            q.push(currentNode->rightChild);
            ++layerCounts[currentLayer+1];
        }
        if (!q.empty()){
            currentNode = q.front();
            q.pop();
        } else
            currentNode = NULL;
        --layerCounts[currentLayer]; // 这里已经减1了,所以下边要加1
        if (layerCounts[currentLayer]==0) // 当前层遍历完成
            ++currentLayer; // 切换到下一层
        else if (layerCounts[currentLayer] > mostLayerCount){ // 还在当前层
            mostLayerCount = layerCounts[currentLayer] + 1;
            mostLayer = currentLayer;
        }
    }
    std::cout << "layer: " << mostLayer << " count: " << mostLayerCount << std::endl;
    return mostLayer;
}

// Q30 将二叉树保存到栈中
template<class T>
void inVec(binaryTreeNode<T>* sourceNode, std::vector<T>& myVec){
    if(sourceNode!=NULL){
        inVec(sourceNode->leftChild, myVec);
        myVec.push_back(sourceNode->element);
        inVec(sourceNode->rightChild, myVec);
    }
}

// Q31 将二叉树保存到栈中,因为使用了栈,所以输出顺序和入栈顺序相反
template<class T>
void preVec(binaryTreeNode<T>* sourceNode, std::vector<T>& myVec){
    if(sourceNode!=NULL){
        myVec.push_back(sourceNode->element);
        preVec(sourceNode->leftChild, myVec);
        preVec(sourceNode->rightChild, myVec);
    }
}

// Q32 将二叉树保存到栈中
template<class T>
void postVec(binaryTreeNode<T>* sourceNode, std::vector<T>& myVec){
    if(sourceNode!=NULL){
        postVec(sourceNode->leftChild, myVec);
        postVec(sourceNode->rightChild, myVec);
        myVec.push_back(sourceNode->element);
    }
}

// Q33需要用递归实现,且需要保证各个节点的数据各不相同,否则获取的二叉树不唯一
// 需要重新导入二叉树数据


//template<class T>
//void Q33Recursion(binaryTreeNode<T>* targetNode, vector<T>& inVec, stack<T>& preStack,int parentIndex, int grandParentIndex)
//{
//    if (!preStack.empty()){
//        T curElement = preStack.top();
//
//        int currentIndex = 0;
//        for(auto t : inVec){
//            if (t == curElement)
//                break;
//            else
//                ++currentIndex;
//        }
//        if (currentIndex<parentIndex){ // 在当前分支下
//            targetNode->leftChild = new binaryTreeNode<T>(curElement);
//            preStack.pop();
//            Q33Recursion(targetNode->leftChild, inVec, preStack, currentIndex, parentIndex);
//        }
//    }
//
//    if (!preStack.empty()){
//        T curElement = preStack.top();
//
//        int currentIndex = 0;
//        for(auto t : inVec){
//            if (t == curElement)
//                break;
//            else
//                ++currentIndex;
//        }
//        if (currentIndex>parentIndex && currentIndex < grandParentIndex) { // 右节点
//            targetNode->rightChild = new binaryTreeNode<T>(curElement);
//            preStack.pop();
//            Q33Recursion(targetNode->rightChild, inVec, preStack, currentIndex, parentIndex);
//        }
//    }
//}
//
//template<class T>
//binaryTreeNode<T>* getTreeFromPreAndInStack(binaryTreeNode<T>* sourceNode)
//{
//    vector<T> MyPreVec, MyInVec;
//    preVec(sourceNode, MyPreVec);
//    inVec(sourceNode, MyInVec);
//
//    stack<T> PreStack;
//    for (int i = MyPreVec.size()-1;i >=0 ; --i)
//        PreStack.push(MyPreVec[i]);
//
//    T curElement = PreStack.top();
//    PreStack.pop();
//
//    int currentIndex = 0;
//    for(auto t : MyInVec){
//        if (t == curElement)
//            break;
//        else
//            ++currentIndex;
//    }
//
//    auto targetNode = new binaryTreeNode<T>(curElement);
//    Q33Recursion(targetNode, MyInVec, PreStack, currentIndex, MyInVec.size());
//    return targetNode;
//}

// Q33
// 这个递归和上一个不成功的递归之间的区别就是是否把中序vector逐个拆开,如果不拆开就会导致上面的混乱
// 且引入很多不必要复杂的表示
template<class T>
binaryTreeNode<T>* Q33Recursion(vector<T>& inVec, stack<T>& preStack)
{
    binaryTreeNode<T>* node = NULL;
    if (!preStack.empty() && inVec.size() > 0)
    {
        T curElement = preStack.top();
        int currentIndex = 0;
        for(auto t : inVec){
            if (t == curElement)
                break;
            else
                ++currentIndex;
        }
        if (currentIndex<inVec.size()) { // 当前vector中存在当前所需元素
//            构造分别对应当前的
            vector<T> leftVec(inVec.begin(), inVec.begin()+currentIndex);
            vector<T> rightVec(inVec.begin()+currentIndex+1, inVec.end());
            preStack.pop();
            node = new binaryTreeNode<T>(curElement);
            node->leftChild = Q33Recursion(leftVec, preStack);
            node->rightChild = Q33Recursion(rightVec, preStack);
        }
    }
    return node;
}

template<class T>
binaryTreeNode<T>* getTreeFromPreAndInStack(binaryTreeNode<T>* sourceNode)
{
    vector<T> MyPreVec, MyInVec;
    preVec(sourceNode, MyPreVec);
    inVec(sourceNode, MyInVec);
    stack<T> PreStack;
    for (int i = MyPreVec.size()-1;i >=0 ; --i)
        PreStack.push(MyPreVec[i]);

    binaryTreeNode<T>* p = Q33Recursion(MyInVec, PreStack);
    return p;
}

// 每个运算。符必须有两个操作数,否则会有错误
binaryTreeNode<char>* getTreeFromPostOrder(string strVec)
{
    stack<binaryTreeNode<char>*> NodeStack;
    for(auto str : strVec){
        auto temp = new binaryTreeNode<char>(str);
        if (str == '+' || str == '-' || str == '*' || str == '/' ){ //单操作数或者双操作数
            temp->rightChild = NodeStack.top();
            NodeStack.pop();
            if (!NodeStack.empty()){
                temp->leftChild = NodeStack.top();
                NodeStack.pop();
            }
        }
        NodeStack.push(temp);
    }
    return NodeStack.top();
}

#endif //CHAPTER11_BINARYTREENODE_H

测试函数

// main.c

#include <iostream>
#include <string>
#include "include/binaryTreeNode.h"

using namespace std;

int main() {
    // 手动实现二叉树的初始化
//    auto* rootNode = new binaryTreeNode<string>("+");
//    rootNode->leftChild = new binaryTreeNode<string>("+");
//    rootNode->leftChild->leftChild = new binaryTreeNode<string>("*");
//    rootNode->leftChild->rightChild = new binaryTreeNode<string>("12");
//    rootNode->leftChild->leftChild->leftChild = new binaryTreeNode<string>("2");
//    rootNode->leftChild->leftChild->rightChild = new binaryTreeNode<string>("4");
//
//    rootNode->rightChild = new binaryTreeNode<string>("-");
//    rootNode->rightChild->leftChild = new binaryTreeNode<string>("*");
//    rootNode->rightChild->leftChild->leftChild = new binaryTreeNode<string>("8");
//    rootNode->rightChild->leftChild->rightChild = new binaryTreeNode<string>("2");
//    rootNode->rightChild->rightChild = new binaryTreeNode<string>("+");
//    rootNode->rightChild->rightChild->leftChild = new binaryTreeNode<string>("6");
//    rootNode->rightChild->rightChild->rightChild = new binaryTreeNode<string>("/");
//    rootNode->rightChild->rightChild->rightChild->leftChild = new binaryTreeNode<string>("8");
//    rootNode->rightChild->rightChild->rightChild->rightChild = new binaryTreeNode<string>("2");

    auto* rootNode = new binaryTreeNode<string>("a");
    rootNode->leftChild = new binaryTreeNode<string>("b");
    rootNode->leftChild->leftChild = new binaryTreeNode<string>("c");
    rootNode->leftChild->rightChild = new binaryTreeNode<string>("d");
    rootNode->leftChild->leftChild->leftChild = new binaryTreeNode<string>("e");
    rootNode->leftChild->leftChild->rightChild = new binaryTreeNode<string>("f");

    rootNode->rightChild = new binaryTreeNode<string>("g");
    rootNode->rightChild->leftChild = new binaryTreeNode<string>("h");
    rootNode->rightChild->leftChild->leftChild = new binaryTreeNode<string>("i");
    rootNode->rightChild->leftChild->rightChild = new binaryTreeNode<string>("j");
    rootNode->rightChild->rightChild = new binaryTreeNode<string>("k");
    rootNode->rightChild->rightChild->leftChild = new binaryTreeNode<string>("l");
    rootNode->rightChild->rightChild->rightChild = new binaryTreeNode<string>("m");
    rootNode->rightChild->rightChild->rightChild->leftChild = new binaryTreeNode<string>("n");
    rootNode->rightChild->rightChild->rightChild->rightChild = new binaryTreeNode<string>("o");

//    inOrder(rootNode); // 中序输出
//    auto* preCopyNode = new binaryTreeNode<string>();
//    auto* postCopyNode = new binaryTreeNode<string>();
//    preCopyTreeNode(rootNode, preCopyNode);
    rootNode->element = "fdfa";
//    cout << endl << "pre"<< endl;
//    inOrder(preCopyNode);
//    postCopyTreeNode(rootNode, postCopyNode);
//    cout << endl << "post"<< endl;
//    inOrder(postCopyNode);
//    cout << calculateNum(rootNode) << endl;
//    cout << getDepth(rootNode) << endl;
//    cout << getNodeCount(rootNode) << endl;
//    nodeMostLayer(rootNode);


//    vector<string> MyVec;
//    preVec(rootNode, MyVec);
//    cout << "preStack: ";
//    for (auto v : MyVec)
//        cout << v << " ";
//    MyVec.clear();
//    cout << endl;
//
//    inVec(rootNode, MyVec);
//    cout << "inStack:  ";
//    for (auto v : MyVec)
//        cout << v << " ";
//    MyVec.clear();

//    auto targetNode = getTreeFromPreAndInStack(rootNode);
//    vector<string> MyVec;
//    preVec(rootNode, MyVec);
//    for (auto v : MyVec)
//        cout << v << " ";
//    MyVec.clear();
//    cout << endl;
//    inOrder(rootNode);
//    cout << endl;
//    inOrder(targetNode);

    auto cal = getTreeFromPostOrder("ba-xy++eb+ca**/");
    inOrder(cal);

    return 0;
}

// linkedBinaryTree.h

//
// Created by Dell on 2021/6/28.
//
#ifndef CHAPTER11_LINKEDBINARYTREE_H
#define CHAPTER11_LINKEDBINARYTREE_H

#include "binaryTree.h"
#include "binaryTreeNode.h"
#include "stack"

template<class T>
class linkedBinaryTree : public binaryTree<binaryTreeNode<T> > // 把节点作为元素的数据类型
{
public:
    linkedBinaryTree() {root=NULL, treeSize=0;}
    ~linkedBinaryTree() {erase();}; // 这里为什么多一个分号
    bool empty() const {return treeSize==0;}
    int size() const {return treeSize;}
    void preOrder(void (*theVisit)(binaryTreeNode<T>*)) {visit = theVisit, preOrder(root);}
    void inOrder(void(*theVisit)(binaryTreeNode<T>*)) {visit = theVisit, inOrder(root);}
    void postOrder(void(*theVisit)(binaryTreeNode<T>*)) {visit = theVisit, postOrder(root);}
    void erase()
    {
        postOrder(dispose); // 用此函数对visit函数进行赋值
        root = NULL;
        treeSize = 0;
    }
    static void output(binaryTreeNode<T>* t) {std::cout << t->element << " "; }
    void preOrderOutput() { preOrder(output), std::cout << std::endl;} // 传递函数指针,所以output不用指定参数,内部调用visit时会指定
    void inOrderOutput() { inOrder(output), std::cout << std::endl;}
    void postOrderOutput() { postOrder(output), std::cout << std::endl;}

    int height() const { return height(root); }
    int height(binaryTreeNode<T> *);

    linkedBinaryTree(const linkedBinaryTree<T> &); // 复制构造函数
    void initialize(binaryTreeNode<T> *); // 从一个已有根节点的二叉树结构的初始化此类对象
    bool compare(const linkedBinaryTree<T> &);
    void swapTrees();

    // 中序输出
    class forwardIterator{
    public:
        friend forwardIterator linkedBinaryTree<T>::begin();
        explicit forwardIterator(binaryTreeNode<T>* theNode = NULL) { node = theNode; }
        //解引用操作符
        T& operator*() const { return node->element; }
        T* operator->() const {return &node->element; }

        // 相等验证
        bool operator==(const forwardIterator& right) const { return node == right.node; }
        bool operator!=(const forwardIterator& right) const { return node != right.node; }

        // 单向递增
        forwardIterator& operator++() {node=nodeQueue.front();nodeQueue.pop();return *this;}
        forwardIterator operator++(int) {forwardIterator temp=node;node=nodeQueue.front();nodeQueue.pop();return temp;}
    private:
        binaryTreeNode<T>* node;
        std::queue<binaryTreeNode<T>*> nodeQueue;
    };

    forwardIterator begin() {
        forwardIterator temp;
        getForwardIteratorQueue(temp.nodeQueue, root);
        temp.nodeQueue.push(NULL); // 用于判断是否到尾
        temp.node = temp.nodeQueue.front();
        temp.nodeQueue.pop();
        return temp;
    }
    forwardIterator end() const {return forwardIterator();}

private:
    binaryTreeNode<T> *root;
    int treeSize;
    // 函数指针,用来访问节点元素,可以对这个函数指针进行赋值
    // 那么就会将赋值的指针的函数的功能传递过来,所以visit本质是一个指针变量
    // static函数是类的所用对象共有,只能修改static成员变量
    static void (*visit)(binaryTreeNode<T>*);
    void preOrder(binaryTreeNode<T> *);
    void inOrder(binaryTreeNode<T> *);
    void postOrder(binaryTreeNode<T> *);
    static void dispose(binaryTreeNode<T>* t) { delete t;}
    void copyConstructor(binaryTreeNode<T>* srcNode, binaryTreeNode<T>* &targetNode);
    bool compare(const binaryTreeNode<T>* firstNode, const binaryTreeNode<T>* secondNode);
    void swapTrees(binaryTreeNode<T>* &firstNode, binaryTreeNode<T>* &secondNode);
    void getForwardIteratorQueue(std::queue<binaryTreeNode<T>*> &myQueue, binaryTreeNode<T>* x);
};

// 这里很重要,由于visit是函数指针,本质是一个普通变量
// 而且又是一个static变量,所以需要在类外进行初始化
template<class T>
void (*linkedBinaryTree<T>::visit)(binaryTreeNode<T>*) = nullptr;

template<class T>
int linkedBinaryTree<T>::height(binaryTreeNode<T> *t) {
    if (t==NULL)
        return 0;
    int hl = height(t->leftChild);
    int hr = height(t->rightChild);
    if (hl > hr) // 还要加上本层的高度
        return ++hl;
    else
        return ++hr;
}

template<class T>
linkedBinaryTree<T>::linkedBinaryTree(const linkedBinaryTree<T> &srcTree) {
    copyConstructor(srcTree.root, this->root);
    this->treeSize = srcTree.treeSize;
}


template<class T>
void linkedBinaryTree<T>::preOrder(binaryTreeNode<T> *t) {
    if (t != NULL){
        visit(t);
        preOrder(t->leftChild);
        preOrder(t->rightChild);
    }
}

template<class T>
void linkedBinaryTree<T>::inOrder(binaryTreeNode<T> *t) {
    if (t != NULL){
        inOrder(t->leftChild);
        visit(t);
        inOrder(t->rightChild);
    }
}

template<class T>
void linkedBinaryTree<T>::postOrder(binaryTreeNode<T> *t) {
    if (t != NULL){
        postOrder(t->leftChild);
        postOrder(t->rightChild);
        visit(t);
    }
}

// 注意这里指针的引用
template<class T>
void linkedBinaryTree<T>::copyConstructor(binaryTreeNode<T>* srcNode, binaryTreeNode<T>* &targetNode) {
    if (srcNode != NULL){
        ++treeSize;
        targetNode = new binaryTreeNode<T>(srcNode->element);
        copyConstructor(srcNode->leftChild, targetNode->leftChild);
        copyConstructor(srcNode->rightChild, targetNode->rightChild);
    }
}

template<class T>
void linkedBinaryTree<T>::initialize(binaryTreeNode<T> *srcNode) {
    this->treeSize=0;
    copyConstructor(srcNode, root);
}

template<class T>
bool linkedBinaryTree<T>::compare(const linkedBinaryTree<T> &theTree) {
    if (size()!=theTree.size())
        return false;
    return compare(root, theTree.root);
}

template<class T>
bool linkedBinaryTree<T>::compare(const binaryTreeNode<T> *firstNode, const binaryTreeNode<T> *secondNode) {
    if (firstNode==NULL && secondNode==NULL)
        return true;
    if ((firstNode==NULL && secondNode!=NULL) || (firstNode!=NULL && secondNode==NULL))
        return false;
    // 全都有值
    if (firstNode->element != secondNode->element)
        return false;
    else // 在元素值相等的前提下
        return compare(firstNode->leftChild, secondNode->leftChild) && compare(firstNode->rightChild, secondNode->rightChild);
}

template<class T>
void linkedBinaryTree<T>::swapTrees() {
    swapTrees(root->leftChild, root->rightChild);
}

template<class T>
void linkedBinaryTree<T>::swapTrees(binaryTreeNode<T>* &firstNode, binaryTreeNode<T>* &secondNode) {
    if (firstNode!=NULL && secondNode!=NULL) {
        binaryTreeNode<T>* temp;
        temp = firstNode;
        firstNode = secondNode;
        secondNode = temp;
        swapTrees(firstNode->leftChild, firstNode->rightChild);
        swapTrees(secondNode->leftChild, secondNode->rightChild);
    }
}

template<class T>
void linkedBinaryTree<T>::getForwardIteratorQueue(std::queue<binaryTreeNode<T> *> &myQueue, binaryTreeNode<T> *x) {
    if(x!=NULL){
        getForwardIteratorQueue(myQueue, x->leftChild);
        myQueue.push(x);
        getForwardIteratorQueue(myQueue, x->rightChild);
    }
}


#endif //CHAPTER11_LINKEDBINARYTREE_H


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值