[算法设计与分析]3.1.3递归与循环的比较(输出各位数字+任何数都可以用2的幂表示+组合数)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Pecony/article/details/79769203
#include<stdio.h>
#include<iostream>

using namespace std;


void PrintToLow1(int num);//7.对十进制数 从高到低输出各位数字
void PrintToLow2(int num);
void PrintToHigh1(int num);
void PrintToHigh2(int num);//对十进制数 从低到高输出各位数字
void MakeUpOfTwo(int num, int r);//8.任何一个正整数都可以用2 的幂次方来表示
void ExtendMakeUpOfTwo(int num, int r);
void Choose1(int n, int r);//9.从n个数中取r个数的组合满足组中的数互不相同且前面的数小于后面的数
void Choose2(int n, int r);
int divide[100] = {0};
int record[100];

int main()
{
    cout << "\n从低位开始打印(递归):\n";
	PrintToLow1(34673);
	cout << "\n从低位开始打印(迭代):\n";
	PrintToLow2(34673);
    cout << "\n从高位开始打印(递归):\n";
    PrintToHigh1(34673);
    cout << "\n从高位开始打印(迭代):\n";
    PrintToHigh2(34673);

    cout << "\n任何一个正整数都可以用2 的幂次方来表示" << endl;
    MakeUpOfTwo(1315, 0);
    cout << "\n任何一个正整数都可以用2 的幂次方来表示" << endl;
    ExtendMakeUpOfTwo(1315, 0);
    cout << "\n组合数:\n";
    Choose1(5, 3);
    record[0] = 3;
    cout << "\n组合数:\n";
    Choose2(5, 3);
}


void PrintToLow1(int num)
{
    if(num == 0)
        return;
    PrintToLow1(num / 10);
    printf("%d  ", num % 10);
}

void PrintToLow2(int num)
{
    int record[10], i = 0;
    while(num)
    {
        record[i++] = num % 10;
        num /= 10;
    }
    i--;
    for(;i >= 0; i--)
        printf("%d  ", record[i]);
}
void PrintToHigh1(int num)
{
    if(num == 0)
        return;
    printf("%d  ", num % 10);
    PrintToHigh1(num / 10);
}
void PrintToHigh2(int num)
{
    while(num)
    {
        printf("%d  ", num % 10);
        num /= 10;
    }
}
//整个求解过程相当于 十进制到二进制的转换 采用辗转相除法
void MakeUpOfTwo(int num, int r)
{
    if(num == 1)
       cout << "2(" << r << ")";
    else
    {
        MakeUpOfTwo(num / 2, r + 1);//用r记录递归的深度 即2的r次幂
        if(num % 2 == 1)//此时递归已经全部结束开始一层层的返回
        {//相当于用二进制表示十进制的数 只有该位对应为1则1*2^n 余数为1对应辗转相除法中 /2 余1写在后面
           cout << " + 2(" << r << ")";
        }
    }
}
void ExtendMakeUpOfTwo(int n, int r)
{//n=1对应的是一组递归的终结
    if(n == 1)//当n=1时证明初始的n已经无法在进行分割了
    {
        switch(r)
        {
        case 0:
            printf("2(0)");
            break;
        case 1:
            printf("2(1)");
            break;
        case 2:
            printf("2(2)");
            break;
        default:
            printf("2(");
            ExtendMakeUpOfTwo(r, 0);//函数ExtendMakeUpOfTwo(n, 0)的作用就是求n的2的幂次方的表示
                                    //因此直接递归调用就可以将之前的2以上的幂的次数表示转换成更小的组成
            printf(")");//递归结束之后将括号补齐
        }
    }
    else
    {
        ExtendMakeUpOfTwo(n / 2, r + 1);//持续递归 最后一次递归一定执行的是上方的if语句
        if(n % 2 == 1)//开始逐层返回
        {
            switch(r)
            {
            case 0:
                printf("+2(0)");
                break;
            case 1:
                printf("+2(1)");
                break;
            case 2:
                printf("+2(2)");
                break;
            default://在本函数中不允许有超过2的2的幂次的表示 因此如果出现就要继续递归
                printf("+2(");
                ExtendMakeUpOfTwo(r, 0);
                printf(")");
            }
        }
    }
}

void Choose1(int n, int r)
{
    cout << endl;
    int counts = 0;
    for(int i = 1; i <= n - 2; i++)
    {
        for(int j = i + 1; j <= n - 1; j++)
        {
            for(int k = j + 1; k <= n; k++)
            {
                counts++;
                printf("%d, %d, %d;\n", i, j, k);
            }
        }
    }
}

void Choose2(int n, int r)
{
    for(int i = n; i >= r; i--)
    {
        record[r] = i;
        if(r > 1)
            Choose2(i - 1, r - 1);
        else
        {
            for(int j = record[0]; j > 0; j--)
               printf("%d  ", record[j]);
            cout << endl;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Pecony/article/details/79769203