复杂度如果是O(n2)则不得分。
分析: 二叉排序树 具有(左子树< 根结点 < 右子树)性质
(1) 二叉排序树的构建过程中总是将新节点插入到叶子结点。
(2)二叉排序树的最小结点是该二叉排序树的最左边的结点。
(3)二叉排序树的最大结点是该二叉排序树的最右边的结点。
(4)查找首个大于给定值的结点(本题就是这个)。
分以下几种情况:
0.比较根结点的值与指定的值,若果根结点的值大于指定的值 则转 1, 否者(otherwise)转2.
1. 当根节点的值大于该值,
(a) 根结点的左子树为空,则根结点为所求。
(b)若左子树不为空,
(i)若左子树的最大结点的值 不大于 指定的值, 则根结点为所求。
(ii)若左子树的最大结点的值 大于 指定的值, 则所求结点在左子树中。将左子树的根节点替换根结点转0.
2. 当根结点值 不大于 指定的值时,
(a) 若根结点的右子树为空,则不存在, 返回NULL。
(b) 若根结点的右子树不为空, 在右子树中找到首个大于指定值得结点,并用这个结点替换根结点,然后转0.
其实,是一个循环不变式!时间复杂度应该小于 O(h*lgn), 因为
h 为树的高度,每一次根节点的比较,使树的规模至少减少一半(若果是平衡二叉排序树的话)。
(5)查找小于指定值的首个结点,方法类似于(4),关键找到那个循环不变式。//右子树的最小结点。
(6)补充, 查找值在指定区间[a, b] 内的所有结点。
实现如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
typedef int item_t;
typedef struct node {
item_t item;
struct node *left;
struct node *right;
} node_t;
typedef node_t * BSTree;
typedef void (*printFuncPtr)(item_t item);
void print(item_t item);
BSTree createBinarySearchTree(BSTree *root, int size, item_t min, item_t max);
void destroyBinarySearchTree(BSTree root);
void postOrderTravel(BSTree root, printFuncPtr print);
void midOrderTravel(BSTree root, printFuncPtr print);
void preOrderTravel(BSTree root, printFuncPtr print);
node_t *minNodeOfBinarySearchTree(BSTree root);
node_t *maxNodeOfBinarySearchTree(BSTree root);
node_t *findNearestBigNode(BSTree root, item_t item);
node_t *findNearestSmallNode(BSTree root, item_t item);
node_t *insertNode(BSTree *root, item_t item);
int main()
{
int i;
int len = 20;
item_t minItem;
item_t maxItem;
item_t midItem;
BSTree root = NULL;
node_t *max_node_ptr;
node_t *min_node_ptr;
node_t *nearest_big_node_ptr;
node_t *nearest_small_node_ptr;
for(i=1; i<len; i++) {
root = createBinarySearchTree(&root, i, 0, i);
printf("root=%p\n", root);
printf("<%d> midOrderTravel: ", i);
midOrderTravel(root, print);
printf("\n");
printf("<%d> preOrderTravel: ", i);
preOrderTravel(root, print);
printf("\n");
printf("<%d> postOrderTravel: ", i);
postOrderTravel(root, print);
printf("\n");
min_node_ptr = minNodeOfBinarySearchTree(root);
max_node_ptr = maxNodeOfBinarySearchTree(root);
if(min_node_ptr) {
minItem = min_node_ptr->item;
printf("The min node of the tree is %p : %d\n", min_node_ptr, minItem);
}
if(max_node_ptr) {
maxItem = max_node_ptr->item;
printf("The max node of the tree is %p : %d\n", max_node_ptr, maxItem);
}
midItem = (maxItem + minItem) >> 1;
nearest_big_node_ptr = findNearestBigNode(root, midItem);
if(nearest_big_node_ptr) {
printf("find the nearest midItem (%d) big node %p: itsItem is %d \n", midItem, nearest_big_node_ptr, nearest_big_node_ptr->item);
}
nearest_small_node_ptr = findNearestSmallNode(root, midItem);
if(nearest_small_node_ptr) {
printf("find the nearest midItem (%d) small node %p: itsItem is %d \n", midItem, nearest_small_node_ptr, nearest_small_node_ptr->item);
}
printf("\n\n");
if(root) {
destroyBinarySearchTree(root);
root = NULL;
}
}
return 0;
}
/*
int getRandom(int min, int max) {
assert(max>=min);
srand((unsigned) time(NULL));
return min + rand()%(max-min);
}
*/
void print(item_t item) {
printf("%d ", item);
}
node_t *insertNode(BSTree *rootPtr, item_t item) {
node_t *tmp = (node_t *) malloc(sizeof(node_t));
assert(tmp!=NULL);
if(!tmp) fprintf(stderr, "error: There is not enough memory to use!!\n");
if(tmp) {
tmp->item = item;
tmp->left = NULL;
tmp->right = NULL;
}
if(!*rootPtr) {
if(tmp) *rootPtr = tmp;
return tmp;
}
BSTree root = *rootPtr;
while(root) {
if(root->item >= item) {
if(root->left == NULL) { //是叶子节点
root->left = tmp;
return tmp;
//break;
}
root = root->left;
}else {
if(root->right == NULL) { //是叶子节点
root->right = tmp;
return tmp;
//break;
}
root = root->right;
}
}
}
BSTree createBinarySearchTree(BSTree *rootPtr, int size, item_t min, item_t max) {
int i;
item_t item;
printf("size= %d \n", size);
srand((unsigned) time(NULL));
for(i=0; i<size; i++) {
item = min + rand()%(max-min);
printf("%d ", item);
insertNode(rootPtr, item);
}
printf("\n");
return *rootPtr;
}
void destroyBinarySearchTree(BSTree root){
if(root) { //后续遍历
destroyBinarySearchTree(root->left);
destroyBinarySearchTree(root->right);
free(root);
}
/*
if(root) { //中序遍历
destroyBinarySearchTree(root->left);
node_t *right = root->right;
free(root);
destroyBinarySearchTree(right);
}
*/
/*
if(root){ //前序遍历
node_t *left = root->left;
node_t *right = root->right;
free(root);
free(left);
free(right);
}
*/
}
void preOrderTravel(BSTree root, printFuncPtr print) {
if(root) {
print(root->item);
preOrderTravel(root->left, print);
preOrderTravel(root->right, print);
}
}
void midOrderTravel(BSTree root, printFuncPtr print) {
if(root) {
midOrderTravel(root->left, print);
print(root->item);
midOrderTravel(root->right, print);
}
}
void postOrderTravel(BSTree root, printFuncPtr print) {
if(root) {
postOrderTravel(root->left, print);
postOrderTravel(root->right, print);
print(root->item);
}
}
node_t *minNodeOfBinarySearchTree(BSTree root) {
if(!root) return NULL;
while(root){
if(root->left == NULL) return root;
root = root->left;
}
}
node_t *maxNodeOfBinarySearchTree(BSTree root) {
if(!root) return NULL;
while(root){
if(root->right == NULL) return root;
root = root->right;
}
}
node_t *findNearestBigNode(BSTree root, item_t item) {
while(root) {
if(root->item > item) {
if(root->left) {
node_t * maxNodePtr = maxNodeOfBinarySearchTree(root->left);
if(maxNodePtr && maxNodePtr->item <= item) return root;
root = root->left;
}else {
return root;
}
}
else {
if(root->right) {
root = root->right;
}else {
return NULL;
}
}
}
}
node_t *findNearestSmallNode(BSTree root, item_t item) {
while(root) {
if(root->item < item) {
if(root->right) {
node_t * minNodePtr = minNodeOfBinarySearchTree(root->right);
if(minNodePtr && minNodePtr->item >= item) return root;
root = root->right;
}else {
return root;
}
}
else {
if(root->left) {
root = root->left;
}else {
return NULL;
}
}
}
}