函数递归调用图
二叉树
// 二叉树.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include "pch.h"#include <stdio.h>struct Node {    int nData;        // 节点的数据域    Node* pLeft;    // 左子树指针    Node* pRight;    // 右子树指针    Node() :pLeft(), pRight() {}    Node(int nData)         :nData(nData),pLeft(), pRight()    {}};// 二叉查找树class BSTree {    int m_nCount = 0; // 树中节点个数    Node* m_pRoot = 0;// 根节点指针:记录树中的根节点地址.protected:    // 参数1是指针的引用, 为的是能够在    // 函数内部修改函数外部的实参(可以参考交换两个变量的函数)    /*!     * 函数名 : insert     * 功  能 : 将数据nData插入到pTree作为根节点的树居中     * 参  数 : Node * & pTree 树的根节点.     * 参  数 : int nData 插入的数据     * 返回值 :  void     */    void insert( Node*& pTree, int nData) {        // 1. 判断树的根节点是否为NULL,如果为NULL        //    直接插入到根节点        if (pTree == nullptr) {            pTree = new Node(nData);            // 递增节点个数            ++m_nCount;            return;        }        // 2. 如果不为空,则判断插入的数据和根节点        //    所保存的数据的大小关系        if (nData < pTree->nData) {            // 3. 如果插入数据小于根节点数据,那么就将            //    根节点的左子树作为新的根节点,让后将            //    数据插入到左子树中.            insert(pTree->pLeft, nData);        }        else {            // 否则就插入到右子树中.            insert(pTree->pRight, nData);        }        }    Node*& find(Node*& pTree, int nData) {        if (pTree == nullptr) {            return pTree;        }        // 1. 判断当前节点保存的数据是否        //    就是要查找的数据        if (pTree->nData == nData) {            // 如果是, 就返回节点本身            return pTree;        }        // 如果不是, 则判断这个数据是在节点的左子树中        // 还是在右子树中.        // 因为二叉树是左小右大的.        // 因此, 比较要删除的数据和当前节点的大小关系        // 就能知道是在左子树还是在右子树中        else if (nData < pTree->nData) {            return find(pTree->pLeft,nData);        }        else {            return find(pTree->pRight,nData);        }    }    void remove(Node*& pTree, int nData) {        if (pTree == nullptr) {            return;        }        printf("-------- 删除:%d-----  \n", nData);        printTree();        // 1. 在树中查找到要删除的节点.        Node*& pFindNode = find(pTree, nData);        // 是否能够找到节点.        if (pFindNode == nullptr) {            return;        }        // 2. 找到节点的就是被删除的节点        //    删除时要判断节点是否是一个叶子节点        //    如果是叶子节点可以直接删除        if (pFindNode->pLeft == nullptr && pFindNode->pRight == nullptr) {            // 直接删除            delete pFindNode;            // 将指针设置为空,由于pFindNode是一个指针            // 的引用, 因此它修改的是哪里????(实际上修改的是            // 父节点的右子树指针或左子树指针)            pFindNode = nullptr;            // 递减节点个数            --m_nCount;            return;        }        // 3. 如果不是叶子节点. 就需要在被删除节点的        //    子树中找到一个叶子节点, 然后两者的值        //    互换, 再删除掉叶子节点        // 3.1 再找叶子节点的时候, 需要考虑子树高度差        //    因此会在树高比较高的子树中找叶子节点.        int nLeftHeight = getHeight(pFindNode->pLeft);        int nRightHeight = getHeight(pFindNode->pRight);        // 3.2 树中左小右大的关系, 因此, 需要左子树中        //     找最大值, 在右子树中找最小值.            if (nLeftHeight >= nRightHeight) {            // 左子树比较高,需要找最大值            Node*& pNode = getMax(pFindNode->pLeft);            // 将当前被找到的节点和叶子节点的数据域            // 进行调换            int t = pFindNode->nData;            pFindNode->nData = pNode->nData;            pNode->nData = t;            // 删除叶子节点            // 递归删除.            remove(pFindNode->pLeft, pNode->nData);        }        else {            // 右子树比较高,需要找最小值            Node*& pNode = getMin(pFindNode->pRight);            int t = pFindNode->nData;            pFindNode->nData = pNode->nData;            pNode->nData = t;            // 删除叶子节点            // 递归删除.            remove(pFindNode->pRight, pNode->nData);        }    }    /*!     * 函数名 : getHeight     * 功  能 : 求一个树的高度     * 参  数 : Node * pTree     * 返回值 :  int     */    int getHeight(Node* pTree) {        if (pTree == nullptr) {            return 0;        }        // 求出左子树的高度        int nLeftHeight =             getHeight(pTree->pLeft);        // 求出右子树的高度        int nRightHeight =             getHeight(pTree->pRight);        // 取左右子树高度的最大值作为子树的高度        int nHeight = nLeftHeight > nRightHeight ? nLeftHeight : nRightHeight;        // 本节点的高度 = 自身高度 + 子树的高度        return 1 + nHeight;    }        Node*& getMin(Node*& pTree) {        if (pTree == nullptr) {            return pTree;        }        // 二叉树是左小右大的.        // 一个树的最小值就在树的最左边        if (pTree->pLeft == nullptr) {            // 如果本节点的左子节点已经为空了            // 说明了本节点就是树中最左边的节点            // 就返回节点自身.            return pTree;        }        return getMin(pTree->pLeft);    }    Node*& getMax(Node*& pTree) {        if (pTree == nullptr) {            return pTree;        }        // 二叉树是左小右大的.        // 一个树的最大值就在树的最右边        if (pTree->pRight == nullptr) {            // 如果本节点的右子节点已经为空了            // 说明了本节点就是树中最右边的节点            // 就返回节点自身.            return pTree;        }        return getMax(pTree->pRight);    }    // 清空整颗树(后序遍历    void clear(Node*& pTree) {        clear(pTree->pLeft);        clear(pTree->pRight);        delete pTree;    }    // 前序方式遍历树    void printTreeByPreOrder(Node*& pTree) {        if (pTree == nullptr) {            return;        }        printf("%d,", pTree->nData);        printTreeByPreOrder(pTree->pLeft);        printTreeByPreOrder(pTree->pRight);    }    // 中序方式遍历树    void printTreeByInOrder(Node*& pTree) {        if (pTree == nullptr) {            return;        }        printTreeByInOrder(pTree->pLeft);        printf("%d,", pTree->nData);        printTreeByInOrder(pTree->pRight);    }    // 后序方式遍历树    void printTreeByPostOrder(Node*& pTree) {        if (pTree == nullptr) {            return;        }        printTreeByPostOrder(pTree->pLeft);        printTreeByPostOrder(pTree->pRight);        printf("%d,", pTree->nData);    }    void printTree(Node*& pTree, int nWidth, char ch) {        if (pTree == nullptr) {            return;        }        printTree(pTree->pLeft, nWidth + 2, '/');        printf("%*c%d\n", nWidth, ch , pTree->nData);        printTree(pTree->pRight, nWidth + 2, '\\');    }    void sort(Node*& pTree) {        // 1. 判断树的形状:        int nLeftHeight = getHeight(pTree->pLeft);        int nRightHeight = getHeight(pTree->pRight);        if (nLeftHeight - nRightHeight > 1) {            // 1.1 左斜            nLeftHeight = getHeight(pTree->pLeft->pLeft);            nRightHeight = getHeight(pTree->pLeft->pRight);            if (nLeftHeight > nRightHeight) {                // 1.1.1 左单斜            }            else {                // 1.1.2 左歪斜            }        }        else if (nLeftHeight - nRightHeight < -1) {            // 1.2 右斜            nLeftHeight = getHeight(pTree->pRight->pLeft);            nRightHeight = getHeight(pTree->pRight->pRight);            if (nRightHeight > nLeftHeight) {                // 1.2.1 右单斜            }            else {                // 1.2.2 右歪斜            }        }    }public:    void insert(int nData) {        insert(m_pRoot, nData);    }    void remove(int nData) {        remove(m_pRoot, nData);    }    void printTree() {        printTree(m_pRoot, 2, '*');        printf("\n");    }};struct MyStruct {    int nNum = 0;    const char* pStr;};const char*& fun(const char*& p) {    return p;}int main(){    MyStruct stc = {0, "hello" };    const char*& p = fun(stc.pStr);    p = "呵呵";    BSTree tree;    tree.insert(10);    tree.insert(5);    tree.insert(20);    tree.insert(7);    tree.insert(6);    tree.printTree();    tree.remove(10);    tree.printTree();}