函数递归调用图
二叉树
// 二叉树.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();}