
/* 编写一个递归算法,在一棵有n个节点的、随机建立起来的二叉排序树上查找第k小的元素,并返回指向该节点的指针,要求算法的平均 时间复杂度为O(logn)。二叉排序树的每个节点中除了data、lchild、rchild等数据成员外,增加一个count成员,保存以该节点为根的 子树的节点个数 分析: 这里要求时间复杂度为O(ln),我们就不能采用常规的方法了,这里我们需要利用递归的思想,将各种情况罗列清楚 一、t->lchild 为空 ①如果t->rchild 非空 且 k=1,那么根据二叉排序树的特性 t即为第k小 ②如果t->rchild 非空 且 k!=1,那么第k小的数肯定在右子树中 二、如果t->lchild 非空 ①如果t->lchild->count ==k-1,那么t即为第k小 ②如果t->lchild->count > k-1,那么第k小在左子树 ③如果t->lchild->count < k-1,那么第k小在右子树,寻找第k-(t->lchild->count +1)小的元素 这道题的那点就在于对问题的分析,我们很容易就遗漏某些情况,导致代码逻辑有问题,需要注意*/typedef struct node { int data; int count;//子树节点个数 struct node *left, *right;}Tree;#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>Tree *create(Tree *T) {//先序创建一颗排序二叉树 int data; printf("请输入当前节点值:data="); scanf("%d", &data); getchar(); if (data != -1) { T = (Tree *)malloc(sizeof(Tree)); T->data = data; T->left = NULL; T->right = NULL; T->left = create(T->left); T->right = create(T->right); } return T;}int getCount(Tree *T) {//统计每个节点的以它为根的子树上的节点个数 if (!T)return 0; int lcount, rcount; lcount = getCount(T->left); rcount = getCount(T->right); T->count = lcount + rcount + 1; return lcount + rcount + 1;}Tree *findKth(Tree *T, int k) { if (k<1 || k>T->count)return NULL; if (!T->left) { if (k == 1) return T; else return findKth(T->right, k - 1); } else { if (T->left->count == k - 1) return T; if (T->left->count > k - 1) return findKth(T->left, k); if (T->left->count < k - 1) return findKth(T->right, k - (T->left->count + 1)); }}int main() { Tree *T = (Tree *)malloc(sizeof(Tree)); Tree *p; int k = 5; T = create(T); getCount(T); p = findKth(T, k); if (p) { printf("第 %d 小的节点值为 %d",k,p->data); } return 0;}