剑指offer之二叉搜索树的第K个节点

举报
chenyu 发表于 2021/07/26 23:54:26 2021/07/26
【摘要】 1 问题 给定一颗二叉搜索树,请找出其中的第k小的结点。例如, 5  3  7  2  4  6  8 中,按结点数值大小顺序第三个结点的值为4。       2 分析 二叉树定义:二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵...

1 问题

给定一颗二叉搜索树,请找出其中的第k小的结点。例如, 5  3  7  2  4  6  8 中,按结点数值大小顺序第三个结点的值为4。

 

 

 

2 分析

二叉树定义:二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树

具体分析:按照定义,我们不难知道二叉查找树如果按照数的中序遍历,我们可以得到单调递增的排列数,我们需要找到第K个节点,也就是中序遍历树的第K个节点。

我们可以通过递归中序遍历求解答,也可以通过通过栈来实现树的中序遍历

 

 

3 代码实现


  
  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <stack>
  4. using namespace std;
  5. typedef struct Tree
  6. {
  7. int value;
  8. struct Tree* left;
  9. struct Tree* right;
  10. } Tree;
  11. Tree* getNode(Tree* node, int k)
  12. {
  13. if (k <= 0)
  14. {
  15. std::cout << "输入的k值不合法" << std::endl;
  16. return NULL;
  17. }
  18. int count;
  19. if (node == NULL)
  20. return NULL;
  21. getNode(node->left, k);
  22. //std::cout << "value is " << node->value <<std::endl;
  23. count++;
  24. if (count == k)
  25. {
  26. return node;
  27. }
  28. getNode(node->right, k);
  29. return node;
  30. }
  31. Tree* getNode1(Tree* node, int k)
  32. {
  33. if (k <= 0)
  34. {
  35. std::cout << "输入的k值不合法" << std::endl;
  36. return NULL;
  37. }
  38. if (node == NULL)
  39. return NULL;
  40. std::stack<Tree *> stack;
  41. Tree *p = node;
  42. int count = 0;
  43. while (p != NULL || !stack.empty())
  44. {
  45. if (p != NULL)
  46. {
  47. stack.push(p);
  48. p = p->left;
  49. }
  50. else
  51. {
  52. Tree *value = stack.top();
  53. //std::cout << "value is " << value->value << std::endl;
  54. count++;
  55. //这里需要pop函数弹出来,不然永远都是二叉树的最左下角的值
  56. stack.pop();
  57. if (k == count)
  58. {
  59. return value;
  60. }
  61. p = value->right;
  62. }
  63. }
  64. return NULL;
  65. }
  66. int main() {
  67. /***
  68. 4
  69. 2 6
  70. 1 3 5 7
  71. **/
  72. Tree *node1 , *node2 , *node3, *node4, *node5, *node6, *node7;
  73. node1 = (Tree *)malloc(sizeof(Tree));
  74. node2 = (Tree *)malloc(sizeof(Tree));
  75. node3 = (Tree *)malloc(sizeof(Tree));
  76. node4 = (Tree *)malloc(sizeof(Tree));
  77. node5 = (Tree *)malloc(sizeof(Tree));
  78. node6 = (Tree *)malloc(sizeof(Tree));
  79. node7 = (Tree *)malloc(sizeof(Tree));
  80. node1->value = 4;
  81. node2->value = 2;
  82. node3->value = 6;
  83. node4->value = 1;
  84. node5->value = 3;
  85. node6->value = 5;
  86. node7->value = 7;
  87. node1->left = node2;
  88. node1->right = node3;
  89. node2->left = node4;
  90. node2->right = node5;
  91. node3->left = node6;
  92. node3->right = node7;
  93. node4->left = NULL;
  94. node4->right = NULL;
  95. node5->left = NULL;
  96. node5->right = NULL;
  97. node6->left = NULL;
  98. node6->right = NULL;
  99. node7->left = NULL;
  100. node7->right = NULL;
  101. Tree *result = getNode(node1, 4);
  102. if (result != NULL)
  103. {
  104. std::cout << "result is " << result->value << std::endl;
  105. }
  106. Tree *result1 = getNode1(node1, 4);
  107. if (result1 != NULL)
  108. {
  109. std::cout << "result1 is " << result1->value << std::endl;
  110. }
  111. return 0;
  112. }

 

 

 

 

 

4 运行结果


  
  1. result is 4
  2. result1 is 4

 

 

 

 

5 总结

我们用栈(stack)进行中序遍历的时候,我们不应该一开始就把树的顶部节点压入栈,这个时候基本上后面再在while循环里面做top操作基本上无解,然后我们既然是要执行左 中 右效果,我们需要单独定义一个遍历保存第一个节点,然后依次压入左孩子节点,然后如果是空就不压进去,而要执行获取顶部元素,这个就是我们需要的值,然后还有把这个元素进行弹出来(pop)操作,然后把这个值的右孩子节点压入栈,这样就可以保证是左 中 右打印值的效果。

文章来源: chenyu.blog.csdn.net,作者:chen.yu,版权归原作者所有,如需转载,请联系作者。

原文链接:chenyu.blog.csdn.net/article/details/102473256

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。