在數(shù)學(xué)中,有一些數(shù)據(jù)選擇的內(nèi)容。舉個(gè)例子來說,有這樣一組數(shù)據(jù):1、2、3、4?,F(xiàn)在我們打算從中挑選出1個(gè)數(shù)據(jù),那么有幾種選擇呢?結(jié)果應(yīng)該是1、2、3、4;那么如果挑選2個(gè)數(shù)據(jù)呢,怎么選呢?那么結(jié)果應(yīng)該是12、13、14、15。以此類推,我們還能挑選出3個(gè)數(shù)據(jù)、4個(gè)數(shù)據(jù)的情況。
那么,在程序上面應(yīng)該怎么表示呢?其實(shí)可以使用遞歸的方法。請(qǐng)大家和我一起計(jì)算一下:
如果需要從1、2、3、4中挑選兩個(gè)數(shù)據(jù),那么是不是先從1開始,然后再2、3、4中挑選一個(gè)數(shù)據(jù),這樣可以有12、13、14三種情況。接著呢,我們從2開始,下面可以選擇的數(shù)據(jù)只有從3、4中選擇了,1不能選擇了,否則會(huì)產(chǎn)生重復(fù)選項(xiàng)。以此類推,那我們從4開始的時(shí)候,發(fā)現(xiàn)4后面沒有數(shù)據(jù)的時(shí)候,此時(shí)迭代終止。
挑選2個(gè)數(shù)據(jù)如此,那么挑選n個(gè)數(shù)據(jù)是不是也是這樣呢?首先選出第1個(gè)數(shù)據(jù),那么剩下來的數(shù)據(jù)只能從這個(gè)數(shù)據(jù)后面位置開始挑選,如果挑選出n-1個(gè)數(shù)據(jù),那么表示n個(gè)數(shù)據(jù)存在,繼續(xù)尋找到,直到n-1個(gè)數(shù)據(jù)選不出來為止;接著我們移動(dòng)第一個(gè)數(shù)據(jù)的位置,同樣需要在當(dāng)前數(shù)據(jù)的后面挑選n-1個(gè)數(shù)據(jù)。以此類推,如果我們發(fā)現(xiàn)當(dāng)前數(shù)據(jù)后面連n-1個(gè)數(shù)據(jù)都沒有了,那么表示遞歸就結(jié)束了。
下面我們就可以書寫代碼了。
a) 定義全局空間和打印函數(shù),保存已經(jīng)遍歷的數(shù)據(jù)
static int gAllData[MAX_NUMBER]= {0};
static int gTotal = 0;
void print(int pData[], int length)
{
int index;
for(index = 0; index < length; index++)
printf("%d", pData[index]);
printf("n");
}
b)開始數(shù)據(jù)的迭代
void traverse(int pData[], int length, int number)
{
int index;
if(0 == length)
return;
for(index = 0; index < length; index++){
gAllData[gTotal ++] = pData[index];
if(1 == number)
print(gAllData, gTotal);
else
traverse(pData + (index + 1), length - (index + 1), number -1);
gAllData[-- gTotal] = 0;
}
}
c)編寫測(cè)試用例,驗(yàn)證結(jié)果
void test()
{
int data[] = {1, 2, 3, 4, 5, 6};
memset(gAllData, 0, sizeof(int) * MAX_NUMBER);
traverse(data, sizeof(data)/sizeof(int), 4);
}
注:我們可以通過不停修改數(shù)組data和數(shù)值number的方法,驗(yàn)證打印出來的數(shù)據(jù)和我們自己計(jì)算的結(jié)果是否有出入。