• <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

            創(chuàng)作,也是一種學習的過程。

               :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::

            十三、左偏樹(Leftist Tree)

            樹這個數(shù)據(jù)結(jié)構(gòu)內(nèi)容真的很多,上一節(jié)所講的二叉堆,其實就是一顆二叉樹,這次講的左偏樹(又叫“左翼堆”),也是樹。

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

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

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

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

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


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

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

            #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;
            }
            也許你還想問:怎么你寫的代碼都不加個頭啊,用來聲明版權(quán)什么的。本人似乎沒這個習慣,那些東西繁瑣得很,而且根據(jù)我多年開發(fā)經(jīng)驗,給每個cpp文件加個頭其實是沒有必要的,就好像注釋,不需要的時候也生硬加上,那就是畫蛇添足了。

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

            評論

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

            精品综合久久久久久88小说| 久久精品国产日本波多野结衣| 久久午夜夜伦鲁鲁片免费无码影视| 伊人伊成久久人综合网777| 久久久黄色大片| 久久发布国产伦子伦精品 | 精品水蜜桃久久久久久久| 品成人欧美大片久久国产欧美| 久久久久女教师免费一区| 99久久夜色精品国产网站| 99久久婷婷国产综合亚洲| 久久高潮一级毛片免费| 久久久久久精品免费免费自慰| 久久er国产精品免费观看2| 合区精品久久久中文字幕一区| 久久综合久久自在自线精品自| 久久精品国产亚洲av瑜伽| 色婷婷综合久久久久中文 | 成人综合久久精品色婷婷| avtt天堂网久久精品| 精品伊人久久大线蕉色首页| 国产精品久久毛片完整版| 伊人久久综合成人网| 久久久99精品一区二区| 996久久国产精品线观看| 伊人久久精品无码二区麻豆| 久久精品亚洲男人的天堂| 久久综合丁香激情久久| 亚洲av成人无码久久精品 | 久久无码人妻一区二区三区| 亚洲欧美国产日韩综合久久| 色综合久久最新中文字幕| 久久久久99精品成人片直播| 久久久久久久精品成人热色戒 | 亚洲日本va午夜中文字幕久久| 久久精品一本到99热免费| 国产香蕉久久精品综合网| 久久天天躁狠狠躁夜夜不卡| 久久久久女教师免费一区| 亚洲精品无码久久久久AV麻豆| 亚洲婷婷国产精品电影人久久|