一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。 复杂度如果是O(n2)则不得分。

一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。

复杂度如果是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;
            }
        }

    }

}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值