《妙趣横生的算法》(C语言实现)-第3章 常用的算法思想

记录一下看到的内容,方便以后回想,也算是有点印记。
对于计算机科学而言,算法(Algorithm)是一个非常重要的概念。它是程序设计的灵魂,是将实际问题同解决问题的计算机程序建立起练习的桥梁。可以这样讲,在编写任何一个计算机程序时(无论使用什么编程语言),都不可避免地要进行算法的设计。
一个程序往往要包含两个方面的描述:一是对数据组织的描述;一是对程序操作流程的描述。对数据组织的描述主要是指定数据的类型和数据的组织形式,称作数据结构;对程序操作流程的描述就是程序的操作步骤,也即算法。数据结构+算法=程序
算法的性质:输入、输出、确定性、有限性。
算法的表示形式很多,包括但不仅限于用自然语言描述、用流程图表示、伪代码等。
穷举法是一种最为直接,实现最为简单,同时又是最为耗时的一种解决实际问题的算法思想。
【实例3-3】寻找1~100之间的素数。
题目分析:判断1至100种的每个数是否是素数即可。

// 3-3 2023年12月25日11点24分-11点28分 
# include 
# include 
int isprime(int num)
{ // 判断num是否是素数,是则返回1,不是则返回0 
    int flg = 1;
    if (num <= 1) // 1不是素数 
        flg = 0;
    else {
        for (int i = 2; num > 2 && i <= sqrt(num); ++i)
            if (num % i == 0) {
                flg = 0;
                break;
            }
    }
    return flg;
}
void getPrime(int low, int high)
{ // 寻找[low, high]之间的素数 
    for (int i = low; i <= high; ++i) {
        if (isprime(i)) {
            printf("%d ", i);
        }
    }
} 
int main()
{
    int low, high;
    printf("Please input the domain for searching prime\n");
    printf("low limitation:");
    scanf("%d", & low);
    printf("high limitation:");
    scanf("%d", & high);
    printf("The whole primes in this domain are\n");
    getPrime(low, high);
    return 0;
} 

【实例3-4】TOM共有5本新书,要借给A、B、C3位同学,每人只能借1本书,则TOM可以有多少种不同的借书方法。

// 3-4 2023年12月25日11点38分-11点43分 
# include 
void func(void)
{ // 三人借的书不相同 
    int cnt = 0;
    for (int i = 1; i <= 5; ++i) {
        for (int j = 1; j <= 5; ++j) {
            if (j == i) {
                continue;
            }
            for (int k = 1; k <= 5; ++k) {
                if (k == i || k == j) {
                    continue;
                }
                printf("<%d,%d,%d>", i, j, k);
                ++cnt;
                if (cnt == 5) {
                    putchar('\n');
                    cnt = 0;
                } else {
                    printf(", ");
                }
            }
        }
    }
}
int main()
{
    printf("There are different methods for TOM to distribute his books to A, B, C\n");
    func();
    return 0;
} 

递归与分治
将一个规模较大的问题分割成规模较小的同类问题,然后将这些小的子问题逐个加以解决,最终也就将整个大的问题解决了。
【实例3-5】计算n的阶乘n!。

// 3-5 2023年12月25日11点55分-11点59分 
# include 
//int factorial(int num)
//{ // 循环累乘 
//    int res = 1;
//    for (int i = 1; i <= num; ++i) {
//        res *= i;
//    }
//    return res;
//}
int factorial(int num)
{ // 递归 
    if (num == 0) // 递归结束标志,递归结束的出口 
        return 1;
    else
        return num * factorial(num - 1);
}
int main()
{
    int n;
    printf("Please input a number:");
    scanf("%d", & n);
    printf("The result is %d", factorial(n));
    return 0;
}

【实例3-6】将一个正整数n表示成一系列的正整数之和,被称作正整数n的一个划分。计算整数的划分数。

// 3-6 2023年12月25日12点12分-12点16分 
# include 
int P(int n, int m)
{
    if (m == 1 || n == 1)
        return 1;
    if (m > n)
        return P(n, n);
    if (m == n)
        return 1 + P(n, m-1); 
    return P(n, m-1) + P(n-m, m);
}
int main()
{
    int n, s;
    printf("Please input a integer for getting the number of division\n");
    scanf("%d", & n); // 输入正整数n
    s = P(n, n); // 求出正整数n的划分数
    printf("The number of division of %d is %d\n", n, s); 
    return 0;
} 

【实例3-7】递归的方法实现折半查找。

// 3-7 2023年12月25日15点34分-15点49分 
int bin_search(int A[], int low, int high, int x)
{
    if (low > high) {
        return -1; 
    } else {
        int mid = (high + low) / 2; // 要认真,是相加除以2,不是相减除以2
        if (A[mid] == x) {
            return mid;
        } else if (A[mid] > x) {
            return bin_search(A, low, mid - 1, x);
        } else {
            return bin_search(A, mid + 1, high, x);
        }
    }
}
# include 
int main()
{
    int A[10] = {2, 3, 5, 7, 8, 10, 12, 15, 19, 21}; // 初始化数组序列A
    printf("The contents of the Array A[10] are\n"); 
    for (int i = 0; i < 10; ++i) {
        printf("%d ", A[i]); // 显示数组A中的内容 
    }
    printf("\nPlease input a integer for search\n");
    int n;
    scanf("%d", & n); // 输入待查找的元素
    int addr = bin_search(A, 0, 9, n); 
    if (-1 != addr) // 查找成功 
        printf("%d is at the %dth unit in array A\n", n, addr + 1);
    else // 查找失败 
        printf("There is no %d in array A\n", n);
    return 0;
}

贪心算法
所谓贪心算法,就是总是做出在当前看来是最好的选择的一种方法。
【实例3-8】有一批集装箱要装入一个载质量为C的货船中,每个集装箱的质量由用户自己输入指定,在货船的装载体积不限的前提下,如何装在集装箱才能尽可能多的将集装箱载入货船中。

// 3-8 2023年12月25日16点08分-16点25分 
# include 
# include 
void sort(int w[], int t[], int n)
{
    int *w_tmp = (int *)malloc(sizeof(int) * n); // 动态开辟一个临时数组,存放w[]中的内容,用于排序
    for (int i = 0; i < n; ++i)
        t[i] = i; // 初始化数组t
    for (int i = 0; i < n; ++i)
        w_tmp[i] = w[i];
    for (int i = 0; i < n-1; ++i) {
        for (int j = 0; j < n-1-i; ++j) {
            if (w_tmp[j] > w_tmp[j+1]) {
                int tmp = w_tmp[j];
                w_tmp[j] = w_tmp[j+1];
                w_tmp[j+1] = tmp;
                tmp = t[j];
                t[j] = t[j+1];
                t[j+1] = tmp; 
            }
        }
    } 
}
void Loading(int x[], int w[], int c, int n)
{
    int *t = (int *)malloc(sizeof(int) * n); // 动态开辟一个临时数组,存放w[]的下标
    sort(w, t, n); // 排序,用数组t存放数组w的下标 
    for (int i = 0; i < n; ++i)
        x[i] = 0; // 初始化数组x
    for (int i = 0; i < n && w[t[i]] <= c; ++i) {
        x[t[i]] = 1; // 将第t[i]个集装箱装入货船中 
        c -= w[t[i]]; // 变量c存放货船的剩余载质量 
    } 
}
int main()
{
    int x[5], w[5], c;
    printf("Please input the maximum loading of the ship\n");
    scanf("%d", & c); // 输入货船的最大载质量 
    printf("Please input the weight of FIVE box\n");
    for (int i = 0; i < 5; ++i)
        scanf("%d", & w[i]); // 输入每个集装箱的质量
    Loading(x, w, c, 5); // 进行最优装载
    printf("The following boxes will be loaded\n"); 
    for (int i = 0; i < 5; ++i) // 输出结果
        if (1 == x[i]) 
            printf("BOX:%d ", i);
    return 0;
}

回溯法
【实例3-9】应用回溯法的思想求解四皇后问题。

// 3-9 2023年12月25日16点32分-16点51分 
# include 
int count = 0; // 记录四皇后问题解的个数
int isCorrect(int i, int j, int (*Q)[4])
{
    for (int s = i, t = 0; t < 4; ++t)
        if (Q[s][t] == 1 && t != j) // 判断行 
            return 0;
    for (int s = 0, t = j; s < 4; ++s)
        if (Q[s][t] == 1 && s != i) // 判断列
            return 0;
    for (int s = i-1, t = j-1; s >= 0 && t >= 0; --s, --t) 
        if (Q[s][t] == 1) // 判断左上方
            return 0;
    for (int s = i+1, t = j+1; s < 4 && t < 4; ++s, ++t) 
        if (Q[s][t] == 1) // 判断右下方
            return 0;
    for (int s = i-1, t = j+1; s >= 0 && t < 4; --s, ++t) 
        if (Q[s][t] == 1) // 判断右上方
            return 0;
    for (int s = i+1, t = j-1; s < 4 && t >= 0; ++s, --t)
        if (Q[s][t] == 1) // 判断左下方
            return 0;
    return 1; // 否则返回1 
} 
void Queen(int j, int (*Q)[4]) 
{
    if (j == 4) {
        for (int i = 0; i < 4; ++i) { // 得到了一个解,在屏幕上输出结果 
            for (int k = 0; k < 4; ++k) {
                printf("%d ", Q[i][k]);
            }
            printf("\n");
        }
        printf("\n");
        ++count;
        return ;
    }
    for (int i = 0; i < 4; ++i) {
        if (isCorrect(i, j, Q)) { // 如果Q[i][j]可以放置皇后 
            Q[i][j] = 1; // 放置皇后
            Queen(j+1, Q); // 递归深度优先搜索解空间树
            Q[i][j] = 0; 
        }
    }
}
int main()
{
    int Q[4][4]; 
    for (int i = 0; i < 4; ++i) { // 初始化数组Q 
        for (int j = 0; j < 4; ++j) {
            Q[i][j] = 0;
        }
    }
    Queen(0, Q); // 执行四皇后求解
    printf("The number of the answers of FOUR_QUEEN are %d", count); 
    return 0;
}

数值概率算法
【实例3-10】计算定积分。

// 3-10 2023年12月25日18点27分-18点33分 
# include 
# include 
# include 
# include 
double Darts(int n)
{
    double x, y;
    time_t t;
    int i, count = 0;
    srand((unsigned)time(& t));
    for (i = 0; i < n; ++i) {
        x = rand() % 100 / 100.0;
        y = rand() % 100 / 100.0;
        if (y <= 1 - pow(x, 2))
            ++count;
    }
    return (double)count / (double)n;
}
int main()
{
    int n;
    printf("Please input the accuracy\n");
    scanf("%d", & n);
    printf("The result is about\n");
    printf("%f\n", Darts(n));
    return 0;
} 

要加油啊!

你可能感兴趣的:(算法,c语言)