• 北邮22信通:二叉树显示路径的两种方法 递归函数保存现场返回现场的实例


    北邮22信通一枚~                           

    跟随课程进度每周更新数据结构与算法的代码和文章 

    持续关注作者  解锁更多邮苑信通专属代码~

    获取更多文章  请访问专栏~

    北邮22信通_青山如墨雨如画的博客-CSDN博客

    目录

    一.讲解

    1.递归详解:是否能够找到路径并将找到的可行路径存储起来的实现函数

    2.打印路径的函数

     3.另一种存储方式

    二.完整代码:

    2.1使用STL栈实现:

    2.2使用模板类定义的栈实现:

    2.3运行效果:


     

    一.讲解

    要想实现二叉树的路径显示,我们要按照先后顺序做这样几件事:

    1.判断是否能够找到路径;

    2.如果能找到路径,则将路径存储起来,如果不能找到路径,则返回查询失败的信息;

    3.将路径按照一定的方法打印出来;

    1.递归详解:是否能够找到路径并将找到的可行路径存储起来的实现函数

    1. template<class temp>
    2. bool bintree::stl_search_path(temp target, binnode*& r,
    3. stack >& stk)
    4. {
    5. if (r == NULL)
    6. return false;
    7. stk.push(*r);
    8. if (r->data == target)
    9. return true;
    10. else if (stl_search_path(target, r->leftchild, stk))
    11. return true;
    12. else if (stl_search_path(target, r->rightchild, stk))
    13. return true;
    14. stk.pop();
    15. return false;
    16. }

             首先我们向这个函数中传入3个参数,分别是待查找的目标,二叉树的根节点,一个空栈(用来存储路径);实现的具体过程运用了递归思想:对整个查找过程中的某次查找如果父节点数据域就是要查找的目标,返回真值;如果沿着他的左孩子找下去能找到目标,返回真值,如果沿着他的右孩子找下去能找到目标,返回真值。如果父节点不是目标并且沿着左孩子右孩子都找不到目标的话,弹出父节点返回假值。

    这里用例子重新讲解递归函数保存现场返回现场的运行过程:

    如上图,我们要查找到结点6的路径:

    按照函数编写顺序:

    1首先入栈,判断1不是6(函数第5、6行),继续执行;

    1. template<class temp>
    2. bool bintree::stl_search_path(temp target, binnode*& r,
    3. stack >& stk)
    4. {
    5. if (r == NULL)
    6. return false;
    7. stk.push(*r);
    8. if (r->data == target)//现在是1,不是9
    9. return true;//执行完毕,继续向下执行;
    10. }

    执行到第7行,需要判断沿着1的左孩子2能不能找到合适路径,保存现场;

    1. template<class temp>
    2. bool bintree::stl_search_path(temp target, binnode*& r,
    3. stack >& stk)
    4. {
    5. if (r == NULL)
    6. return false;
    7. stk.push(*r);
    8. if (r->data == target)
    9. return true;
    10. else if (stl_search_path(target, r->leftchild, stk))
    11. return true;
    12. /*
    13. 执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)
    14. 是否为真值;
    15. 函数保存现场不继续向下执行,将r->leftchild==2作为参数替代r==1,重新开始执行函数;
    16. */
    17. }

    重新从第一行开始执行函数,2入栈,2不是6,向下执行;

    1. template<class temp>
    2. bool bintree::stl_search_path(temp target, binnode*& r,
    3. stack >& stk)
    4. {
    5. if (r == NULL)
    6. return false;
    7. stk.push(*r);
    8. if (r->data == target)
    9. return true;//r==2不是9,继续向下执行;
    10. }

    执行到第7行,需要判断沿着2的左孩子4能不能找到合适路径,保存现场;

    1. template<class temp>
    2. bool bintree::stl_search_path(temp target, binnode*& r,
    3. stack >& stk)
    4. {
    5. if (r == NULL)
    6. return false;
    7. stk.push(*r);
    8. if (r->data == target)
    9. return true;
    10. else if (stl_search_path(target, r->leftchild, stk))
    11. return true;
    12. /*
    13. 执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)
    14. 是否为真值;
    15. 函数保存现场不继续向下执行,将r->leftchild->leftchild==4作为参数
    16. 替代r->leftchild==2,重新开始执行函数;
    17. */
    18. }

    重新从第一行开始执行函数,4入栈,4不是6,向下执行;

    1. template<class temp>
    2. bool bintree::stl_search_path(temp target, binnode*& r,
    3. stack >& stk)
    4. {
    5. if (r == NULL)
    6. return false;
    7. stk.push(*r);
    8. if (r->data == target)
    9. return true;
    10. else if (stl_search_path(target, r->leftchild, stk))
    11. return true;
    12. /*
    13. 执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)
    14. 是否为真值;
    15. 函数保存现场不继续向下执行,
    16. 将r->leftchild->leftchild->leftchild==NULL作为参数
    17. 替代r->leftchild->leftchild==4,重新开始执行函数;
    18. */
    19. }

    发现4的左孩子是空,返回假值;

    返回上一级现场,执行函数第8、9行,需要判断沿着4的右孩子能不能找到合适路径,保存现场;

    1. template<class temp>
    2. bool bintree::stl_search_path(temp target, binnode*& r,
    3. stack >& stk)
    4. {
    5. if (r == NULL)
    6. return false;
    7. stk.push(*r);
    8. if (r->data == target)
    9. return true;
    10. else if (stl_search_path(target, r->leftchild, stk))
    11. return true;
    12. else if (stl_search_path(target, r->rightchild, stk))
    13. return true;
    14. /*
    15. 执行到这一步,需要重新判断stl_search_path(target, r->leftchild, stk)
    16. 是否为真值;
    17. 函数保存现场不继续向下执行,
    18. 将r->leftchild->leftchild->rightchild==NULL作为参数
    19. 替代r->leftchild->leftchild==4,重新开始执行函数;
    20. */
    21. }

    右孩子为空;

    返回上一级现场,判断沿着2的右孩子5能不能找到可行的路径,保存现场,以此类推……

    示意图如下:

    2.打印路径的函数

    1. template<class temp>
    2. void bintree::stl_node_root_path(temp target)
    3. {
    4. stack>stk;
    5. stl_search_path(target, this->root, stk);
    6. if (stk.empty())
    7. cout << target << "未能找到目标" << endl;
    8. else
    9. {
    10. cout << target << "结点到根节点的路径为:" << endl;
    11. binnodeout;
    12. while (!stk.empty())
    13. {
    14. out = stk.top();
    15. if (stk.size() == 1)
    16. cout << out.data;
    17. else
    18. cout << out.data << "->";
    19. stk.pop();
    20. }
    21. cout << endl;
    22. }
    23. }

     对于给定的二叉树,首先调用上面讲解过的函数,如果有可行路径就将可行路径通过函数存储到本函数的栈空间中,然后通过控制条件输出,最终可以实现打印的效果。

     3.另一种存储方式

    使用模板类定义的栈存储也未尝不可。

    代码如下:

    1. template<class temp>
    2. void bintree::linkstack_node_root_path(temp target)
    3. {
    4. linkstack>stk;
    5. linkstack_search_path(target, this->root, stk);
    6. if (stk.empty())
    7. cout << target << "未能找到目标" << endl;
    8. else
    9. {
    10. cout << target << "结点到根节点的路径为:" << endl;
    11. binnodeout;
    12. while (!stk.empty())
    13. {
    14. out = stk.gettop();
    15. if (stk.getsize() == 1)
    16. cout << out.data;
    17. else
    18. cout << out.data << "->";
    19. stk.pop();
    20. }
    21. cout << endl;
    22. }
    23. }
    1. template<class temp>
    2. bool bintree::linkstack_search_path(temp target, binnode*& r, linkstack>& stk)
    3. {
    4. if (r == NULL)
    5. return false;
    6. stk.push(*r);
    7. if (r->data == target)
    8. return true;
    9. else if (linkstack_search_path(target, r->leftchild, stk))
    10. return true;
    11. else if (linkstack_search_path(target, r->rightchild, stk))
    12. return true;
    13. stk.pop();
    14. return false;
    15. }

    二.完整代码:

    2.1使用STL栈实现:

    1. #include
    2. #include
    3. using namespace std;
    4. class student
    5. {
    6. private:
    7. int ID;
    8. string name;
    9. public:
    10. int existence;
    11. student()
    12. {
    13. this->ID = 0;
    14. this->name = "unknown name";
    15. this->existence = 0;
    16. }
    17. student(int ID, string name)
    18. {
    19. this->ID = ID;
    20. this->name = name;
    21. this->existence = 1;
    22. }
    23. bool operator == (student& s)
    24. {
    25. return ((this->ID == s.ID) && (this->name == s.name)) ? true : false;
    26. }
    27. friend ostream& operator<<(ostream& output, student& s)
    28. {
    29. output << "\"" << s.ID << " " << s.name << "\"";
    30. return output;
    31. }
    32. };
    33. template<class temp>
    34. struct binnode
    35. {
    36. temp data;
    37. binnode* leftchild;
    38. binnode* rightchild;
    39. };
    40. template<class temp>
    41. class bintree
    42. {
    43. private:
    44. void create(binnode*& r, temp data[], int i, int n);
    45. void release(binnode* r);
    46. public:
    47. binnode* root;
    48. bintree(temp data[], int n);
    49. void stl_node_root_path(temp target);
    50. bool stl_search_path(temp target, binnode*& r, stack >& stk);
    51. ~bintree();
    52. };
    53. template<class temp>
    54. void bintree::create(binnode*& r, temp data[], int i, int n)
    55. {
    56. if (i <= n && data[i - 1].existence != 0)
    57. {
    58. r = new binnode;
    59. r->data = data[i - 1];
    60. r->leftchild = NULL;
    61. r->rightchild = NULL;
    62. create(r->leftchild, data, 2 * i, n);
    63. create(r->rightchild, data, 2 * i + 1, n);
    64. }
    65. }
    66. template<class temp>
    67. bintree::bintree(temp data[], int n)
    68. {
    69. create(this->root, data, 1, n);
    70. }
    71. template<class temp>
    72. void bintree::release(binnode* r)
    73. {
    74. if (r != NULL)
    75. {
    76. release(r->leftchild);
    77. release(r->rightchild);
    78. delete r;
    79. }
    80. }
    81. template<class temp>
    82. bintree::~bintree()
    83. {
    84. release(this->root);
    85. }
    86. template<class temp>
    87. void bintree::stl_node_root_path(temp target)
    88. {
    89. stack>stk;
    90. stl_search_path(target, this->root, stk);
    91. if (stk.empty())
    92. cout << target << "未能找到目标" << endl;
    93. else
    94. {
    95. cout << target << "结点到根节点的路径为:" << endl;
    96. binnodeout;
    97. while (!stk.empty())
    98. {
    99. out = stk.top();
    100. if (stk.size() == 1)
    101. cout << out.data;
    102. else
    103. cout << out.data << "->";
    104. stk.pop();
    105. }
    106. cout << endl;
    107. }
    108. }
    109. template<class temp>
    110. bool bintree::stl_search_path(temp target, binnode*& r, stack >& stk)
    111. {
    112. if (r == NULL)
    113. return false;
    114. stk.push(*r);
    115. if (r->data == target)
    116. return true;
    117. else if (stl_search_path(target, r->leftchild, stk))
    118. return true;
    119. else if (stl_search_path(target, r->rightchild, stk))
    120. return true;
    121. stk.pop();
    122. return false;
    123. }
    124. int main()
    125. {
    126. system("color 0A");
    127. student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
    128. bintreetree(stu, 5);
    129. student stu1(1, "zhang"), stu2(5, "liu"), stu3(6, "cao");
    130. tree.stl_node_root_path(stu1);
    131. tree.stl_node_root_path(stu2);
    132. tree.stl_node_root_path(stu3);
    133. return 0;
    134. }

    2.2使用模板类定义的栈实现:

    1. #include
    2. using namespace std;
    3. class student
    4. {
    5. private:
    6. int ID;
    7. string name;
    8. public:
    9. int existence;
    10. student()
    11. {
    12. this->ID = 0;
    13. this->name = "unknown name";
    14. this->existence = 0;
    15. }
    16. student(int ID, string name)
    17. {
    18. this->ID = ID;
    19. this->name = name;
    20. this->existence = 1;
    21. }
    22. bool operator == (student& s)
    23. {
    24. return ((this->ID == s.ID) && (this->name == s.name)) ? true : false;
    25. }
    26. friend ostream& operator<<(ostream& output, student& s)
    27. {
    28. output << "\"" << s.ID << " " << s.name << "\"";
    29. return output;
    30. }
    31. };
    32. //二叉树声明部分
    33. template<class temp>
    34. struct binnode;
    35. //栈
    36. template <class temp>
    37. struct node
    38. {
    39. temp data;
    40. node* next;
    41. };
    42. template <class temp>
    43. class linkstack
    44. {
    45. public:
    46. binnode* r;
    47. int tag;
    48. linkstack() { top = NULL; }
    49. ~linkstack();
    50. void push(temp x);
    51. temp pop();
    52. temp gettop();
    53. int getsize();
    54. bool empty()
    55. {
    56. return top == NULL ? true : false;
    57. }
    58. private:
    59. node* top;
    60. };
    61. template <class temp>
    62. void linkstack::push(temp x)
    63. {
    64. node* p = new node;
    65. p->data = x;
    66. p->next = this->top;
    67. this->top = p;
    68. }
    69. template<class temp>
    70. temp linkstack::pop()
    71. {
    72. if (empty())throw "下溢";
    73. temp x = this->top->data;
    74. node* p = this->top;
    75. this->top = this->top->next;
    76. delete p;
    77. return x;
    78. }
    79. template<class temp>
    80. linkstack::~linkstack()
    81. {
    82. while (this->top != NULL)
    83. {
    84. node* p = this->top;
    85. this->top = this->top->next;
    86. delete p;
    87. }
    88. }
    89. template<class temp>
    90. temp linkstack::gettop()
    91. {
    92. if (empty())throw"下溢";
    93. return this->top->data;
    94. }
    95. template<class temp>
    96. int linkstack::getsize()
    97. {
    98. int num = 0;
    99. node* p = this->top;
    100. while (p != NULL)
    101. {
    102. num++;
    103. p = p->next;
    104. }
    105. return num;
    106. }
    107. template<class temp>
    108. struct binnode
    109. {
    110. temp data;
    111. binnode* leftchild;
    112. binnode* rightchild;
    113. };
    114. template<class temp>
    115. class bintree
    116. {
    117. private:
    118. void create(binnode*& r, temp data[], int i, int n);
    119. void release(binnode* r);
    120. public:
    121. binnode* root;
    122. bintree(temp data[], int n);
    123. void linkstack_node_root_path(temp target);
    124. bool linkstack_search_path(temp target, binnode*& r, linkstack>& stk);
    125. ~bintree();
    126. };
    127. template<class temp>
    128. void bintree::create(binnode*& r, temp data[], int i, int n)
    129. {
    130. if (i <= n && data[i - 1].existence != 0)
    131. {
    132. r = new binnode;
    133. r->data = data[i - 1];
    134. r->leftchild = NULL;
    135. r->rightchild = NULL;
    136. create(r->leftchild, data, 2 * i, n);
    137. create(r->rightchild, data, 2 * i + 1, n);
    138. }
    139. }
    140. template<class temp>
    141. bintree::bintree(temp data[], int n)
    142. {
    143. create(this->root, data, 1, n);
    144. }
    145. template<class temp>
    146. void bintree::release(binnode* r)
    147. {
    148. if (r != NULL)
    149. {
    150. release(r->leftchild);
    151. release(r->rightchild);
    152. delete r;
    153. }
    154. }
    155. template<class temp>
    156. bintree::~bintree()
    157. {
    158. release(this->root);
    159. }
    160. template<class temp>
    161. void bintree::linkstack_node_root_path(temp target)
    162. {
    163. linkstack>stk;
    164. linkstack_search_path(target, this->root, stk);
    165. if (stk.empty())
    166. cout << target << "未能找到目标" << endl;
    167. else
    168. {
    169. cout << target << "结点到根节点的路径为:" << endl;
    170. binnodeout;
    171. while (!stk.empty())
    172. {
    173. out = stk.gettop();
    174. if (stk.getsize() == 1)
    175. cout << out.data;
    176. else
    177. cout << out.data << "->";
    178. stk.pop();
    179. }
    180. cout << endl;
    181. }
    182. }
    183. template<class temp>
    184. bool bintree::linkstack_search_path(temp target, binnode*& r, linkstack>& stk)
    185. {
    186. if (r == NULL)
    187. return false;
    188. stk.push(*r);
    189. if (r->data == target)
    190. return true;
    191. else if (linkstack_search_path(target, r->leftchild, stk))
    192. return true;
    193. else if (linkstack_search_path(target, r->rightchild, stk))
    194. return true;
    195. stk.pop();
    196. return false;
    197. }
    198. int main()
    199. {
    200. system("color 0A");
    201. student stu[5] = { {1,"zhang"},{2,"wang"},{3,"li"},{4,"zhao"},{5,"liu"} };
    202. bintreetree(stu, 5);
    203. student stu1(1, "zhang"), stu2(5, "liu"), stu3(6, "cao");
    204. tree.linkstack_node_root_path(stu1);
    205. tree.linkstack_node_root_path(stu2);
    206. tree.linkstack_node_root_path(stu3);
    207. return 0;
    208. }

    2.3运行效果:

  • 相关阅读:
    QT发送Get请求并返回内容
    基于树莓派的智能门禁及3D外壳打印设计
    linux系统向github传文件
    在条码软件中如何制作ISBT-128条码
    【Harmony OS】【ArkUI】ets开发 简易视频播放器
    为什么您的公司应该进行脉动调查以及如何正确进行
    高级IO—多路转接
    View的事件分发机制
    金蝶云星空与旺店通·企业奇门对接集成盘盈单查询打通创建盘点单
    JAVA家教管理系统毕业设计 开题报告
  • 原文地址:https://blog.csdn.net/bc202205/article/details/130842838