C 语言解 常见编程题(上):https://developer.aliyun.com/article/1489149
10 回文数
/* 判断 n 是否为回文数 */ #include <stdio.h> /* 思路: 倒置数值,判断倒置后是否相等 */ int isPalindromes(int n){ // m倒置后的, nn复制一份n用于操作, div 倒置所需乘数 int m = 0, nn = n, div = 1; while (n / div) div *= 10; do { div /= 10; m += nn % 10 * div; } while (nn /= 10); printf("%d----倒置后:%d\n",n,m); if (m == n) return 1; else return 0; } int main(){ printf("%d", isPalindromes(1234321)); return 0; }
测试数据1: 1234321
1234321----倒置后:1234321
1
测试数据1: 12345
12345----倒置后:54321
0
/* 判断 n 是否为回文数 */ #include <stdio.h> /* 思路: 挨个比较 每个位上的 数字 */ int isPalindromes(int n){ int div1 = 1,div2 = 1; //div1 左第一位所需的除数, div2 右第一位所需的除数 int m1,m2; //m1 左第一位的值, m2 右第一位的值 while(n/div1/10) div1 *= 10;; while(div1 > div2){ //对比过 中间一个,停止对比 m1 = n/div1%10; m2 = n/div2%10; printf("%d----%d\n",m1,m2); if(m1!=m2) return 0; div2*=10; div1/=10; } return 1; } int main(){ printf("%d", isPalindromes(1234321)); return 0; }
测试数据1: 1234321
1----1
2----2
3----3
1
测试数据2: 12354321
1----1
2----2
3----3
5----4
0
测试数据3: 1234
1----4
0
11 进制转换
① N进制转10进制
- 由于16进制包括有abc等字符, 需使用字符串形式输入
- 原理:权值相加 , 比如8进制转10进制,如下
/* n进制转10进制 */ #include <stdio.h> //将字符转为所表示的数值, 比如 'a'或'A' 返回 10 int charToint(char c){ if(c>='a') return c-87; else if(c>='A') return c-55; else return c-'0'; } // n进制数num 转为 10进制数值 int numTodec(char *num, int n){ int i,dec=0,k=1; // k 权值 for(i=0; num[i+1];i++); //下标指向末位,从最后位开始 for(;i>=0;i--,k*=n) dec+= k*charToint(num[i]); return dec; } int main(){ char num[20]; //使用字符串形式,兼容16进制 gets(num); printf("%d",numTodec(num,8)); return 0; }
/* n进制转10进制 -- 排除16进制(不考虑字符情况) */ #include <stdio.h> // n进制数num 转为 10进制数值 int numTodec(int num, int n){ int dec=0,k=1; // k 权值 for(;num;k*=n,num/=10) dec+=num%10*k; return dec; } int main(){ int num; scanf("%d",&num); printf("%d",numTodec( num , 8 )); return 0; }
② 10进制转N进制
- 原理: 除N取余, 至0为止
- 比如二进制:
/* 递归 -- 10进制转N进制 */ #include <stdio.h> //输出 10进制数num 的 n进制形式,只输出,不返回值 void decToany(int num,int n){ if(num){ decToany(num/n,n); printf("%c", num%n + (num%n>9?55:'0') ); //兼容16进制,以字符形式输出 } } int main(){ decToany(89,2); return 0; }
12 数组排序
通用函数 – 交换:
//将数组p中的下标分别为a,b的两个数交换 void swap(int a,int b,int p[]){ int temp = p[a]; p[a] = p[b]; p[b] = temp; }
① 冒泡排序
#include<stdio.h> int main(){ int a[10]={3,2,5,8,1,9,7,4,0,6}; // 外层循环代表循环次数(n-1) for (int i = 0; i < 10-1; i++){ // 内层循环代表第j个与第i个比 for (int j = i+1; j <= 10; j++){ if(a[i]>a[j]){ int t=a[i]; a[i]=a[j]; a[j]=t; } } } // 打印结果 for (int i = 0; i <= 9; i++) printf("%d",a[i]); return 0; }
/* 冒泡排序法 将长度为len的数组arr, 以升序排序 */ void bubbling(int *arr,int len){ // 外层循环代表循环次数(n-1) for(int i=0;i<len-1;i++){ int var = 1; //交换标记变量 // 内层循环代表个数(n-1-i) for(int j = 0; j< len - i - 1; j++) if(arr[j]>arr[j+1]) { swap(j,j+1,arr); var = 0; } //print_arr(arr,len); //查看排序过程 if(var) break; //本回合未产生排序,即已排序完成,跳出循环,提高效率(非必须) } }
② 选择排序
#include<stdio.h> int main(){ int a[10]={3,2,5,8,1,9,7,4,0,6}; // 外层循环代表循环次数(n-1) for (int i = 0; i < 10-1; i++){ // 内层循环代表第j个与第i个比 for (int j = i+1; j <= 10; j++){ if(a[i]>a[j]){ int t=a[i]; a[i]=a[j]; a[j]=t; } } } // 打印结果 for (int i = 0; i <= 9; i++) printf("%d",a[i]); return 0; }
/* 选择排序法 升序 最多产生 len(数组长度) 次交换 */ void elect_sort(int *arr,int len){ int i,j,k; for(i=0;i<len;i++){ k=i; //假设当前下标为最小值 for(j = i + 1; j < len; j++) //找最小值下标 if(arr[j]<arr[k]) k = j; if(k!=i) swap(i,k,arr); //将最小值交换到i的位置 } }
//选择排序法1,交换次数较多,但更简洁 void elect_sort_1(int *arr,int len){ for(int i = 0; i < len; i++) for(int j = i + 1; j < len; j++) if(arr[i]>arr[j]) swap(i,j,arr); }
③ 插入排序
//一般插入排序 #include<stdio.h> int main(){ int a[10]={3,2,5,8,1,9,7,4,0,6}; // 循环数组a for (int i = 0; i < 10; i++){ // 循环前面的被插入数组 for (int j = i; j > 0; j--){ if (a[j] < a[j - 1]) { int t = a[j]; a[j] = a[j - 1]; a[j - 1] = t; } } } // 打印结果 for (int i = 0; i <= 9; i++) printf("%d",a[i]); return 0; }
/* 插入排序法 升序 */ void insertt_sort(int *r, int len){ int i, j, k; for (i = 1; i < len; i++){ if (r[i] < r[i - 1]){ k = r[i]; //存入当前待插入的值,否则定位后移 会覆盖 for (j = i - 1; r[j] > k && j>=0; j--) //后移,寻找合适的插入位置 r[j + 1] = r[j]; r[j + 1] = k; //插入 } } }
13 数组反转
// 交换a,b所指向的值 void swap(int *a,int *b){ int temp = *a; *a = *b; *b = temp; } /* 数组反转 传入数组首地址head与长度len */ void reverse(int *head,int len){ int *tail = head+len-1; //tail 尾指针,指向最后一个元素 while(head<tail) swap(head++,tail--); }
14 查找
① 折半查找
- 要求已按 升序 排序好的数组
/* 循环 -- 折半查找 在arr数组 [0,len]之间, 查询num的下标 存在 返回其下标,不存在返回 -1 */ int Halfsearch(int *arr,int len,int num){ int mid,low = 0, high = len - 1; do{ mid = (low + high)/2; printf("\n%d---%d",low,high); if(arr[mid]>num) high = mid - 1; else if(arr[mid]<num) low = mid + 1; else return mid; }while(low <= high); return -1; }
/* 递归 -- 折半查找 在arr数组的下标为 [low,high] 之间查找 num 存在 返回其下标,不存在返回 -1 */ int Halfsearch(int *arr,int low,int high,int num){ if(low>high) return -1; int mid = (low+high)/2; if(arr[mid]>num) return Halfsearch(arr,low,mid-1,num); else if(arr[mid]<num) return Halfsearch(arr,mid+1,high,num); else return mid; }
② 顺序查找
- 对数组无要求 , 不排序也行
- 效率极低
/* 顺序查找 */ int sequential(int *arr,int len,int num){ for(int i = 0; i < len; i++) if(arr[i]==num) return i; return -1; }
- 要求已按 升序 排序好的数组
/* 顺序查找 */ int sequential(int *arr,int len,int num){ for(int i = 0; i < len; i++) if(arr[i]==num) return i; else if(arr[i]>num) break; //找不着 return -1; }
15 字符串函数
① 字符串连接
#include <stdio.h> //将s2连接到s1后面, s2不改变 void strconcat(char *s1,char *s2){ int i,j; for(i = 0;s1[i];i++); //定位到 s1字符串 中的'\0' 位置 for(j = 0;s2[j];i++,j++) s1[i] = s2[j]; s1[i] = '\0'; //结束!!!超级重要!!!超级容易忘!!! } int main(){ char a[100],b[100]; gets(a); gets(b); strconcat(a,b); puts(a); return 0; }
② 比较字符串
#include <stdio.h> //比较字符串s1,s2 , 相等返回0, 正数s1大,反之. int strcomp(char *s1,char *s2){ for(int i=0;s1[i] || s2[i];i++) if(s1[i]!=s2[i]) return s1[i]-s2[i]; return 0; } int main(){ char a[100],b[100]; gets(a); gets(b); printf("%d",strcomp(a,b)); return 0; }
③ 复制字符串
#include <stdio.h> //s2字符串 复制 到s1中 void strcopy(char *s1,char *s2){ int i,j; for(i=0;s2[i];i++) s1[i] = s2[i]; s1[i] = '\0'; //结束!!!超级重要!!!超级容易忘!!! } int main(){ char s1[100],s2[100]; gets(s2); strcopy(s1,s2); puts(s1); }
16 链表
① 动态链表创建
#define LEN sizeof(Player) //类型声明 typedef struct Node{ int num; struct Node *next; } Player; //动态链表创建 Player *creat(){ int temp; //暂存量--判断是否继续输入 Player *head, *p1, *p2; head = p1 = p2 = (Player *)malloc(LEN); printf("请输入你的编号 宝儿:"); scanf("%d", &temp); if (!temp) return NULL; //第一次输入0,返回空表 p2->num = temp; //存入 do { scanf("%d", &temp); // 下一个节点的数据!!! if (!temp) break; //输入0结束输入,不想继续输入=>不用再创建新节点 p1 = (Player *)malloc(LEN); //创建新节点 p1->num = temp; p2->next = p1; //上个节点next指向新的节点 p2 = p1; //p2 也指向新节点 } while (1); p2->next = NULL; //将本节点的next指向NULL,如改为指向head,形成一个圈,循环链表 return head; }
② 链表打印+返回长度
//链表打印+长度 int printLinked(Player *head){ int len = 0; if (!head) printf("这个是空表哦 亲"); else { Player *p = head; while (p){ printf("%d ", p->num); p = p->next; len++; if(p==head) break; //如果是首尾相连的链表 } } return len; }
③ 链表删除节点
//链式链表 删除节点 void del_linked(Player *head,Player *del){ Player *p = head; while(p->next!=del){ //找到待删除节点的上一个节点 p = p->next; if(!p){ printf("\n找不到你要删除的节点呢 亲"); return; } } p->next = del->next; //将其指向下一个节点 }
//循环链表 删除节点 void del_linked(Player *del){ Player *p = del; while(p->next!=del) //找到待删除节点的上一个节点 p = p->next; p->next = del->next; //将其指向下一个节点 }
//删除头结点可在主函数中使用以下语句 head = head -> next;
④ 链表插入
//将add插入到head链表的第n个位置之后, n>=1 链式链表 void insert(Player* head,Player *add,int n){ if(n<1) {printf("非法操作!");return;} if(n>linklegth(head)) n = linklegth(head); //大于最大长度,插入在最后 Player * p = head; while(--n) p=p->next; add->next = p->next; p->next = add; }
17 求方程近似解
① 二分法
#include <stdio.h> #include <math.h> double func(double n){ return 2 * pow(n, 3) - 4 * pow(n, 2) + 3 * n - 6; //待求解函数 } double Solution(double low, double high){ double mid, fm; mid = (low + high) / 2; fm = func(mid); //printf("%f--%f --> %f\n", low, high, mid); //二分过程 if (fm == 0 || (high - low) < 1e-5)//两种情况停止,一是fm刚好等于0(应该不可能),二是精度小于1e-5时,直接返回mid为近似解 return mid; else if (fm < 0) return Solution(mid, high); else if (fm > 0) return Solution(low, mid); } int main(){ printf("%.2f", Solution(-10, 10)); return 0; }
② 牛顿迭代法
#include<stdio.h> #include<math.h> double func(double x){ //举例函数 return 2*x*x*x-4*x*x+3*x-6.0; } double func1(double x){ //导函数 return 6*x*x-8*x+3; } int Newton(double *x,double precision,int maxcyc){ //maxcyc 迭代次数 double x1,x0; int k; x0=*x; for(k=0;k<maxcyc;k++){ if(func1(x0)==0.0){//若通过初值,函数返回值为0 printf("迭代过程中导数为0!\n"); return 0; } x1=x0-func(x0)/func1(x0);//进行牛顿迭代计算 if(fabs(x1-x0)<precision || fabs(func(x1))<precision){//达到结束条件 *x=x1; //返回结果 printf("该值附近的根为:%lf\n",*x); return 1; } else //未达到结束条件 x0=x1; //准备下一次迭代 } printf("迭代次数超过预期!\n"); //迭代次数达到,仍没有达到精度 return 0; } int main(){ double x,precision; int maxcyc; printf("输入初始迭代值x0:"); scanf("%lf",&x); printf("输入最大迭代次数:"); scanf("%d",&maxcyc); printf("迭代要求的精度:"); scanf("%lf",&precision); if(Newton(&x,precision,maxcyc)==1) //若函数返回值为1 ; else //若函数返回值为0 printf("迭代失败!\n"); return 0; }
18 求最大值
① 输入三个数abc,输出其中最大值
#include <stdio.h> int main() { int a, b, c; scanf("%d,%d,%d", &a, &b, &c); if (a >= b && a >= c) printf("max=%d", a); else if (b >= a && b >= c) printf("max=%d", b); else if (c >= a && c >= b) printf("max=%d", c); return 0; }
②求出n个数字的最大值
#include<stdio.h> int main() { int x,max,n; scanf("%d",&n); scanf("%d",&x); max=x; for(int i=0;i<n-1;i++) { scanf("%d",&x); if(max<x) max=x; } printf("%d",max); return 0; }
19 打印图形
①打印菱形
#include<stdio.h> int main() { int m=3,n=1; for (int i = 0; i < 7; i++) { for (int i = 0; i < m; i++) { printf(" ");//前面空格数 } i<3?m--:m++; for (int j = 0; j < n; j++) { printf("%c",'*'); } n=i<3?n+2:n-2; printf("\n"); } return 0; }
测试相关函数
/* 循环 */ #include <stdio.h> int main(){ return 0; }
随机生成数组
#include <time.h> //函数声明: 防止编译系统警告 void srand(unsigned seed); int rand(void); //随机数组 a数组首地址,l数组长度 void getArr(int *a,int l){ int i=0; srand(time(NULL)); //以当前系统时间作为种子 printf("\n你生成的数组为:"); while (i < l) printf("%d,",a[i++] = rand()%(2*l+1)); //限制范围[0,2*l] }
打印数组
void print_arr(int *a,int len){ printf("\n数组为:"); while(len--) printf("%d,",*a++); }
折半查找 测试案例
/*折半查找 */ #include <stdio.h> #include <time.h> //函数声明: 防止编译系统警告 void srand(unsigned seed); int rand(void); //随机数组 a数组首地址,l数组长度 void getArr(int *a,int l){ int i=0; srand(time(NULL)); //以当前系统时间作为种子 printf("你生成的数组为:"); while (i < l) printf("%d,",a[i++] = rand()%(2*l+1)); //限制范围[0,2*l] } //将数组p中的下标分别为a,b的两个数交换 void swap(int a,int b,int p[]){ int temp = p[a]; p[a] = p[b]; p[b] = temp; } /* 插入排序法 升序 */ void insertt_sort(int *r, int len){ int i, j, k; for (i = 1; i < len; i++){ if (r[i] < r[i - 1]){ k = r[i]; //存入当前待插入的值,否则定位后移 会覆盖 for (j = i - 1; r[j] > k && j>=0; j--) //后移,寻找合适的插入位置 r[j + 1] = r[j]; r[j + 1] = k; //插入 } } } /* 在长度为len的arr数组中, 查询num的下标 存在 返回其下标,不存在返回 -1 */ int Halfsearch(int *arr,int len,int num){ int mid,low = 0, high = len - 1; do{ mid = (low + high)/2; printf("\n%d---%d",low,high); if(arr[mid]>num) high = mid - 1; else if(arr[mid]<num) low = mid + 1; else return mid; }while(low <= high); return -1; } void print(int *a,int len){ printf("\n数组为:"); while(len--) printf("%4d",*a++); } int main(){ int arr[10]; getArr(arr,10); insertt_sort(arr,10); print(arr,10); printf("\n%d",Halfsearch(arr,10,8)); return 0; }
数组反转 测试
#include <stdio.h> #include <time.h> //函数声明: 防止编译系统警告 void srand(unsigned seed); int rand(void); //随机数组 a数组首地址,l数组长度 void getArr(int *a,int l){ int i=0; srand(time(NULL)); //以当前系统时间作为种子 printf("\n你生成的数组为:"); while (i < l) printf("%d,",a[i++] = rand()%(2*l+1)); //限制范围[0,2*l] } // 交换a,b所指向的值 void swap(int *a,int *b){ int temp = *a; *a = *b; *b = temp; } /* 数组反转 */ void reverse(int *head,int len){ int *tail = head+len-1; while(head<tail) swap(head++,tail--); } //打印 void print_arr(int *a,int len){ printf("\n数组为:"); while(len--) printf("%d,",*a++); } int main(){ int arr[10]; getArr(arr,10); reverse(arr,10); print_arr(arr,10); return 0; }
你生成的数组为:18,12,0,7,1,19,11,3,13,0,
数组为:0,13,3,11,19,1,7,0,12,18,