選擇樹、判定樹和查找樹


選擇樹

  • 概念:假設有k個已經排序的序列,並且想要將其合並成一個單獨的排序序列。每個排好序的序列叫走一個歸並段

  • 暴力算法:假設總共有n個數字,每次取k個歸並串最小或者最大的一個數,比較k-1次得到所有數中最大或者最小的樹,存入新空間中,接着一直這樣比較...需要比較的次數是n*(k-1)

  • 選擇樹算法:可以構造完全二叉樹的數組表示法。初始狀態如下:

image_1bdanvg751kp9msn1nnph4u1r9rm.png-41.1kB

接着將上圖最小的6放到新序列中,然后用15替換最下層的6,再進行規范化,接着選出最小,如下:

image_1bdanucc21h561sv6bar18hj1tmh9.png-34kB

可以看到,每次的比較次數是O(logk),時間復雜度是O(nlogk)

判定樹

  • 概念:以著名的8枚硬幣的問題進行說明。假定有8枚硬幣a-h,其中一枚硬幣是偽造的。偽造的硬幣可能比標准的重或者輕,所以可能的結果有16種情況。

捕獲.PNG-43.2kB

  • 如圖,無論是什么情況,經過3次比較一定出結果

  • 代碼如下:

    char Compare(int a, int b)
    {
        if(a > b)
            return '>';
        else if(a < b)
            return '<';
        else
            return '=';
    }
    
    
    void comp(int x,int y,int z)
    {
        if(x>z)
            cout << x << "heavy";
        else
            cout << y << "light";
    }
    
    void eightcoins()
    {
        int a,b,c,d,e,f,g,h;
        cin >> a >> b >> ... >> h;
        switch(Compare(a+b+c,d+e+f)) {
            case '=':
                if(g>h)
                    comp(g,h,a)
                else
                    comp(h,g,a);
                
                break;
            case '>':
                switch(Compare(a+d,b+e)) {
                    case '=':
                        comp(c,f,a);
                        break;
                    case '>':
                        comp(a,e,b);
                        break;
                    case '<':
                        comp(b,d,a);
                    break;
                }
                
                break;
            case '<':
                switch(Compare(a+d,b+e)) {
                    case '=':
                        comp(f,c,a);
                        break;
                    case '>':
                        comp(d,b,a);
                        break;
                    case '<':
                        comp(e,a,b);
                    break;
                }
                
                break;
                    
        }
    }
    
    

查找樹

  一般來說,查找樹指的是二叉查找樹,其查找過程是從根結點一直向下查找,時間復雜度為O(logn)。

對查找二叉樹進行中序遍歷,是個遞增序列

定義如下:

  • 若它的左子樹不空,則其左子樹上任意結點的關鍵字的值都小於根結點關鍵字的值
  • 若右子樹不空,則其右子樹上任意結點的關鍵字的值都大於根結點的關鍵字的值
  • 它的左右子樹又是一個二叉查找樹

image_1bdg1qlmv19jbggt111u7q217lt9.png-30.8kB

代碼實現:

  • 定義數據結構:
    struct celltype{
        records data;
        celltype *lchild, *rchild;
    };
    
    typedef celltype *BST;
  • 插入數據:
    void Insert(records R, BST &F)
    {
        if(F == NULL) {
            F = new celltype;
            F->data = R;
            F->lchild = NULL;
            F->rchild = NULL;
        } else if(R.key < F->data.key)
            Insert(R,F->lchild);
        else if(R.key > F->data.key)
            Insert(R,F->rchild);
    }
    
  • 刪除數據:
    //刪除關鍵字最小的結點並且返回其數據
    records DeleteMin(BST & F)
    {
        records tmp;
        BST P;
        if(F->lchild == NULL) {
            P = F;
            tmp = F->data;
            F = F->rchild;
            delete P;
            return tmp;
        } else
            return DeleteMin(F->lchild);
    }

    void Delete(keytype k,BST &F)
    {
        if(F) {
            if(k < F->data.key)
                Delete(k,F->lchild);
            else if(k > F->data.key)
                Delete(k,F->rchild);
            else
                //查找成功
            {
                if(F->lchild == NULL)
                    F = F->rchild;
                else if(F->rchild == NULL)
                    F = F->lchild;
                else
                    F->data = DeleteMin(F->rchild);
            }
        }
    }
  • 查找數據
    BST Serach(keytype k,BST F)
    {
        if(F == NULL)
            return NULL;
        else if( k == F->data.key)
            return F;
        else if(k < F->data.key)
            return Search(k,F->lchild);
        else if(k > F->data.key)
            return Search(k,F->rchild);
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM