• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Jiang's C++ Space

            創作,也是一種學習的過程。

               :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::

            十三、左偏樹(Leftist Tree)

            樹這個數據結構內容真的很多,上一節所講的二叉堆,其實就是一顆二叉樹,這次講的左偏樹(又叫“左翼堆”),也是樹。

            二叉堆是個很不錯的數據結構,因為它非常便于理解,而且僅僅用了一個數組,不會造成額外空間的浪費,但它有個缺點,那就是很難合并兩個二叉堆,對于“合并”,“拆分”這種操作,我覺得最方面的還是依靠指針,改變一下指針的值就可以實現,要是涉及到元素的移動,那就復雜一些了。

            左偏樹跟二叉堆比起來,就是一棵真正意義上的樹了,具有左右指針,所以空間開銷上稍微大一點,但卻帶來了便于合并的便利。BTW:寫了很多很多的程序之后,我發覺“空間換時間”始終是個應該考慮的編程方法。:)

            左偏左偏,給人感覺就是左子樹的比重比較大了,事實上也差不多,可以這么理解:左邊分量重,那一直往右,就一定能最快地找到可以插入元素的節點了。所以可以這樣下個定義:左偏樹就是對其任意子樹而言,往右到插入點的距離(下面簡稱為“距離”)始終小于等于往左到插入點的距離,當然了,和二叉堆一樣,父節點的值要小于左右子節點的值。

            如果節點本身不滿,可插入,那距離就為0,再把空節點的距離記為-1,這樣我們就得出:父節點的距離 = 右子節點距離 + 1,因為右子節點的距離始終是小于等于左子節點距離的。我把距離的值用藍色字體標在上圖中了。

            左偏樹并一定平衡,甚至它可以很不平衡,因為它其實也不需要平衡,它只需要像二叉堆那樣的功能,再加上合并方便,現在來看左偏樹的合并算法,如圖:


            這種算法其實很適合用遞歸來做,但我還是用了一個循環,其實也差不多。對于左偏樹來說,這個合并操作是最重要最基本的了。為什么?你看哦:Enqueue,我能不能看作是這個左偏樹的root和一個單節點樹的合并?而Dequeue,我能不能看作是把root節點取出來,然后合并root的左右子樹?事實上就是這樣的,我提供的代碼就是這樣干的。

            Conclusion:左偏樹比同二叉堆的優點就是方便合并,缺點是編程復雜度略高(也高不去哪),占用空間稍大(其實也大不去哪)。附上代碼,老樣子了,單個文件,直接調試的代碼,零依賴零配置,一看就懂,代碼雖然不算完美,但作為演示和學習,是足夠了。

            #include <stdio.h>

            // TreeNode
            //////////////////////////////////////////////////////////////////////////
            struct TreeNode 
            {
                TreeNode(
            int iVal)
                {
                    m_iData 
            = iVal;
                    m_iDistance 
            = 0;
                    m_pLeft 
            = 0;
                    m_pRight 
            = 0;
                }

                
            ~TreeNode()
                {

                }

                
            void SwapLeftRight()
                {
                    TreeNode 
            *pTmp = m_pLeft;
                    m_pLeft 
            = m_pRight;
                    m_pRight 
            = pTmp;
                }

                
            void UpdateDistance()
                {
                    m_iDistance 
            = GetRightDistance()+1;
                }

                
            int GetLeftDistance()
                {
                    
            return m_pLeft!=0?m_pLeft->m_iDistance:-1;
                }

                
            int GetRightDistance()
                {
                    
            return m_pRight!=0?m_pRight->m_iDistance:-1;
                }

                
            int m_iData;
                
            int m_iDistance;
                TreeNode
            * m_pLeft;
                TreeNode
            * m_pRight;
            };

            // Stack
            //////////////////////////////////////////////////////////////////////////
            class Stack
            {
            public:
                Stack(
            int iAmount = 10);
                
            ~Stack();
                
                
            //return 1 means succeeded, 0 means failed.
                int Pop(TreeNode* & val);
                
            int Push(TreeNode* val);
                
            int Top(TreeNode* & val);
                
                
            //iterator
                int GetTop(TreeNode* &val);
                
            int GetNext(TreeNode* &val);
            private:
                TreeNode
            ** m_pData;
                
            int m_iCount;
                
            int m_iAmount;
                
                
            //iterator
                int m_iCurr;
            };

            Stack::Stack(
            int iAmount)
            {
                m_pData 
            = new TreeNode*[iAmount];
                m_iCount 
            = 0;
                m_iAmount 
            = iAmount;
                m_iCurr 
            = 0;
            }

            Stack::
            ~Stack()
            {
                delete m_pData;
            }

            int Stack::Pop(TreeNode* & val)
            {
                
            if(m_iCount>0)
                {
                    
            --m_iCount;
                    val 
            = m_pData[m_iCount];
                    
            return 1;
                }
                
            return 0;
            }

            int Stack::Push(TreeNode* val)
            {
                
            if(m_iCount<m_iAmount)
                {
                    m_pData[m_iCount] 
            = val;
                    
            ++m_iCount;
                    
            return 1;
                }
                
            return 0;
            }

            int Stack::Top(TreeNode* & val)
            {
                
            if(m_iCount>0 && m_iCount<=m_iAmount)
                {
                    val 
            = m_pData[m_iCount-1];
                    
            return 1;
                }
                
            return 0;
            }

            int Stack::GetTop(TreeNode* &val)
            {
                
            if(m_iCount>0 && m_iCount<=m_iAmount)
                {
                    val 
            = m_pData[m_iCount-1];
                    m_iCurr 
            = m_iCount - 1;
                    
            return 1;
                }
                
            return 0;
            }

            int Stack::GetNext(TreeNode* &val)
            {
                
            if((m_iCurr-1)<(m_iCount-1&& (m_iCurr-1)>=0)
                {
                    
            --m_iCurr;
                    val 
            = m_pData[m_iCurr];
                    
            return 1;
                }
                
            return 0;
            }

            // LeftistTree
            //////////////////////////////////////////////////////////////////////////
            class LeftistTree
            {
            public:
                LeftistTree();
                
            ~LeftistTree();

                
            //return 0 means failed.
                int Dequeue(int& iVal);
                
            int Enqueue(int iVal);

                
            //returns the merged root.
                TreeNode* Merge(TreeNode *pT1, TreeNode *pT2);

                TreeNode
            * GetRoot();
            #ifdef _DEBUG
                
            void Print(TreeNode* pNode);
            #endif

            protected:
                TreeNode 
            *m_pRoot;
            };

            LeftistTree::LeftistTree()
            {
                m_pRoot 
            = NULL;
            }

            LeftistTree::
            ~LeftistTree()
            {
                Stack st(
            40); //2^40 must be enough.
                
                
            //Postorder traverse the tree to release all nodes.
                TreeNode *pNode = m_pRoot;
                TreeNode 
            *pTemp;
                
            if(pNode==0)
                    
            return;
                
                
            while (1)
                {
                    
            if(pNode->m_pLeft!=0)
                    {
                        st.Push(pNode);
                        pTemp 
            = pNode;
                        pNode 
            = pNode->m_pLeft;
                        pTemp
            ->m_pLeft = 0;
                        
            continue;
                    }
                    
                    
            if(pNode->m_pRight!=0)
                    {
                        st.Push(pNode);
                        pTemp 
            = pNode;
                        pNode 
            = pNode->m_pRight;
                        pTemp
            ->m_pRight = 0;
                        
            continue;
                    }
                    
                    delete pNode;
                    
                    
            if(0==st.Pop(pNode))
                        
            break;
                }
            }

            int LeftistTree::Dequeue(int& iVal)
            {
                
            if(m_pRoot==0)
                    
            return 0;

                iVal 
            = m_pRoot->m_iData;
                TreeNode 
            *pTmp = m_pRoot;
                m_pRoot 
            = Merge(m_pRoot->m_pLeft, m_pRoot->m_pRight);
                delete pTmp;
                
            return 1;
            }

            int LeftistTree::Enqueue(int iVal)
            {
                TreeNode 
            *pNew = new TreeNode(iVal);
                m_pRoot 
            = Merge(m_pRoot, pNew);
                
            return 1;
            }

            TreeNode
            * LeftistTree::Merge(TreeNode *pT1, TreeNode *pT2)
            {
                
            if(pT1==0 && pT2==0)
                    
            return 0;
                
            else if(pT1==0//pT2!=0
                    return pT2;
                
            else if(pT2==0//pT1!=0
                    return pT1;

                
            if(pT1->m_iData > pT2->m_iData)
                    
            return Merge(pT2, pT1);

                Stack st(
            40);
                
                TreeNode
            * pInsPos = pT1;
                TreeNode
            * pToIns = pT2;
                TreeNode
            * pTmp;
                
                st.Push(pInsPos);

                
            //Find a node available for insert.
                while(1)
                {
                    
            if(pInsPos->m_pRight!=NULL)
                    {
                        
            if(pToIns->m_iData < pInsPos->m_pRight->m_iData)
                        {
                            pTmp 
            = pInsPos->m_pRight;
                            pInsPos
            ->m_pRight = pToIns;
                            pToIns 
            = pTmp;
                            st.Push(pInsPos);
                            pInsPos 
            = pInsPos->m_pRight;
                        }
                        
            else
                        {
                            st.Push(pInsPos);
                            pInsPos 
            = pInsPos->m_pRight;
                        }
                    }
                    
            else
                    {
                        st.Push(pInsPos);
                        
            //Insert
                        pInsPos->m_pRight = pToIns;
                        
            break;
                    }
                }

                TreeNode
            * pNode;
                
            //Try to update the relative distance and make the tree be still the leftist tree.
                while (0!=st.Pop(pNode))
                {
                    
            if(pNode->GetLeftDistance() < pNode->GetRightDistance())
                        pNode
            ->SwapLeftRight();
                    pNode
            ->UpdateDistance();
                }

                
            return pT1;
            }

            TreeNode
            * LeftistTree::GetRoot()
            {
                
            return m_pRoot;
            }

            #ifdef _DEBUG
            void LeftistTree::Print(TreeNode* pNode)
            {
                
            if(pNode!=NULL)
                {
                    
            if(pNode->m_pLeft!=NULL && pNode->m_pRight!=NULL)
                    {
                        printf(
            "%d[%d]->(%d, %d)\n", pNode->m_iData, pNode->m_iDistance, pNode->m_pLeft->m_iData, pNode->m_pRight->m_iData);
                        Print(pNode
            ->m_pLeft);
                        Print(pNode
            ->m_pRight);
                    }
                    
            else if(pNode->m_pLeft!=NULL)
                    {
                        printf(
            "%d[%d]->(%d, x)\n", pNode->m_iData, pNode->m_iDistance, pNode->m_pLeft->m_iData);
                        Print(pNode
            ->m_pLeft);
                    }
                    
            else if(pNode->m_pRight!=NULL)
                    {
                        printf(
            "%d[%d]->(x, %d)\n", pNode->m_iData, pNode->m_iDistance, pNode->m_pRight->m_iData);
                        Print(pNode
            ->m_pRight);
                    }
                }
            }
            #endif

            int main(int argc, char* argv[])
            {
                LeftistTree tree;
                tree.Enqueue(
            9);
                tree.Enqueue(
            4);
                tree.Enqueue(
            2);
                tree.Enqueue(
            1);
                tree.Enqueue(
            3);
                tree.Enqueue(
            8);

            #ifdef _DEBUG
                tree.Print(tree.GetRoot());
            #endif

                
            int iVal;
                tree.Dequeue(iVal);
                printf(
            "\nDequeue value is %d\n", iVal);
                tree.Dequeue(iVal);
                printf(
            "Dequeue value is %d\n", iVal);

            #ifdef _DEBUG
                tree.Print(tree.GetRoot());
            #endif

                
            return 0;
            }
            也許你還想問:怎么你寫的代碼都不加個頭啊,用來聲明版權什么的。本人似乎沒這個習慣,那些東西繁瑣得很,而且根據我多年開發經驗,給每個cpp文件加個頭其實是沒有必要的,就好像注釋,不需要的時候也生硬加上,那就是畫蛇添足了。

            (未完待續)
            posted on 2009-10-30 15:55 Jiang Guogang 閱讀(1611) 評論(1)  編輯 收藏 引用 所屬分類: Knowledge

            評論

            # re: 圖解數據結構(9)——左偏樹 2010-04-25 11:43 ccsu_010
            必須頂~  回復  更多評論
              

            久久九九久精品国产| 亚洲国产精品综合久久网络 | 亚洲AV伊人久久青青草原| 久久精品成人欧美大片| 久久久一本精品99久久精品88| 一本色综合网久久| 久久久久久亚洲精品不卡| 国产69精品久久久久9999APGF| 久久精品国产网红主播| 亚洲国产一成久久精品国产成人综合| 精品国产日韩久久亚洲| 久久久久国色AV免费观看| 亚洲国产另类久久久精品| 亚洲AV无码久久寂寞少妇| 久久人人爽人爽人人爽av| 国内精品免费久久影院| 国产精品gz久久久| 国内精品欧美久久精品| 久久综合狠狠综合久久综合88| 日日噜噜夜夜狠狠久久丁香五月| 99久久国产热无码精品免费久久久久 | 久久这里只有精品视频99| 国产精品天天影视久久综合网| 久久久久人妻一区精品色| 色综合久久久久综合99| 国产高潮久久免费观看| 亚洲国产成人久久精品影视| 97久久天天综合色天天综合色hd| 亚洲va国产va天堂va久久| 国产成人精品久久| 人妻无码精品久久亚瑟影视| 久久国产亚洲精品| 精品人妻久久久久久888| 国产亚洲成人久久| 久久精品国产99国产电影网| 青青热久久国产久精品| 精品国产一区二区三区久久蜜臀| 伊人久久综在合线亚洲2019 | 久久夜色精品国产网站| 人妻少妇久久中文字幕| 国产精品一久久香蕉国产线看观看|