二叉搜索树的中位数

Given a BST (Binary search Tree) how will you find median in that? 

 

Constraints: 

 

* No extra memory. 

* Function should be reentrant (No static, global variables allowed.) 

* Median for even no of nodes will be the average of 2 middle elements and for odd no of terms will be middle element only. 

* Algorithm should be efficient in terms of complexity. 

 

 

 

中文不需要赘述了,就是二叉搜索树如何高效地找到中位数,不希望申请内存,不要static/global的变量来实现。

 

第一反应就是中序遍历就是排序了,但是如果要计数的话,我们需要一个额外的变量,这样恐怕需要或是静态或者全局变量了,故不可以用。但是我们其他很多次都碰到了那样类似的问题,如何把一个二叉树原地转化成双向链表,那时候还有点觉得题目没意思,没啥用处。但是在这里,作用得以体现。假如有形如

 

 

 

                                            10

                                          /    /

                                        6       14

                                      /  /     /  /

                                    4     8  12    16

 

的二叉树转化成了4=6=8=10=12=14=16这样一个双链表,那后面的问题就变成了如何在4=6=8=10=12=14=16里面找到中间节点了,这对于我们习惯了2个快慢指针追赶的小朋友来说不算问题了。

 

下面就是写的一个实现:

 

[cpp] view plaincopy

#include <iostream>  

typedef struct bstNode  

{  

      

    int      data;  

    bstNode* pLeft;  

    bstNode* pRight;  

      

    bstNode()  

    {  

        data = 0;  

        pLeft = NULL;  

        pRight = NULL;  

    }  

}bstNode;  

void bst2dll (bstNode* pNode, bstNode*& pTail )  

{  

    // in-order traverse  

    if (pNode == NULL) return ;  

      

    if (pNode->pLeft) bst2dll(pNode->pLeft,pTail);  

          

    bstNode* pCurrent = pNode;  

    pCurrent->pLeft = pTail;  

    if (pTail)  

        pTail->pRight = pCurrent;  

    pTail = pCurrent;  

    if(pNode->pRight) bst2dll(pNode->pRight, pTail);  

}  

// parameter is the original root  

// return the new double linked list head   

int  medianInBST ( bstNode* pRoot )  

{  

    bstNode* pTail = NULL;  

    bst2dll(pRoot,pTail);  

      

    // dummy handling here  

    if (pTail == NULL) return -1;  

    bstNode* pFast = pTail;  

    bstNode* pSlow = pTail;  

      

    while (pFast&&pSlow)  

    {  

        if (pFast->pLeft==NULL)   

            return pSlow->data;  

        else if (pFast->pLeft != NULL && pFast->pLeft->pLeft == NULL)  

            return (pSlow->data + pSlow->pLeft->data)>>1;  

        else  

        {  

            pFast = pFast->pLeft;  

            pFast = pFast->pLeft;  

            pSlow = pSlow->pLeft;  

        }  

    }  

}  

// test case  

/* 

             10 

            /  / 

           6   14 

          / /  / /   

         4   8 12 16 

*/  

bstNode* buildupTree()  

{  

// level 1  

    bstNode* pRoot = new bstNode;  

    pRoot->data = 10;  

//level2  

    bstNode* pNewL = new bstNode;  

    pNewL->data = 6;  

    bstNode* pNewR = new bstNode;  

    pNewR->data = 14;  

//level3      

    bstNode* pNewLL = new bstNode;  

    pNewLL->data = 4;  

    bstNode* pNewLR = new bstNode;  

    pNewLR->data = 8;  

    bstNode* pNewRL = new bstNode;  

    pNewRL->data = 12;  

    bstNode* pNewRR = new bstNode;  

    pNewRR->data = 16;  

      

    pRoot->pLeft = pNewL;  

    pRoot->pRight = pNewR;  

    pNewL->pLeft = pNewLL;  

    pNewL->pRight = pNewLR;  

    pNewR->pLeft = pNewRL;  

    pNewR->pRight = pNewRR;  

      

    return pRoot;  

}  

void main()  

{  

    bstNode* pRoot = buildupTree();  

    std::cout<<medianInBST(pRoot)<<std::endl;  

    system("pause");  

}  

 

说实话这样的题目还是比较喜欢的,考到了很多的概念和想法,

 

a.中序遍历

 

b.BST转化成DLL

 

c.寻找链表的中间节点

 

如果任何一个问题割裂开了问, 都是比较容易解决的。困难就在于如何用已知的办法组合地解决未知的问题,发人深思,余是以记之。

 

转载:http://blog.csdn.net/hhygcy/article/details/4654305

posted @ 2013-05-23 18:00  simon1024  阅读(1313)  评论(0编辑  收藏  举报