您的位置:首页 > 业界新闻

高效率的排列组合算法

2006-10-10 12:55 603 查看
 
1。最近一直在考虑从m个数里面取n个数的算法。最容易理解的就是递归,但是其效率,实在不能使用。一直找寻中,今日得果

2。算法来源与互联网

组合算法  
  本程序的思路是开一个数组,其下标表示1到m个数,数组元素的值为1表示其下标  
  代表的数被选中,为0则没选中。    
  首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。    
  然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为  
  “01”组合,同时将其左边的所有“1”全部移动到数组的最左端。    
  当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得  
  到了最后一个组合。    
  例如求5中选3的组合:    
  1   1   1   0   0   //1,2,3    
  1   1   0   1   0   //1,2,4    
  1   0   1   1   0   //1,3,4    
  0   1   1   1   0   //2,3,4    
  1   1   0   0   1   //1,2,5    
  1   0   1   0   1   //1,3,5    
  0   1   1   0   1   //2,3,5    
  1   0   0   1   1   //1,4,5    
  0   1   0   1   1   //2,4,5    
  0   0   1   1   1   //3,4,5  

 

代码实现:(java)

public class XuanZePaiLie {
    int[] orgNumbers;
    int[] mapNumbers;
    int iSelectCount;
    int iTotal = 0;
    public XuanZePaiLie(int[] orgNumbers,int iSelect) {
        this.orgNumbers = orgNumbers;
        this.iSelectCount = iSelect;
        mapNumbers = new int[orgNumbers.length];
        for(int i=0;i<iSelectCount;i++)
        {
            this.mapNumbers[i] = 1;
        }
    }

    public void doXuanZePaiLie()
    {
        printNumbers();
        while(!isPaiLieEnd())
        {
            int index = getSwitchOneIndex();
            switchOneZero(index);
            moveOneToLeft(index);
            printNumbers();
        }
    }

    private boolean isPaiLieEnd()
    {
        for(int i=mapNumbers.length-1;i>mapNumbers.length-(1+iSelectCount);i--)
        {
            if(mapNumbers[i]==0)
            {
                return false;
            }
        }
        return true;
    }

    private int getSwitchOneIndex()
    {
        int i=0;
        while(i<mapNumbers.length)
        {
            if(mapNumbers[i]==1&&mapNumbers[i+1]==0)
            {
                return i;
            }
            i++;
        }
        return -1;
    }

    private void switchOneZero(int oneIndex)
    {
        mapNumbers[oneIndex]=0;
        mapNumbers[oneIndex+1]=1;
    }

    private void moveOneToLeft(int oneIndex)
    {
        int i = oneIndex-1;
        int iCount = 0;
        while(i>=0&&mapNumbers[i]==1)
        {
            iCount++;
            mapNumbers[i]=0;
            i--;
        }
        for(int j=0;j<iCount;j++)
        {
            mapNumbers[j]=1;
        }
    }

    private void printNumbers()
    {
        for(int i=0;i<orgNumbers.length;i++)
        {
            if(mapNumbers[i]==1)
            {
                System.out.print(orgNumbers[i]);
            }
        }
        System.out.println(" "+(++iTotal));
    }

}

全排列算法  
   
  从1到N,输出全排列,共N!条。  
  分析:用N进制的方法吧。设一个N个单元的数组,对第一个单元做加一操作,满N进  
  一。每加一次一就判断一下各位数组单元有无重复,有则再转回去做加一操作,没  
  有则说明得到了一个排列方案。

代码实现:(java)

//Main调用类:

public class mainjava {
    public mainjava() {
    }
    public static void main(String[] args)
    {
        int[] numbers = {1,2,2,3,4,5};
        pailie p = new pailie(numbers);
        p.doPailie();
    }
}

//排序处理类

public class pailie {
    int[] orgNumbers;
    int[] mapNumbers;
    int iJinZhi;
    int iCount = 0;
    public pailie(int[] orgNumbers) {
        this.orgNumbers = orgNumbers;
        this.iJinZhi = orgNumbers.length;
        mapNumbers = new int[orgNumbers.length];
        for(int i=0;i<mapNumbers.length;i++)
        {
            mapNumbers[i] = 0;
        }
    }

    public boolean isAnyNumbersSame()
    {
        for(int i=0;i<mapNumbers.length-1;i++)
        {
            for(int j=i+1;j<=mapNumbers.length-1;j++)
            {
                if(mapNumbers[i]==mapNumbers[j])
                {
                    return true;
                }
            }
        }
        return false;
    }

    public int getJinWeiIndex()
    {
        for(int i=mapNumbers.length-1;i>=0;i--)
        {
            if(mapNumbers[i]==this.iJinZhi)
            {
                return i;
            }
        }
        return -1;
    }

    public void addOne()
    {
        mapNumbers[mapNumbers.length-1]++;
    }

    public void printNumber()
    {
        for(int i=0;i<mapNumbers.length;i++)
        {
            System.out.print(orgNumbers[mapNumbers[i]]);
        }
        System.out.println(" "+(++iCount));
    }

    public void doJinWei(int index)
    {
        mapNumbers[index] = 0;
        mapNumbers[index-1]++;
    }

    private boolean hasNotOutRange()
    {
        if(mapNumbers[0]>=this.iJinZhi)
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    public void doPailie()
    {
        while(hasNotOutRange())
        {
            if (!isAnyNumbersSame()) {
                int index = getJinWeiIndex();
                if (index == -1) {
                    printNumber();
                    addOne();
                } else {
                    doJinWei(index);
                }
            } else {
                addOne();
                int index = getJinWeiIndex();
                if (index != -1) {
                    doJinWei(index);
                }
            }
        }
    }
}

comes from:/blog.csdn.net/MaybeHelios
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息