西南科技大学814考研一

C语言基础

字节大小

char1 字节
unsigned char1 字节
short2 字节
unsigned short2 字节
int:通常为 4 字节(32 位平台)或 8 字节(64 位平台)
unsigned int:通常为 4 字节(32 位平台)或 8 字节(64 位平台)
long:通常为 4 字节(32 位平台)或 8 字节(64 位平台)
unsigned long:通常为 4 字节(32 位平台)或 8 字节(64 位平台)
long long8 字节
unsigned long long8 字节
float4 字节
double8 字节
long double:通常为 8 字节(32 位平台)或 16 字节(64 位平台)
"i love you"字符串C语言中占多少字节
C语言字符串是字符数组表示,并且结尾用\0
"i love you"={'i',' ','l','o','v','e',' ','y','o','u','\0'}
11
字节

union联合体:不需要补位,找最大

struct结构体:union和数组直接加,其余需要按照补位

补位:char(1),int(4)

char需要补最大的int也就是char占四位总共8位

注意

字节小的可以转换位字节大的,大的转换小的时候向下取整数

输出类型

类型值必须对应打印类型格式

例子

**1:**不同类型进行运算时候,小类型要转换为大类型在进行运算

3+'a'这样的表达式会发生隐式类型转换,'a'会被转换为它对应的ASCII码值97,然后与3相加得到100,这个值是一个整型值。

**2:**变量定义,赋值一定是相同类型

    char a[10]="SERWERTE";//不会报错char b[5];b="wertw";//会报错,string类型给char类型会报错

**3:**字符数组的存储地址

在C语言中,字符数组会以字符串的形式存储,字符串的每个字符会占用1个字节的空间,并且在字符串的末尾会加上一个'\0'作为字符串的结束标志。这个'\0'字符也会被存储在数组中,占用1个字节的空间。

**4:**数组初始化

int a[2][3]={1};
只赋值a[0][0]=1,其余都为0

变量

变量名只能由字母、数字和下划线组成,且必须以字母或下划线开头,不能用特殊字符

自增

int a=1;
int b=++a; //a先加1 a=2 在赋值给b=2
int c=a++; //先赋值给c c=1,a在自增1;a=2

变量后先加

"unsigned char" 是计算机编程中的一种数据类型。它表示一个无符号字符型变量,即只能存储非负整数的字符型变量。

三种结构

  1. 顺序结构:这是C语言中最基本的程序结构,指的是按照代码的先后顺序,逐行执行,不发生跳转。

  2. 选择结构:这种结构用于根据特定条件来执行不同部分的代码。C语言中的选择结构主要由ifelse ifelse语句实现。switch语句也是一种选择结构,用于处理多个可能的情况。

  3. 循环结构:这种结构用于重复执行一段代码,直到满足某个条件时停止。C语言中的循环结构主要由forwhiledo...while循环实现。

    for(开始;判定条件;循环结束执行)

顺序结构

c语言逻辑判断的结果是0或者1

#include <stdio.h>
#include <stdlib.h>int main (){if(3>2&&3%2){printf("%s","进入");}else{printf("%s","不进入");}return 0;
}

循环结构

swith case

满足一个case 里面没有break 会不判断,继续执行下面的case语句

default 默认执行,前面满足有break不会执行,没有会执行

#include <stdio.h>
#include <stdlib.h>int main (){int i;for(i=0;i<2;i++){switch (i) {case 1:printf("%d",i);case 2:printf("%d",i);case 3:printf("%d",3);default:printf("%d",i);}};return 0;
}

注意

x=4
!x=0
在C语言中,!是一个逻辑非运算符,它会对操作数进行逻辑非运算。如果操作数为0,则逻辑非运算的结果为1;如果操作数不为0,则逻辑非运算的结果为0

运算符

运算符表达式:(表达式有几个)一目、二目、三目

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

三目运算符:?:

逗号

int a;
printf("%d",(a=2*5,a*4,a+3));

在这段代码中,使用了逗号运算符。逗号运算符会从左到右依次计算每个表达式,并返回最右侧表达式的值。

首先,a=2*5a 赋值为 10

然后,a*4 计算得到 40,但这个值并没有被赋给任何变量,因此它会被忽略。

最后,a+3 计算得到 13,这是逗号运算符返回的值。

因此,printf("%d",(a=2*5,a*4,a+3)); 会输出 13

逻辑运算符

逻辑运算符的优先级从高到低为:NOT(!) > AND(&&) > OR(||)

&& 有一个为真就是真,前面为真不需要判断后面直接返回真

||全真为真,前面为假直接返回假

int x,y,z,t;    
x=y=z=1;
t=++x || ++y && ++z; 
printf("%d,%d,%d,%d",x,y,z,t);

++xx 自增 1,然后返回 x 的值,所以 ++x 的值为2,然后 t = ++x || ++y && ++z,因为 || 运算符具有短路特性,当 ++x 的值为真(非0)时,后面的 ++y && ++z 将不再执行,直接返回 ++x 的结果,所以 yz 的值没有改变,仍然为1。而 t 的值就是 ++x 的结果,也就是2。所以最后的输出结果为 2,1,1,1

普通函数

isspace是C语言中的一个函数,用于检查给定的字符是否是空白字符。

C语言程序的基本单位是函数。一个C语言程序可以由一个或多个函数组成,其中必须有一个名为main的函数,作为程序的入口点。

交换两个值与指针

错误方法 \textcolor{red}{错误方法} 错误方法

#include <stdio.h>
void f(int *p,int *q){int *c;c=p;p=q;q=c;
}
void tran(int a,int b){int c = a;a=b;b=c;
}
//u.a和u.b共享同一块内存区域。当你先给u.a赋值,然后给u.b赋值,你实际上是在覆盖u.a的值。
int main() {int x=4,y=8;int *p = &x;int *q = &y;printf("交换之前地址%d-%d\n",p,q);printf("交换之前指针对应的值%d-%d\n",*p,*q);f(p,q);printf("交换之后地址%d-%d\n",p,q);printf("交换之后指针对应的值%d-%d\n",*p,*q);printf("x,y之前的值%d-%d\n",x,y);f(&x,&y);printf("x,y之后的值%d-%d\n",x,y);printf("x,y之前的值%d-%d\n",x,y);tran(x,y);printf("x,y之后的值%d-%d\n",x,y);
}

函数f中的参数a和b是整型指针,函数内部对a和b的修改并不会影响到函数外部的p和q。这是因为指针变量在C语言中也是按值传递的,也就是说,函数f接收的是p和q的副本,而非它们本身。

因此,在函数f中交换a和b的值,并不会影响到p和q。所以,主函数main中的打印结果会显示,指针的地址和对应的值都没有发生变化。

指针函数

看后面,就是一个函数

返回函数结果的地址

定义:int *f()

#include <stdio.h>
int *f(){static  int x = 10; //全局使用return &x;          //返回x的地址
}
int main() {int *r = f();   //接受返回地址printf("%d\n",*r);   //打印地址对应的值return 0;
}

函数指针

看后面就是一个指针 ;一个指向函数的指针;在内存空间中存放的是函数的地址;

int add(int a,int b){return a+b;
}
int main() {int (*r)(int a,int b) = &add;   //函数指针接受函数地址int out = r(2,3);         //调用函数printf("%d\n",out);return 0;
}

输出与输入

格式化输出

int x=10,y=3;
printf("%d\n",x%y,x/y);
输出:1

printf函数中,格式化字符串"%d\n"只对应一个输出,即x%y的结果

int a=3366;
printf("│%-08d│",a);

这段代码的目的是打印整数 a,值为 3366,在一个格式化的字符串中,字符串的格式为 “│ %-08d │”。让我们分析一下这个格式化字符串:

  • 是一个字面字符,它会被直接打印出来。
  • % 是一个格式说明符的开始。
  • - 表示左对齐。
  • 0 表示如果数字的位数少于指定的宽度,那么不足的部分会用0填充。
  • 8 表示数字的宽度为8位。
  • d 表示打印一个整数。

所以,这段代码会打印出 │33660000│。整数 a(3366)左对齐,并在右侧用0填充,以确保总共有8位数字。

int x;
x = printf("I am c program\n");
printf("x=%d", x);

首先打印字符串 “I am c program\n”,然后打印变量 x 的值。变量 x 的值就是 printf 函数返回的值,也就是打印的字符数(不包括最后的 ‘\0’ 字符)。

打印与++

#include <stdio.h>
//合并方法
int main() {int a = 1;printf("%d ",a++);//在前先打印,a在+1;return 0;
}
1 
#include <stdio.h>
//合并方法
int main() {int a = 1;printf("%d ",++a);//a先+1,后先打印;return 0;
}
2
#include <stdio.h>int main( ){int arr[] = {2,4,6,8,10,12,14,16};int *p=arr;printf("%d ", *p); //p指针指向数组第一元素printf("%d ", *p+1); //拿到p指针指向元素,该元素的值加1,在打印,p还是指向该元素,该元素的值没有发送变化printf("%d ", *p++); //先打印p指针指向元素的值;p指针往后后移一个printf("%d ", (*p)++); //先打印p指针指向元素的值;设置p指针指向的值在加1printf("%d ",--*p);    //先拿出p指针指向元素的值,设置元素值减1,在打印return 0;
}#include <stdio.h>int main( ){int arr[] = {1,2,3,4,5,6,7,8};int *p=arr + sizeof(arr) / sizeof(int) - 1;*p--+=123; // 双目大于单目 --》*p=*p+123;p是指针p--等同p往前移动一个printf("%d", *p--);//先打印,p在往前移动一个printf("%d", (*p)--);// 先拿着值,打印值,值在减1printf("%d", *--p);//先指针往前移动,在拿着值printf("%d",--*p);//先拿值,值在减1return 0;
}
    #include <stdio.h>int main(){FILE *fp;int i, a[6] = {1, 2, 3, 4, 5, 6}, b[6];fp = fopen("d.dat", "w + b");//将数组中元素写入fp文件指针,数组,每次写入元素存储地址大小,写六个,文件指针fwrite(a, sizeof(int), 6, fp);for (i = 0; i < 6; i++)//将数组中下标为2的元素写入fp文件指针,数组,每次写入元素存储地址大小,写六个,文件指针fwrite(&a[2], sizeof(int), 1, fp);//重置到文件开头rewind(fp);//定位到数组a的第三个元素(索引为2)  fseek(fp, sizeof(int) * 2, SEEK_CUR);// 读取6个整数到数组b  fread(b, sizeof(int), 6, fp);fclose(fp);for (i = 0; i < 6; i++)printf("%d,", b[i]);}
//结果
3,4,5,6,3,3,

数组

什么类型的数组用什么类型指针的接收

int arr[10] = {1,2,3,4,5,6,7,8,9,10,};
//c语言数组名是第一个元素的地址
int *p = arr;
int *p1 = arr+1;//数组第二个元素的地址
int *p2 = arr++;//不允许,编译报错
printf("%d",*p);
return 0;
#include <stdio.h>
#include <stdlib.h>int main (){char arr[20] = {"hello world"};//数组名是第一个元素的地址char *p1=arr;//打印第一个元素printf("%c\n",*arr);printf("%c\n",*p1);//打印第六个元素printf("%c\n",*arr+5);printf("%c\n",*p1+5);//打印第六个元素地址if(arr+5 == p1+5){printf("%s","是一样的结果\n");}else{printf("%s","不是一样的结果\n");}printf("%c\n",arr+5);printf("%c\n",p1+5);return 0;
}

二维数组

#include <stdio.h>
int main (){int n;int array[1000][3];scanf("%d",&n);for(int i = 0;i<n;i++){scanf("%d %d %d",&array[i][0],&array[i][1],&array[i][2]);}printf("输入的数组:\n");for(int i=0;i<n;i++){printf("%d %d %d\n",array[i][0],array[i][1],array[i][2]);}return 0;
}
#include <stdio.h>int main() {int m, n;scanf("%d", &m);scanf("%d", &n);// 声明二维数组int array[m][n];// 获取用户输入的二维数组元素printf("请输入二维数组的元素:\n");for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {scanf("%d", &array[i][j]);}}// 打印二维数组以验证输入printf("\n您输入的二维数组是:\n");for(int i = 0; i < m; i++) {for(int j = 0; j < n; j++) {printf("%d ", array[i][j]);}printf("\n");}return 0;
}

字符串

定义字符串

char *str1 = "Hello, World 1!";
char str2[] = "Hello, World 2!";
printf("%s\n",str1);
printf("%s\n",str2);

字符串的比较

字符数组

if(!*s2) 在 C 语言中是判断 s2 指向的字符是否为 '\0' —— 字符串结束标志。

if(*s2)在C语言中是判断s2指向的字符是否不为'\0'

#include <stdio.h>
int main() {char a[5] ={'a','b','c','d','e'};char *ptr = (char*)(&a+1); //ptr指向a的下一个printf("%c, %c\n",*(a+1),*(ptr-1)); //*(ptr-1) 指向a中最后一个return 0;
}

文件读写

C语言操作文件的标准库是stdio.h库,这个库中包含了用于文件操作的函数,例如:

  1. fopen():打开文件;
  2. fclose():关闭文件;
  3. fgetc():从文件中读取一个字符;
  4. fgets():从文件中读取一行;
  5. fprintf():将格式化的数据写入文件;
  6. fscanf():从文件中读取格式化的数据。
FILE *fp; // 文件指针
char ch; // 读取的字符
// 打开文件,如果文件不存在则创建新文件
fp = fopen("./study.txt", "w+");
// 向文件中写入数据
fprintf(fp, "Hello, world!\n");
// 向文件中写入数据
fputs("This is testing for fputs...\n", fp);
// 将文件指针移到文件开头
fseek(fp, 0, SEEK_SET);
// 从文件中读取数据并输出到控制台
while ((ch = fgetc(fp)) != EOF) {
putchar(ch);
}
// 关闭文件
fclose(fp);

fprintf()fputs() 都是用于向文件中写入数据的 C 语言标准库函数,但它们有一些区别。

区别一:参数不同

fprintf() 函数需要指定格式化字符串以及要写入的数据,可以写入多种类型的数据,并且可以按照指定的格式进行输出。而 fputs() 函数只能写入字符串数据,不能写入其他类型的数据。

区别二:返回值不同

fprintf() 函数返回写入的字符数,如果发生错误则返回负值。而 fputs() 函数返回非负数表示成功,返回 EOF 表示失败。

区别三:功能不同

fprintf() 函数可以将多种类型的数据按照指定的格式写入文件中,可以实现更加复杂的输出操作。而 fputs() 函数只能将字符串写入文件中,功能相对较为简单。

综上所述,fprintf() 函数更加灵活和强大,可以实现更加复杂的输出操作,而 fputs() 函数则适用于简单的字符串写入操作。

fgetc() 是一个 C 语言标准库函数,用于从指定的文件中读取一个字符。

putchar() 函数会将 ch 字符输出到标准输出设备上,并返回输出的字符。如果输出失败,则返回 EOF

例子:

读取文件内容算平均值再写入到文件

#include <stdio.h>int main() {FILE *fp;int num, sum = 0, count = 0;float avg;// 打开文件fp = fopen("data.txt", "r");if (fp == NULL) {printf("无法打开文件!\n");return 1;}// 读取文件中的数字并计算总和和数量while (fscanf(fp, "%d", &num) != EOF) {sum += num;count++;}// 计算平均值avg = (float)sum / count;// 将平均值写入文件fp = fopen("avg.txt", "w");if (fp == NULL) {printf("无法打开文件!\n");return 1;}fprintf(fp, "%.2f", avg);fclose(fp);printf("平均值已写入文件 avg.txt\n");// 关闭文件fclose(fp);return 0;}

例子

#include "stdio.h"
int main(){FILE *fp = NULL;char s[] ="How to tell a story?", ch;fp = fopen("data. txt","w");//将字符串写入文件fprintf(fp,"%s", s);fclose(fp);//读文件fp = fopen("data. txt","r");//移送文件指针fseek(fp,4,SEEK_SET) ;//读取字符判断是不是到文件末尾while ((ch = fgetc(fp)) != EOF){//是t 往前两个设置为结束符,while判断结束跳出循环if(ch =='t'){s[ftell(fp) - 2]='\0';}}printf("%s\n",s);fclose(fp);return 0;
}
  1. ftell(fp):这是一个函数,用于获取文件指针 fp 当前在文件中的位置(以字节为单位)。
  2. ftell(fp) - 2:从 fp 的当前位置往回数 2 个字节。
  3. s[ftell(fp) - 2]:这表示字符数组 s 中位置为 ftell(fp) - 2 的字符。这里有一个假设,即 ftell(fp) - 2 是一个有效的数组索引,不会越界。
  4. s[ftell(fp) - 2] = '\0';:这将 s 数组中位置为 ftell(fp) - 2 的字符设置为 \0(字符串的结束标记)。

联合体

#include <stdio.h>
union {int a;char b;} u;
//u.a和u.b共享同一块内存区域。当你先给u.a赋值,然后给u.b赋值,你实际上是在覆盖u.a的值。
int main() {u.a = 65;u.b = 'a';//覆盖a的值printf("%d\n", u.a);printf("%c\n", u.b);}

算法

算法复杂度

模式匹配:O(m*n)

KMP:O(m+n)

模式匹配

暴力

void bruteForce(char *src, char *target) {  int srcLen = strlen(src);  int targetLen = strlen(target);  for (int i = 0; i <= srcLen - targetLen; i++) {  int j;  for (j = 0; j < targetLen; j++) {  if (src[i + j] != target[j])  break;  }  if (j == targetLen) {  printf("Pattern found at index %d \n", i);  }  }  
}

kmp

i不会回退,当不匹配时,回退j,j回退的值在next数组中找

由匹配字符串构建,next数组

next数组构建原理:

nenxt数组长度与匹配串长度一致,循环匹配字符串,

next数组下标值:在匹配串中从0到下标的子串中,分别求该子串前缀或者后缀,从前缀或者后缀中找出一样的,公共缀的最长长度就是next数组对应的下标值

"ABCDABD"为例,
1.首先需要找出ABCDABD这一串字符串的所有前缀AABABCABCDABCDAABCDABABCDABD2.然后找出每个前缀字符的最长公共前后缀"A"的前缀和后缀都为空集,共有元素的长度为0"AB"的前缀为[A],后缀为[B],共有元素的长度为0"ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0"ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;“ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A”,长度为1;“ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB”,长度为2"ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为03.然后就形成了部分匹配值(prefix table)每个前缀字符的最长公共前后缀放在一起就形成了部分匹配表,也就是:0 0 0 0 1 2 0
//构建next数组
void computeLPSArray(char *pat, int M, int *lps) {  int len = 0;   lps[0] = 0;   int i = 1;  while (i < M) {  if (pat[i] == pat[len]) {  len++;  lps[i] = len;  i++;  } else {  if (len != 0) {  len = lps[len - 1];  } else {  lps[i] = len;  i++;  }  }  }  
}  void KMPSearch(char *pat, char *txt) {  int M = strlen(pat);  int N = strlen(txt);  //匹配字符串构建next数组int lps[M];  computeLPSArray(pat, M, lps);  int i = 0;   int j = 0;   while (i < N) { //匹配上加1if (pat[j] == txt[i]) {  j++;  i++;  }  //找到返回indexif (j == M) {  printf("Found pattern at index %d \n", i - j);  j = lps[j - 1];  //没有找到} else if (i < N && pat[j] != txt[i]) {  //不是第一个没有匹配,回退jif (j != 0)  j = lps[j - 1];  //第一个找到,直接加else  i = i + 1;  }  }  
}

数组合并

两个有序数组合并一个有序数组

#include <stdio.h>
//合并方法
int main() {int a[] = {1,3,5,7,9};int asize= sizeof(a)/ sizeof(a[0]);int b[] = {2,4,6,8,10};int bsize= sizeof(b)/ sizeof(b[0]);int r[] ={0,0,0,0,0,0,0,0,0,0};int rsize=asize+bsize;//合并ab到int i=0,j=0,l=0;while(i<=asize&&j<=bsize){if(a[i]<=b[j]){r[l]=a[i];i=i+1;}else{r[l]=b[j];j=j+1;}l=l+1;}for(int i=0;i<rsize;i++){printf("%d ",r[i]);}return 0;
}

动态规划

未知的问题用已知的解决

定义dp数组,判断数组里面是否有,有就取,没有就放在数组

斐波那契数列

int n =10;
int dp[n+1];
dp[0]=0;
dp[1]=1;
int l = sizeof(dp)/sizeof (dp[0]);
for (int j = 2; j <=l ; ++j) {dp[j]=dp[j-1]+dp[j-2];
}
for (int i = 0; i < l; ++i) {printf("%d ",dp[i]);
}
printf("%d ",dp[n-1]);

走楼梯

dp[1] = 1;  
dp[2] = 2;  
for (int i = 3; i <= n; i++) {  p[i] = dp[i - 1] + dp[i - 2];  
}  

最长连续递增子序列

#include <stdio.h>
int max(int a,int b){if(a>b){return a;}else{return b;}
}
int main() {int arr[] = {3,2,5,7,1,4,10,8,9};int len=sizeof(arr)/ sizeof(arr[0]);int dp[len]; //定义dp数组for (int i = 0; i < len; ++i) { //初始化dp[i]=1;};for (int i = 0; i < len; ++i) {int temp = arr[i];//i位置上的元素for (int j = i; j >0 ; j--) {if(arr[j]<temp && i==j+1){  //在i之前找到比这个小,并且是连续的dp[i]=dp[j]+1; //以i位置结尾的最长递增子序列的长度是j的加1(i本身)break;}}}int result = 1;for (int i = 0; i < len; ++i) { //初始化result=max(result,dp[i]);};printf("最长递增子序列的长度:%d",result);return 0;
}

贪心

最优解决:程序通过贪心算法计算出需要使用多少个硬币找零,收银员总是先给最大的硬币

也就是说要找的零钱张数最少

#include <stdio.h>
int found(int a[],int mon,int len,int dp[]){//要找给顾客的钱为0;就退出循环if(mon == 0){return 0;}else{for (int i = 0; i < len; ++i) {if(a[i]>=mon){//先找最大dp[i-1]=mon/a[i-1];mon=mon%a[i-1];len=i;break;}}return found(a,mon,len,dp);}
}
int main() {//若干零钱int arr[] = {1,2,5,10,20,50,100};int mon = 37;//实际要给顾客找零int len = sizeof(arr)/ sizeof(arr[0]);int dp[len];//对应零钱找的张数for(int i=0;i<len;i++){dp[i]=0;}found(arr,mon,len,dp);for(int i=0;i<len;i++){printf("%d张%d\n",dp[i],arr[i]);}return 0;
}

背包

01背包

#include <stdio.h>
int max(int a, int b) {return a > b ? a : b;
}int knapsack(int w[], int v[], int n, int W) {int i, j;//构建二维数组:行放入物品种类0-n号物品种类,列是背包对应的重量,ij是背包对应的最大价值int dp[n+1][W+1];// 初始化dp数组--背包重量为0,其最大价值为0;背包种类为0;其最大价值为0for (i = 0; i <= n; i++) {for (j = 0; j <= W; j++) {if (i == 0 || j == 0) {dp[i][j] = 0;} else {dp[i][j] = -1;}}}// 动态规划求解for (i = 1; i <= n; i++) {for (j = 1; j <= W; j++) {if (j < w[i-1]) {//当前背包重量小于物品重量dp[i][j] = dp[i-1][j]; //背包最大价值是背包重量-1对应的最大价值} else {//当前背包重量可以放该物品//不放,背包最大价值还是当前物品重量-1对应的价值//放,背包最大价值是当前放入物品重量对应的价值+没放之前背包对应的最大价值dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i-1]] + v[i-1]);}}}return dp[n][W];
}int main() {int w[] = {2, 1, 3}; // 物品的重量int v[] = {4, 2, 3}; // 物品的价值int W = 5; // 背包的总重量int n = sizeof(w) / sizeof(w[0]); // 物品的数量int max_value = knapsack(w, v, n, W); // 求最大价值printf("最大价值为:%d\n", max_value);return 0;}

回溯

DFS:深度优先搜索借鉴递归、栈实现

BFS:广度优先搜索借鉴队列实现

DFS 递归判断迷宫有出路没有

#include <stdio.h>
#define M 5
#define N 5
//迷宫出口
int a=3;int b=4;
//迷宫
//0是没有访问过
//-1墙
//2访问过
int maze[M][N] = {{0, 0, 0, 0, 0},{0, -1, -1, 0, -1},{0, -1, 0, 0, -1},{0, -1, -1, -1, -1},{-1, 0, 0, 0, 0}};
//找出路
int find_path(int m,int n){//当前是不是目标,是:返回找到出口if(m==a && n==b){maze[m][n]=2;return 1;}//刚开始一定可以进去;标记走过maze[m][n]=2;//在迷宫内并且可以走//上if(0<=m-1&&m-1<=M&&maze[m-1][n]==0){return find_path(m-1,n);}//右else if(0<=n+1&&n+1<=M&&maze[m][n+1]==0){return find_path(m,n+1);}//下else if(0<=m+1&&m+1<=M&&maze[m+1][n]==0){return find_path(m+1,n);}//左else if(0<=n-1&&n-1<=M&&maze[m][n-1]==0){return find_path(m,n-1);}else {return 0;}}
int main() {if(find_path(0,0)){printf("有出路");}else{printf("没有出路");}//找出路}

BFS长草问题–BFS借助队列

【问题描述】
小明有一块空地,他将这块空地划分为 n 行 m 列的小块,每行和每列的长度都为 1小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。
这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,小块空地都将变为有草的小块。请告诉小明,k 个月后空地上哪些地方有草。
【输入格式】
输入的第一行包含两个整数 n, m。
接下来 n 行,每行包含 m 个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为 g,表示种了草。
接下来包含一个整数 k。
【输出格式】
输出 n 行,每行包含 m 个字母,表示 k 个月后空地的状态。如果为小数点,表示为空地,如果字母为 g,表示长了草。
【样例输入】
4 5
.g...
.....
..g..
.....
2
【样例输出】
gggg.
gggg.
ggggg
.ggg.
#include<stdio.h>
#include <stdlib.h>
#define M 6
#define N 6
// 定义链表节点结构体
typedef struct node {int data;struct node* next;
} Node;
// 定义队列结构体
typedef struct queue {Node* front; // 队头指针Node* rear; // 队尾指针int size; // 队列长度
} Queue;// 初始化队列
void initQueue(Queue* q) {q->front = NULL;q->rear = NULL;q->size = 0;
}// 判断队列是否为空
int isEmpty(Queue* q) {return q->front == NULL;
}// 获取队列长度
int getLength(Queue* q) {return q->size;
}// 入队操作
void enqueue(Queue* q, int data) {Node* newNode = (Node*)malloc(sizeof(Node)); // 创建新节点newNode->data = data;newNode->next = NULL;if (isEmpty(q)) { // 如果队列为空,队头和队尾都指向新节点q->front = newNode;} else { // 否则,将新节点插入到队尾,并更新队尾指针q->rear->next = newNode;}q->rear = newNode; // 更新队尾指针q->size++; // 队列长度加1
}// 出队操作
int dequeue(Queue* q) {if (isEmpty(q)) { // 如果队列为空,返回错误码-1return -1;}int data = q->front->data; // 取出队头节点的数据Node* temp = q->front; // 用临时变量保存队头节点地址q->front = q->front->next; // 将队头指针指向下一个节点if (q->front == NULL) { // 如果队头指针为空,说明队列已空,将队尾指针也置为空q->rear = NULL;}free(temp); // 释放队头节点的内存空间q->size--; // 队列长度减1return data; // 返回取出的数据}
//第几个月后
int k = 1;
//草地
char c[M][N]={{'.','.','.','.','.','.'},{'.','.','.','.','g','.'},{'.','g','.','.','.','.'},{'.','.','.','.','.','.'},{'.','.','g','.','.','.'},{'.','.','.','.','.','.'}};
//bfs长草
void bfs(Queue *x,Queue *y){//初始化:长草地址加入队列for (int i = 0; i < M; ++i) {for (int j = 0; j < N ; ++j) {if(c[i][j]=='g'){enqueue(x,i);enqueue(y,j);}}}//队列长度大于0while(getLength(x)>0){//出队int qx = dequeue(x);int qy = dequeue(y);//循环拿到下一步//移动方向int mv[4][2]={{0,1},{1,0},{0,-1},{-1,0}};for(int i=0;i<4;i++){int *temp = mv[i];int tx = qx+temp[0];int ty = qy+temp[1];//如果下个方向可以长草if(0<=tx&&tx<M && c[tx][ty]=='.'&&0<=ty&&ty<N){//标记长草c[tx][ty]='g';//坐标加入队列enqueue(x,tx);enqueue(y,ty);}}}
}
int main(){printf("初始化草地:\n");for (int i = 0; i < M; ++i) {for (int j = 0; j < N ; ++j) {printf("%c ",c[i][j]);}printf("\n");}//创建队列Queue x;initQueue(&x); // 初始化队列Queue y;initQueue(&y); // 初始化队列//长草bfs(&x,&y);printf("%d个月草地长草后:\n",k);for (int i = 0; i < M; ++i) {for (int j = 0; j < M ; ++j) {printf("%c ",c[i][j]);}printf("\n");}return 0;
}

例子

数组移位置

编写一个程序,有 n 个整数,要求你编写一个函数使其向右循环移动 m 个位置

输入:输入 n m 表示有 n 个整数,移动 m 位

输出:输出移动后的数组

例如:

输入:
10 5
1 2 3 4 5 6 7 8 9 0

输出:
6 7 8 9 0 1 2 3 4 5

    #include <stdio.h>int main(){int a[] ={1,2,3,4,5,6,7,8,9,0};int l=sizeof(a)/sizeof (int);int b[l];int index;for(int i=0;i<l;i++){int now = (i+5)%l;b[now]=a[i];}for(int i=0;i<l;i++){printf("%d ",b[i]);}return 1;}

判断字符数组大小

例如:

输入:
abc
abd

输出:

abd

#include<stdio.h>
int strcmp(char *p1,char *p2){//不为0,并且p1对应元素=p2对应元素 进入循环while (*p1 && (*p1 == *p2)){p1++;p2++;}return *(const unsigned char *)p1 - *(const unsigned char *)p2;}
int main()
{char a[]="abc",b[]="abd";if(strcmp(a,b)>0)printf("%s", a);elseprintf("%s", b);return 0;
}

走楼梯

题目描述

现有一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用,你选择从下标为 0 或下标为 1 的台阶开始爬楼梯。请你计算并返回达到楼梯顶部的最低花费。
编程要求

此题已给出部分代码,你可在/begin-end/之间进行编码,让程序通关。
输入输出格式

输入格式
第一行输入一个整数 costSize;
第二行输入数组 cost。
输出格式
输出一个整数。
输入输出样例1

输入
4
10 21 13 16
输出
23
输入输出样例2

输入
5
1 2 3 4 5
输出
6
说明提示

2≤costSize≤1000
1≤cost[i]≤100


获得二维数组中B、b的个数

#include <stdio.h>int cnt(char *s) {int i = 0;int c = 0;// 如果字符串非空if (s)while (*(s + i)) {if (s[i] == 'B' || *(s + i) == 'b') {c++;}i++;}return c;
}int main() {int c = 0;char s[][6] = {"book", "BBS", "bee", "table"};// 获取数组长度int len = sizeof(s) / sizeof(s[0]);// 遍历数组中的每个字符串,并计算'B'或'b'的个数for (int i = 0; i < len; i++) {//对于二维数组 s[0]是一个指针,指向bookc += cnt(s[i]);}printf("%d\n", c);return 0;
}

函数指针

#include <stdio.h>
int* (*funcpl[2])(int*, int*,int*);
int (*funcp2[2])(int*, int*);
int* max(int *a, int *b,int *c){int*x=*a>*b?a:b;return *x >*c ?x:c;
}
int* min(int *a, int *b, int *c){int *x=*a<*b?a:b;return*x<*c?x:c;
}
int mul(int *a,int *b){return *a * *b;
}
int div(int *a, int *b){//判断b是不是0;不是返回a/b;是返回-1return *b?*a/(*b):-1;
}int main(){int a = 10,b= 20,c = 30, result = 0;funcpl[0] = max;funcpl[1] = min;funcp2[0] = mul;funcp2[1] = div;for(int j= 0;j< 2;){result +=(*funcp2[j++])((*funcpl[0])(&a,&b,&c),(*funcpl[1])(&a, &b,&c));}printf("%d\n",result);return 1;
}

回文数

#include <stdio.h>int is_palindrome(int num) {int reversed = 0;int temp = num;/**********FOUND**********/while (temp != 0) {reversed = reversed * 10 + temp % 10;/**********FOUND**********/temp=temp/10;}if (num == reversed) {return 1;} else {return 0;}
}int main() {int num = 12321;if (is_palindrome(num)) {printf("%d is a palindrome.\n", num);} else {printf("%d is not a palindrome.\n", num);}return 0;
}

交换a,b的值

#include <stdio.h>/**********FOUND**********/
void swap(int *a, int *b) {  // 错误:传递的是值的拷贝,无法实现交换/**********FOUND**********/int temp = *a;/**********FOUND**********/*a = *b;/**********FOUND**********/*b = temp;
}int main() {int x = 10;int y = 5;printf("Before swap: x = %d, y = %d\n", x, y);/**********FOUND**********/swap(&x, &y);printf("After swap: x = %d, y = %d\n", x, y);return 0;
}

自增与逻辑

C语言中!=0的整数为ture,==0为false

#include <stdio.h>int main(){int a = 1;int b=-2;for( ; a-- && b++; ){printf("%d ,%d,", a, b);}printf("%d ,%d,", a, b);return 1;
}

注意:a–&&

先拿a的值,判断true还是false,与&&右边比较,a在减少1

函数

函数的形参和实参分别占用不同的存储单元

若指针指向变量,则可以向指针所指内存单元写入数据

可以取变量的地址赋值给同类型的指针变量

printf("%d\n", strlen("\t"\\n'\065\08AB"));\t 代表一个制表符 (tab)。\\n 代表一个换行符,因为 \ 被转义了,所以它表示一个普通的换行。' 是一个单引号字符。\065 是八进制表示的字符,其对应的十进制是 53,代表字符 S。\08AB 这里有点问题,因为 \08A 和 B 都被解释为独立的字符。八进制08A对应的是一个不可打印的控制字符,而B就是一个普通的字母。两个字符

求数组中最大可以构成的等差数组的组数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//判断素数
int isPrime(int n){if(n<2){return 1;}else{for(int i = 2;i<n;i++){if(n%i==0){return 0;}}return 1;}
}
// 查找等差数列的函数
int findArithmeticSequences(int arr[], int n) {if (n < 3) return 0; // 如果数组元素少于3, 则不可能有等差数列int maxCount = 0; // 记录最大的等差数列组数  1 2 3 4 最大组数就有三组(1,2;2,3;3,4)for (int i = 0; i < n - 2; i++) { // 遍历数组int count = 0; // 计数器,记录当前起始点的等差数列数量int diff = arr[i + 1] - arr[i]; // 计算当前起始点的公差// 检查等差数列for (int j = i + 1; j < n - 1; j++) {if (arr[j + 1] - arr[j] == diff) {count++; // 找到一个等差数列,增加计数器j++; // 跳过这个元素,因为下一个元素可能与当前元素形成新的等差数列}}maxCount = count > maxCount ? count : maxCount; // 更新最大的等差数列组数}return maxCount + 1; // 返回最大的等差数列组数(+1是因为我们需要至少3个元素来形成一个等差数列)
}int main() {int a=1,b=11;int max_len = 0; // 最长等差数列的长度int temp[b-a];//数组长度int index=0;//获取之间的素数数组for (int i = a; i <= b; i++) {if (isPrime(i)==0){continue; // 如果i不是质数,跳过}else{temp[index]=i;index++;}};int r = findArithmeticSequences(temp,index);printf("%d",r);return 0;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/190035.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go zero手把手教你入门案例

一、入门案例 1、在黑窗口上安装 go install github.com/zeromicro/go-zero/tools/goctllatest2、使用goland创建一个项目 3、在项目中安装依赖 go get -u github.com/zeromicro/go-zerolatest4、模拟创建一个user的项目 goctl api new user5、安装依赖包 go mod tidy6、补充代…

vue项目本地开发完成后部署到服务器后报404

vue项目本地开发完成后部署到服务器后报404是什么原因呢&#xff1f; 一、如何部署 前后端分离开发模式下&#xff0c;前后端是独立布署的&#xff0c;前端只需要将最后的构建物上传至目标服务器的web容器指定的静态目录下即可 我们知道vue项目在构建后&#xff0c;是生成一系…

Guitar Pro2024吉他软件好不好用?

吉他&#xff0c;这把魔幻的弹奏利器&#xff0c;既需要技术&#xff0c;又需要技巧。 是的&#xff0c;它不会自己跳入你的手中&#xff0c;除非你敲对了密码&#xff1a;练习&#xff01; 今天就来看看&#xff0c;大家是不是已经找到了快速掌握吉他的门道呢&#xff1f; …

【DataV可视化工具详解】

文章目录 前言一、什么是DataV&#xff1f;二、主要特点1. 强大的图表库2. 灵活的数据接入3.实时数据展示4. 易于定制的仪表盘 三、应用场景1.业务监控与分析2.大屏展示3.数据洞察与决策支持 四、例图总结我是将军&#xff0c;我一直都在&#xff0c;。&#xff01; 前言 今天…

Vatee万腾的科技征程:Vatee数字化创新的前沿探讨

在Vatee万腾的科技征程中&#xff0c;我们目睹了一场数字化创新的引领之旅&#xff0c;探讨了Vatee在科技前沿的独到见解。Vatee万腾不仅仅是一家科技公司&#xff0c;更是一支前行不辍的冒险队伍&#xff0c;通过不断突破自我&#xff0c;探索未知领域&#xff0c;引领着数字化…

Vue3 动态设置 ref

介绍 在一些场景&#xff0c;ref设置是未知的需要根据动态数据来决定&#xff0c;如表格中的input框需要我们主动聚焦&#xff0c;就需要给每一个input设置一个ref&#xff0c;进而进行聚焦操作。 Demo 点击下面截图中的编辑按钮&#xff0c;自动聚焦到相应的输入框中。 &…

UnoCss(原子化css引擎) 让你的开发更轻松愉快

什么是原子化CSS&#xff0c;UnoCSS又是什么&#xff0c;对此有疑问的推荐看下antfu的这篇文章——重新构想原子化 CSS (antfu.me) 相信看完这篇文章的你也会跟我一样热衷于UnoCSS. 介绍 今天介绍一个CSS开发利器 UnoCSS , 是一个具有高性能且极具灵活性的即时原子化 CSS 引擎…

《洛谷深入浅出基础篇》——P3405 citis and state ——哈希表

上链接&#xff1a;P3405 [USACO16DEC] Cities and States S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3405 上题干&#xff1a; 题目描述 Farmer John 有若干头奶牛。为了训练奶牛们的智力&#xff0c;Farmer John 在谷仓的墙上放了一…

ceph学习笔记

ceph ceph osd lspoolsrbd ls -p testpool#查看 ceph 集群中有多少个 pool,并且每个 pool 容量及利 用情况 rados dfceph -sceph osd tree ceph dfceph versionsceph osd pool lsceph osd crush rule dumpceph auth print-key client.adminceph orch host lsceph crash lsceph…

python计算脚长 青少年电子学会等级考试 中小学生python编程等级考试一级真题答案解析2022年9月

目录 python字符串输出 一、题目要求 1、编程实现 2、输入输出 二、解题思路 1、案例分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python字符串输出 2022年9月 python编程等级考试一级编程…

基于Zemax的高能激光发射系统的扩束系统设计

关键词&#xff1a;高功率激光发射系统&#xff1b;扩束系统 1 引言 高功率激光发射系统是强激光空间传输系统中不可缺少的装置。对高功率激光发射系统的研究一直是激光应用领域的关键技术问题。高功率激光发射系统通常由准直系统、导光光路系统和扩束系统组成,光学系统要求具…

【docker】Docker网络与iptables

Docker能为我们提供很强大和灵活的网络能力&#xff0c;很大程度上要归功于与iptables的结合。在使用时&#xff0c;你可能没有太关注到 iptables在其中产生的作用&#xff0c;这是因为Docker已经帮我们自动的完成了相关的配置。 iptables在Docker中的应用主要是用于网络流量控…