zoukankan      html  css  js  c++  java
  • 二叉搜索树的中位数

    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

  • 相关阅读:
    jquery 菜单1
    Notepad++在vs2008下编译运行
    Linux readelf命令的使用
    Linux下truss、strace或ltrace的使用
    (转载)new和malloc的区别
    windows xp 设置回环网卡
    Linux下没有网线的情况下,从主机使用SSH登录虚拟机
    Linux ELF文件学习(1)
    C++子类继承父类
    (转载)wireshark抓包的时候有黄条、蓝条各代表什么意思?
  • 原文地址:https://www.cnblogs.com/simonote/p/3095315.html
Copyright © 2011-2022 走看看