C语言关键算法

C语言关键算法

AB交换算法 万能版,适用float double int long

#define chg(a,b,t) t=a;a=b;b=t;

使用技巧

#define chg(a,b,t) t=a;a=b;b=t;
main(){
    int a=10,b=20,z;
    chg(a,b,z);//执行完 ab互换;
    int t[]={1,2,3,4,5};
    chg(t[0],t[1],z);//执行完 t[]={2,1,3,4,5};
}

AB交换算法,异或版,适用int long

#define chg(a,b) a^=b;b^=a;a^=b;
//或者
#define chg(a,b) b^=a^=b^=a;
//或者
#define chg(a,b) a^=b^=a^=b;

使用技巧

#define chg(a,b) a^=b^=a^=b;
main(){
    int a=10,b=20;
    chg(a,b);//执行完 ab互换;
    int t[]={1,2,3,4,5};
    chg(t[0],t[1]);//执行完 t[]={2,1,3,4,5};
}

最大公约数算法

递归版

int Gcd(int a, int b){
    return b == 0 ? a : Gcd(b, a % b);
}

循环版

int Gcd(int a, int b)
{	
	int t = b;
	while(a%b!=0)
	{
		t = a%b;
		a = b;
		b = t;
	}
	return t;
}

最小公倍数

int Lcm(int a, int b){
    return a * b / Gcd(a,b);
}

斐波那契数列

递归版

int Fib(int n){
    return (n == 1 || n == 2) ? 1 : Fib(n - 1) + Fib(n - 2);
}

循环版

int fib[1000] = { 0 };
fib[1] = fib[2] = 1;
for ( int i = 3; i < n; i++ )
{
	fib[i] = fib[i - 2] + fib[i - 1];
}

素数判断函数

//该函数返回1是素数,返回0则不是素数
int isPrime(int target) {
    if (target <= 1) return 0;
    for (int i = 2; i*i <= target; i++) {
        if (target % i == 0) return 0;
    }
    return 1;
}

阶乘函数

// 阶乘数很大,一般用long做返回值
long factor(int n){
	long ret=1;
	for(int i=1;i<=n;i++) ret*=i;
	return ret;
}

阶乘求和 sumFactor=1!+2!+3!..+n!

// 阶乘数很大,一般用long做返回值
long sumFactor(int n){
    long sum=0;
    for(int i=1;i<n;i++) sum+=factor(i);
    return sum;
}

冒泡排序

#define chg(a,b) a^=b^=a^=b;
void bubble_sort(int *arr, int len) {
    int i, j;
    for (i = 0; i < len - 1; i++)
        for (j = 0; j < len - 1 - i; j++)
            if (arr[j] > arr[j + 1]) {
                chg(arr[j],arr[j + 1])
                /*或者
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                */
            }
}

使用技巧

#include <stdio.h>
int main() {
    int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };
    int len = sizeof(arr) / sizeof(*arr);
    bubble_sort(arr, len);
    int i;
    for (i = 0; i < len; i++)
        printf("%d ", arr[i]);
    return 0;
}

二分查找


/**
 *  折半查找函数
 *
 *  @param arr   数组
 *  @param len   数组长度
 *  @param value 查找元素
 *
 *  @return 返回查找元素的位置,找不到返回-1
 */
int searchItem(int *arr,int len, int value){
    int low = 0,high = len-1,mid;
    while (low <= high) {
        mid = (low + high)/2;
        if (value > arr[mid]) 
            low = mid+1;
        else if (value < arr[mid])
            high = mid - 1;
        else
            return mid;
    }
    return -1;
}

使用技巧

#include <stdio.h>
int main(int argc, const char * argv[]) {
    //数组必须是有序数组
   int a[10] = {1,2,31,45,52,62,73,86,90,100};
   int len=10;
    //查找86元素
    int l = searchItem(a,len,86);
    printf("loc = %d\n",l);
    return 0;
}

汉诺塔

/**
 *  @param n   个数
 *  @param A   起始地
 *  @param B   借用地
 *  @param C   目的地
 */
void hanoi(int n,char A,char B,char C)
{
    if(n==1)
        printf("Move %d from %c to %c\n",n,A,C);
    else
    {
        hanoi(n-1,A,C,B);
        printf("Move %d from %c to %c\n",n,A,C);
        hanoi(n-1,B,A,C);
    }
    return 0;
}

使用技巧

题目地址 https://www.dotcpp.com/oj/problem2056.html

#include <stdio.h>
int main() {
    hanoi(4,'A','B','C');
    return 0;
}

报数问题


int p[1000]={0};//初始数组 记录人员死亡情况 p[1000]={0}
//设p[n]==0 则人活着,p[n]==1则人死了

int PeopleCount;//scanf 得到实际 玩家数量 PeopleCount

int live=PeopleCount;//记录活人的数量,初始=玩家数量

int now=0;//设定变量 记录现在是第几个玩家进行游戏,开局是第一个人

int code=0;//设定变量,记录目前报数到几,开局是0

int deathCode=3;//设定死亡号码是3

//游戏开始,进入循环,直到live剩下一个玩家
while(live>1){
    //先进行活人判断,并报数.
    if(p[now]==0) {
        code++; //活着就报数
    }
    //报数完了,进行死亡判断
    if(code==deathCode) {
        p[now]=1;//如果数到3,则当前人死亡.
        live--;//活人减少一个
        code=0;//报数变成0,等待下一位玩家报数时,改写成1
    }
    //击鼓传花,移到下一玩家
    now++;
    now%=PeopleCount;
}

亲密数

题目:一个整数 X 的全部因子(包括1,不包括 X 本身)之和等于 Y;并且整数 Y 的全部因子(包括1,不包括 Y 本身)之和等于 X ,则将整数 X 和 Y 称为亲密数。求3000以内的全部亲密数。

#include <stdio.h>
int main() {
    int i, x, y, z;
    for (i = 1; i < 3000; i++) {
        for (y = 0, x = 1; x <= i / 2; x++)
            // 计算x的所有因子之后,保存再y中
            if (0 == (i % x))
                y += x;
        for (z = 0, x = 1; x <= y / 2; x++)
            // 计算y的所有因子之后,保存再z中
            if (0 == (y% x))
                z+= x;
        if (z== i && i < y)
            printf("%4d 的亲密数是 %4d\n", i, y);
    }

    return 0;
}

小球自由下落

题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半,再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?


#include <stdio.h>

int main() {
    float h = 100, s = 100;
    //第一次反弹高度
    h = h / 2;
    for (int i = 2; i <= 10; i++) {
        s = s + 2 * h;
        h = h / 2;
    }
    printf("第10次落地时,共经过%f米,第10次反弹高%f米", s, h);
    return 0;
}

求自然底数e

题目:自然底数 e=2.718281828…,e 的计算公式:e=1+1/1!+1/2!+1/3!+…。当最后一项的值小于 10^-10 时结束。

分析:循环遍历累加求和,并在求和后计算下一项所对应的阶乘。

#include <stdio.h>

int main() {
    double e = 1.0, n = 1.0;
    int i = 1;
    while (1 / n > 1e-10) {
        e += 1 / n;
        i++;
        n = i * n;
    }
    printf("e=%f", e);
    return 0;
}

杨辉三角

题目:杨辉三角的两个腰边的数都是 1,其它位置的数都是上顶上两个数之和。

#include <stdio.h>

int main() {
    int i, j, k, n = 0;
    printf("输入要打印的行数:");
    scanf("%d", &n);

    int a[n+1][n+1];

    printf("%d行杨辉三角如下:\n", n);

    for (i = 1; i <= n; i++)
        a[i][1] = a[i][i] = 1;  // 两边的数令它为1
    for (i = 3; i <= n; i++)
        for (j = 2; j <= i - 1; j++)
            a[i][j] = a[i - 1][j - 1] + a[i - 1][j];  // 除两边的数外都等于上两顶数之和
    for (i = 1; i <= n; i++) {
        for (k = 1; k <= n - i; k++)
            printf("   ");  // 让显示美观,在输出数之前打上合适的空格
        for (j = 1; j <= i; j++)
            printf("%6d", a[i][j]);

        printf("\n");  // 当一行数字输出后换行
    }
    printf("\n");
}
输入要打印的行数:10
10行杨辉三角如下:
                                1
                             1     1
                          1     2     1
                       1     3     3     1
                    1     4     6     4     1
                 1     5    10    10     5     1
              1     6    15    20    15     6     1
           1     7    21    35    35    21     7     1
        1     8    28    56    70    56    28     8     1
     1     9    36    84   126   126    84    36     9     1

回文数

题目:输入一个数,判断它是不是回文数。一个数从左边读和从右边读的结果是一模一样的话就是回文数,例如12321是回文数,12531不是回文数。

分析:判断从左边读和右边读,结果是不是一样。

#include <stdio.h>

int main( ) {
    int num, x, y = 0;
    printf("请输入一位数:");
    scanf("%d", &num);
    x = num;
    while (x > 0) {
        y = y * 10 + x % 10;
        x = x / 10;
    }
    if (num == y) {
        printf("%d是一个回文数", num);
    } else {
        printf("%d不是一个回文数", num);
    }
}

字符串反转

题目:字符串反转,例如 chenPiJavaLib 翻转为 biLavaJiPnehc。

#include <stdio.h>

void reverse(char* s)
{
    // 获取字符串长度
    int len = 0;
    char* p = s;
    while (*p != 0)
    {
        len++;
        p++;
    }

    // 首尾交换字符
    int i = 0;
    char c;
    while (i <= len / 2 - 1)
    {
        c = *(s + i);
        *(s + i) = *(s + len - 1 - i);
        *(s + len - 1 - i) = c;
        i++;
    }
}

int main()
{
    char s[] = "chenPiJavaLib";
    printf("翻转前:%s\n", s);
    reverse(s);
    printf("翻转后:%s", s);
    return 0;
}

演示输出结果如下

翻转前:chenPiJavaLib
翻转后:biLavaJiPnehc

数字排序

题目:输入三个整数 x,y,z,请把这三个数由小到大输出。

分析:先将 x 分别与 y,z 比较,将最小的值赋值到 x。然后 y 和 z 再进行比较,找出第二小的值赋值到 y。最后 x,y,z 就是从小到大的数。

#include <stdio.h>
#define chg(a,b) a^=b^=a^=b;
int main() {
    int x, y, z, t;
    printf("请输入三个数字(逗号隔开):");
    scanf("%d,%d,%d", &x, &y, &z);
    if (x > y) chg (x,y);
    if (x > z) chg (x,z);
    if (y > z) chg (y,z);
    printf("从小到大排序: %d %d %d", x, y, z);
}

演示输出结果如下:

请输入三个数字(逗号隔开):10,2,6
从小到大排序: 2 6 10

九九乘法表

题目:输出九九乘法表。

#include <stdio.h>

int main() {
    int i, j;
    for (i = 1; i < 10; i++) {
        for (j = 1; j <= i; j++) {
            printf("%d*%d=%-3d", i, j, i * j);
        }
        printf("\n");
    }
}

演示输出结果如下:

1*1=1
2*1=2  2*2=4
3*1=3  3*2=6  3*3=9
4*1=4  4*2=8  4*3=12 4*4=16
5*1=5  5*2=10 5*3=15 5*4=20 5*5=25
6*1=6  6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7  7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8  8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9  9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

兔子生崽

题目:一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数总数为多少?假设输出前30个月。

分析:就是斐波那切数列,兔子的个数规律为:1,1,2,3,5,8,13,21…,即下个月是上两个月之和(从第三个月开始)。
版本一

#include <stdio.h>
int Fib(int n){
    return (n == 1 || n == 2) ? 1 : Fib(n - 1) + Fib(n - 2);
}
int main() {
	for(int i=1;i<=30;i++)
		printf("%d",Fib(i));
}

版本二

int main() {
	int fib[50] = { 0 };
	fib[1] = fib[2] = 1;
	for ( int i = 3; i <=30; i++ )
		fib[i] = fib[i - 2] + fib[i - 1];
	for(int i=1;i<=30;i++)
		printf("%d",fib[i]);
	
}

版本三

#include <stdio.h>

int main() {
    int f1 = 1, f2 = 1, i;
    for (i = 1; i <= 15; i++) {
        printf("%12d%12d", f1, f2);
        if (i % 2 == 0) printf("\n");
        f1 = f1 + f2;
        f2 = f1 + f2;
    }

    return 0;
}

演示输出结果如下:

           1           1           2           3
           5           8          13          21
          34          55          89         144
         233         377         610         987
        1597        2584        4181        6765
       10946       17711       28657       46368
       75025      121393      196418      317811
      514229      832040

无重复数字

题目:给你1、2、3、4、5总共五个数字,能组成多少个互不相同且无重复数字的三位数?并且输出。

分析:通过三层循环遍历,遍历所有情况,并排除重复的数字即可。

#include <stdio.h>

int main() {
    int i, j, k; // i,j,k分别代表百位,十位,个位
    int count = 0; // 记录总共不重复的数字的个数
    for (i = 1; i <= 5; i++) {
        for (j = 1; j <= 5; j++) {
            for (k = 1; k <= 5; k++) {
                if (i != k && i != j && j != k) {
                    count++;
                    printf("%d%d%d ", i, j, k);
                    if (0 == count % 10) {
                        printf("\n");
                    }
                }
            }
        }
    }
    printf("不重复的数字的个数为:%d", count);
}
123 124 125 132 134 135 142 143 145 152
153 154 213 214 215 231 234 235 241 243
245 251 253 254 312 314 315 321 324 325
341 342 345 351 352 354 412 413 415 421
423 425 431 432 435 451 452 453 512 513
514 521 523 524 531 532 534 541 542 543
不重复的数字的个数为:60

判断星期几

题目:输入星期几的第一个字母,判断是星期几,如果第一个字母一样,则继续输入第二个字母进行判断。

分析:首先可以通过 switch 语句进行大方向判断,首字母一样再通过 if 语句判断。

#include <stdio.h>

int main() {
    char i, j;
    printf("请输入星期几第一个字母:");
    scanf("%c", &i);
    // scanf("%c",&j) 最后会输入一个换行符,需要使用调这个换行符,避免下一次读取字符时读取到上一次的换行符
    getchar();
    switch (i) {
        case 'm':
            printf("monday\n");
            break;
        case 'w':
            printf("wednesday\n");
            break;
        case 'f':
            printf("friday\n");
            break;
        case 't':
            printf("请输入星期几第二个字母:");
            scanf("%c", &j);
            if (j == 'u') {
                printf("tuesday\n");
                break;
            }
            if (j == 'h') {
                printf("thursday\n");
                break;
            }
        case 's':
            printf("请输入星期几第二个字母:");
            scanf("%c", &j);
            if (j == 'a') {
                printf("saturday\n");
                break;
            }
            if (j == 'u') {
                printf("sunday\n");
                break;
            }
        default :
            printf("error\n");
            break;
    }
    return 0;
}

演示输出结果如下:

请输入星期几第一个字母:t
请输入星期几第二个字母:u
tuesday
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值