• <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>
            SmartPtr
            本博客已搬至:http://www.cnblogs.com/baiyanhuang/
            posts - 29,comments - 176,trackbacks - 0
            By SmartPtr(http://www.shnenglu.com/SmartPtr/)

            給出1, 2, 3, 4四個數(shù), 請編程輸出其全排列, 如:
            1 2 3 4
            1 2 4 3
            1 3 2 4
            1 3 4 2
            ...
            這樣的題, 我們在學校的時候一般都遇到過,而我們最先能想到的,應該就是遞歸實現(xiàn)了,因為這和我們我理解的數(shù)學中的排列組合比較一致:先取第一個數(shù),有4種可能,再在剩下的3個數(shù)種取出第二個數(shù),這又有3種可能,這樣下去直到取到最后一個數(shù)。 這樣,4個數(shù)的全排列就有4*3*2 = 24個。n個數(shù)的全排列就是n*(n-1)*(n-2)*...*2*1. 按照這個描述, 我們發(fā)現(xiàn)有兩點在程序中遞歸實現(xiàn)時十分重要:
            1. 哪些數(shù)已經(jīng)取過了而哪些數(shù)又是沒有取過,可以用的?
            2. 現(xiàn)在取的是哪一個數(shù)。
            確保了這兩個信息,我們的遞歸實現(xiàn)就沒有什么問題了。對于第一個問題,我們有兩種方法可以實現(xiàn):
            1) 用一個對應的bool型數(shù)組來記錄被排列數(shù)組的使用狀態(tài),這個狀態(tài)在遞歸過程中需要回溯
            2) 用一個ILLEGAL值來表示不是屬于排序的數(shù),排列數(shù)組中的數(shù)一旦被使用,就用這個值來覆蓋,當然,遞歸過程中此值也需要回溯。
            同樣,現(xiàn)在取得是哪個數(shù),我們也有兩種方法來表示:
            1) 用參數(shù)的方式來表明這次遞歸調用是為了得第幾個值、
            2) 用一個靜態(tài)變量來表示當前遞歸的深度,此深度值表明了我當前取的是哪個數(shù)。

            上面兩點的兩種解決方法排列組合一下:),我們就有4種方法

            首先是定義最大數(shù)組長度與非法值

            #define N 10
            #define ILLEAGALNUM  -100

            下面列出每一種實現(xiàn):

            //數(shù)組存使用狀態(tài),調用深度表示取第幾個數(shù)
            void Permutation1(int a[], int n)
            {
                
            static int out[N]; // result array
                static bool m[N] = {1,1,1,1,1,1,1,1,1,1}; // mark array, indicate whether the coorespond element 
                                                          
            //in array a is already used.
                static int depth = -1;                      //recursive call depth.
                depth++;
                
            for(int i = 0; i < n; ++i)
                {
                    
            if(depth == n)                      // if we already get the last num, print it
                    {
                        
            static int l = 1;
                        printf(
            "%3d: ", l++);
                        
            for(int k = 0; k<n; k++) printf("%d "out[k]);
                        printf(
            " ");
                        depth
            --;
                        
            return;
                    }
                    
            else if(true == m[i])                      // if element i not used
                    {
                        
            out[depth] = a[i];
                        m[i] 
            = false;                      // mark element i as used
                        Permutation1(a, n);                      // recursive to get next num
                        m[i] = true;                      // backdate , so that we can try another case
                    }
                }
                depth
            --;
            }

            //修改數(shù)據(jù)數(shù)組表示其使用狀態(tài),參數(shù)表示取第幾個數(shù)
            void Permutation2(int a[], int index, int n)
            {
                
            static int out[N];
                
            for(int i = 0; i < n; ++i)
                {
                    
            if(index == n)                      //index > n-1, try to get the n-1 num, means it is ok , printf it
                    {
                        
            static int l = 1;
                        printf(
            "%3d: ", l++);
                        
            for(int k = 0; k<n; k++) printf("%d "out[k]);
                        printf(
            " ");
                        
            return;
                    }
                    
            else if(a[i] != ILLEAGALNUM)
                    {
                        
            out[index] = a[i];
                        a[i] 
            = ILLEAGALNUM;
                        Permutation2(a, index
            +1, n);
                        a[i] 
            = out[index];
                    }
                }
            }

            //修改數(shù)據(jù)數(shù)組表示其使用狀態(tài),調用深度表示取第幾個數(shù)
            void Permutation3(int a[], int n)
            {
                
            static int out[N];
                
            static int depth = -1;                      //recursive call depth.
                depth++;
                
            for(int i = 0; i < n; ++i)
                {
                    
            if(depth == n)                      //index > n-1, try to get the n-1 num, means it is ok , printf it
                    {
                        
            static int l = 1;
                        printf(
            "%3d: ", l++);
                        
            for(int k = 0; k<n; k++) printf("%d "out[k]);
                        printf(
            " ");
                        depth
            --;
                        
            return;
                    }
                    
            else if(a[i] != ILLEAGALNUM)
                    {
                        
            out[depth] = a[i];
                        a[i] 
            = ILLEAGALNUM;
                        Permutation3(a, n);
                        a[i] 
            = out[depth];
                    }
                }
                depth
            --;
            }


            //額外的數(shù)組表示其使用狀態(tài),參數(shù)表示取第幾個數(shù)
            void Permutation4(int a[], int index, int n)
            {
                
            static int out[N]; // result array
                static bool m[N] = {1,1,1,1,1,1,1,1,1,1}; // mark array, indicate whether the coorespond element 
                                                          
            //in array a is already used.
                for(int i = 0; i < n; ++i)
                {
                    
            if(index == n)                      // if we already get the last num, print it
                    {
                        
            static int l = 1;
                        printf(
            "%3d: ", l++);
                        
            for(int k = 0; k<n; k++) printf("%d "out[k]);
                        printf(
            " ");
                        
            return;
                    }
                    
            else if(true == m[i])                      // if element i not used
                    {
                        
            out[index] = a[i];
                        m[i] 
            = false;                      // mark element i as used
                        Permutation4(a, index+1, n);                      // recursive to get next num
                        m[i] = true;                      // backdate , so that we can try another case
                    }
                }
            }

             

            雖然對于這樣的問題效率與空間相差不會特別明顯,但是我們還是來比較一下來找出最佳的一個。對于數(shù)組使用狀態(tài)的保存,顯然,用第一個方案需要動用一個額外的數(shù)組,而并沒有提高效率,所以我們應該采用第二個方案:修改數(shù)組值的方法。對于當前取的是哪個數(shù),如果我們用傳參數(shù)的方式,因為在排列過程中,這個遞歸函數(shù)被調用的次數(shù)是非常多的。(6個數(shù)的全排列就要調用1957次),這樣多一個參數(shù), 其每次調用壓棧出棧的消耗就顯得比較大了, 所以我們推薦用調用深度來表示。


            經(jīng)過上面的討論, Permutation3就是我們的最佳選擇。



            posted on 2007-08-26 20:45 SmartPtr 閱讀(763) 評論(0)  編輯 收藏 引用
            77777亚洲午夜久久多喷| Xx性欧美肥妇精品久久久久久 | 亚洲国产精品无码久久久秋霞2 | 欧美777精品久久久久网| 久久久久亚洲AV无码专区桃色| 一本久久综合亚洲鲁鲁五月天| 2022年国产精品久久久久| 人人狠狠综合久久亚洲婷婷| 久久这里有精品视频| 国产成人久久激情91| av色综合久久天堂av色综合在| 久久91精品国产91久久麻豆| 久久夜色精品国产亚洲| 精品国产热久久久福利| 久久国产精品一区| 国产农村妇女毛片精品久久| 久久精品卫校国产小美女| 伊人久久一区二区三区无码| 久久国产亚洲精品无码| 久久九九久精品国产免费直播| 999久久久免费精品国产| 日产精品久久久久久久| 久久综合伊人77777麻豆| 好久久免费视频高清| 久久久久久国产精品无码超碰| 国产精品一区二区久久精品涩爱| 成人国内精品久久久久影院VR| 久久久国产乱子伦精品作者| 中文精品99久久国产 | 一本色道久久88加勒比—综合| 久久99国产精品二区不卡| 伊人久久大香线蕉av一区| 超级碰碰碰碰97久久久久| 久久性生大片免费观看性| 欧美久久久久久精选9999| 精品久久久久一区二区三区| 狠狠色噜噜狠狠狠狠狠色综合久久| 一本久道久久综合狠狠爱| 久久久久久久久久久久中文字幕 | 伊人久久综在合线亚洲2019 | 精品精品国产自在久久高清|