95.png

    1. /*
    2. 编写一个递归算法,在一棵有n个节点的、随机建立起来的二叉排序树上查找第k小的元素,并返回指向该节点的指针,要求算法的平均
    3. 时间复杂度为O(logn)。二叉排序树的每个节点中除了data、lchild、rchild等数据成员外,增加一个count成员,保存以该节点为根的
    4. 子树的节点个数
    5. 分析:
    6. 这里要求时间复杂度为O(ln),我们就不能采用常规的方法了,这里我们需要利用递归的思想,将各种情况罗列清楚
    7. 一、t->lchild 为空
    8. ①如果t->rchild 非空 且 k=1,那么根据二叉排序树的特性 t即为第k小
    9. ②如果t->rchild 非空 且 k!=1,那么第k小的数肯定在右子树中
    10. 二、如果t->lchild 非空
    11. ①如果t->lchild->count ==k-1,那么t即为第k小
    12. ②如果t->lchild->count > k-1,那么第k小在左子树
    13. ③如果t->lchild->count < k-1,那么第k小在右子树,寻找第k-(t->lchild->count +1)小的元素
    14. 这道题的那点就在于对问题的分析,我们很容易就遗漏某些情况,导致代码逻辑有问题,需要注意
    15. */
    16. typedef struct node {
    17. int data;
    18. int count;//子树节点个数
    19. struct node *left, *right;
    20. }Tree;
    21. #define _CRT_SECURE_NO_WARNINGS
    22. #include <stdio.h>
    23. #include <stdlib.h>
    24. Tree *create(Tree *T) {//先序创建一颗排序二叉树
    25. int data;
    26. printf("请输入当前节点值:data=");
    27. scanf("%d", &data);
    28. getchar();
    29. if (data != -1) {
    30. T = (Tree *)malloc(sizeof(Tree));
    31. T->data = data;
    32. T->left = NULL;
    33. T->right = NULL;
    34. T->left = create(T->left);
    35. T->right = create(T->right);
    36. }
    37. return T;
    38. }
    39. int getCount(Tree *T) {//统计每个节点的以它为根的子树上的节点个数
    40. if (!T)return 0;
    41. int lcount, rcount;
    42. lcount = getCount(T->left);
    43. rcount = getCount(T->right);
    44. T->count = lcount + rcount + 1;
    45. return lcount + rcount + 1;
    46. }
    47. Tree *findKth(Tree *T, int k) {
    48. if (k<1 || k>T->count)return NULL;
    49. if (!T->left) {
    50. if (k == 1) return T;
    51. else return findKth(T->right, k - 1);
    52. }
    53. else {
    54. if (T->left->count == k - 1) return T;
    55. if (T->left->count > k - 1) return findKth(T->left, k);
    56. if (T->left->count < k - 1) return findKth(T->right, k - (T->left->count + 1));
    57. }
    58. }
    59. int main() {
    60. Tree *T = (Tree *)malloc(sizeof(Tree));
    61. Tree *p;
    62. int k = 5;
    63. T = create(T);
    64. getCount(T);
    65. p = findKth(T, k);
    66. if (p) {
    67. printf("第 %d 小的节点值为 %d",k,p->data);
    68. }
    69. return 0;
    70. }