C语言编程100例题_第1页
C语言编程100例题_第2页
C语言编程100例题_第3页
C语言编程100例题_第4页
C语言编程100例题_第5页
已阅读5页,还剩20页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C语言经典编程100例说明本教程按题目类型分为10个部分,每部分10个例题,覆盖C语言基础语法、数组字符串、算法、数据结构等核心知识点,既适合初学者入门练习,也能帮助进阶者巩固基础。所有程序均兼容C99及以上标准,编译时可使用命令:gccexample.c-std=c99-oexample执行编译,确保代码正常运行。每个例题包含题目要求、完整代码及核心解析,重点标注关键语法和逻辑思路,助力快速掌握编程技巧。第一部分:基础语法(例1-10)例1:HelloWorld(最基础C程序)题目:编写程序,输出"Hello,World!",熟悉C程序的基本结构。c

#include<stdio.h>

intmain(void){

printf("Hello,World!\n");//输出指定字符串,\n表示换行

return0;//程序正常结束,返回0

}解析:C程序的入口是main()函数,printf()是标准输出函数,需包含头文件stdio.h;return0表示程序正常退出,是main函数的标准返回值。这是最基础的C程序,用于熟悉程序的基本框架。例2:交换两个整数(不借助第三变量)题目:从键盘输入两个整数,不使用临时变量,利用异或运算实现两数交换并输出结果。c

#include<stdio.h>

intmain(void){

inta,b;

printf("请输入两个整数:");

scanf("%d%d",&a,&b);//读取键盘输入的两个整数

//利用异或运算交换两数,异或特性:a^a=0,a^0=a

a=a^b;

b=a^b;//等价于b=(a^b)^b=a^(b^b)=a^0=a

a=a^b;//等价于a=(a^b)^a=b^(a^a)=b^0=b

printf("交换后:a=%d,b=%d\n",a,b);

return0;

}解析:异或运算(^)的核心特性是“相同为0,不同为1”,利用该特性可实现无临时变量的交换;scanf()函数用于读取输入,&符号表示取变量地址,是输入函数的必要参数。例3:递归实现阶乘题目:从键盘输入一个正整数,使用递归函数计算该数的阶乘并输出。c

#include<stdio.h>

//递归函数声明:计算n的阶乘

longlongfactorial(intn){

returnn<=1?1:n*factorial(n-1);//递归终止条件:n<=1时返回1

}

intmain(void){

intn;

printf("请输入一个整数:");

scanf("%d",&n);

//调用递归函数,longlong类型避免阶乘值溢出

printf("%d的阶乘是%lld\n",n,factorial(n));

return0;

}解析:递归函数的核心是“自身调用自身”,需明确终止条件(n<=1返回1),否则会出现死循环;阶乘值增长较快,使用longlong类型(64位整数)可避免小范围输入时的溢出问题。例4:迭代实现斐波那契数列题目:从键盘输入斐波那契数列的项数n,使用迭代方式输出前n项斐波那契数(斐波那契数列:0,1,1,2,3,5...,前两项为0和1,后续每项为前两项之和)。c

#include<stdio.h>

intmain(void){

intn;

printf("请输入斐波那契数列项数:");

scanf("%d",&n);

longlonga=0,b=1,temp;//a存储当前项,b存储下一项,temp临时变量

printf("斐波那契数列:\n");

for(inti=0;i<n;i++){

printf("%lld",a);

temp=a+b;//计算下一项

a=b;//更新当前项为原来的下一项

b=temp;//更新下一项为新计算的项

}

printf("\n");

return0;

}解析:迭代方式相比递归,效率更高、无栈溢出风险;使用longlong类型存储数列项,避免项数较多时出现溢出;循环中通过临时变量temp保存中间结果,实现两项的更新。例5:判断一个数是否为质数题目:从键盘输入一个整数,判断该数是否为质数(质数:大于1的整数,除了1和自身外,无法被其他整数整除)。c

#include<stdio.h>

#include<math.h>

#include<stdbool.h>

//判断质数的函数,返回bool类型(true为质数,false非质数)

boolisPrime(intn){

if(n<2)returnfalse;//小于2的数不是质数

//优化:只需判断到sqrt(n),因为大于sqrt(n)的因子必与小于sqrt(n)的因子成对出现

for(inti=2;i<=(int)sqrt(n);i++){

if(n%i==0)//能被i整除,说明不是质数

returnfalse;

}

returntrue;

}

intmain(void){

intn;

printf("请输入一个整数:");

scanf("%d",&n);

printf("%d%s质数。\n",n,isPrime(n)?"是":"不是");

return0;

}解析:质数判断的核心是“排除法”,通过循环判断该数是否能被2到sqrt(n)之间的数整除;引入math.h头文件使用sqrt()函数,stdbool.h头文件使用bool类型,使代码更简洁易读。例6:输出指定范围内的所有质数题目:从键盘输入两个整数(下界lower和上界upper),输出该区间内的所有质数。c

#include<stdio.h>

#include<math.h>

#include<stdbool.h>

//复用判断质数的函数

boolisPrime(intn){

if(n<2)returnfalse;

for(inti=2;i<=(int)sqrt(n);i++){

if(n%i==0)

returnfalse;

}

returntrue;

}

intmain(void){

intlower,upper;

printf("请输入下界和上界:");

scanf("%d%d",&lower,&upper);

printf("区间[%d,%d]内的质数有:\n",lower,upper);

//遍历区间内的所有数,逐一判断是否为质数

for(inti=lower;i<=upper;i++){

if(isPrime(i)){

printf("%d",i);

}

}

printf("\n");

return0;

}解析:复用例5中的isPrime()函数,减少代码冗余;通过for循环遍历指定区间,对每个数调用质数判断函数,符合“模块化编程”思路,提高代码可复用性。例7:求两个正整数的最大公约数和最小公倍数题目:从键盘输入两个正整数,利用欧几里得算法(辗转相除法)求它们的最大公约数(GCD),并根据最大公约数求最小公倍数(LCM)。c

#include<stdio.h>

//欧几里得算法求最大公约数:gcd(a,b)=gcd(b,a%b),终止条件b=0

intgcd(inta,intb){

returnb==0?a:gcd(b,a%b);

}

intmain(void){

inta,b;

printf("请输入两个正整数:");

scanf("%d%d",&a,&b);

intg=gcd(a,b);

//最小公倍数公式:LCM(a,b)=(a*b)/GCD(a,b),先除后乘避免溢出

intlcm=a/g*b;

printf("最大公约数:%d\n",g);

printf("最小公倍数:%d\n",lcm);

return0;

}解析:欧几里得算法是求最大公约数的高效方法,核心逻辑是“大数对小数取余,循环迭代,直到余数为0”;最小公倍数通过公式计算,先除以最大公约数再乘另一个数,可避免两个大数相乘导致的溢出。例8:反转一个整数题目:从键盘输入一个整数,将其各位数字反转(如输入123,输出321;输入-456,输出-654),并输出反转后的整数。c

#include<stdio.h>

intmain(void){

intn,rev=0;//rev存储反转后的整数

printf("请输入一个整数:");

scanf("%d",&n);

//循环提取n的最后一位,拼接至rev中

while(n!=0){

rev=rev*10+n%10;//取出最后一位,拼接到rev末尾

n/=10;//去掉n的最后一位

}

printf("反转后的整数为:%d\n",rev);

return0;

}解析:核心逻辑是通过取余(%10)提取整数的最后一位,通过整除(/10)去掉最后一位,循环迭代直到整数变为0;该方法自动处理负数,因为负数取余和整除的结果仍为负数,无需额外判断。例9:判断一个整数是否为回文数题目:从键盘输入一个整数,判断该数是否为回文数(回文数:正读和反读完全相同,如12321、1221,负数不是回文数)。c

#include<stdio.h>

intmain(void){

intn,original,rev=0;

printf("请输入一个整数:");

scanf("%d",&n);

original=n;//保存原始值,用于后续对比

//反转整数(复用例8的反转逻辑)

while(n!=0){

rev=rev*10+n%10;

n/=10;

}

//对比原始值和反转后的值,且原始值非负(负数不是回文数)

if(original==rev&&original>=0)

printf("是回文数。\n");

else

printf("不是回文数。\n");

return0;

}解析:基于整数反转的逻辑,先保存原始整数,反转后与原始值对比;需注意负数一定不是回文数(如-121反转后为-121,但负号位置不同,不符合回文定义),因此增加original>=0的判断。例10:判断三位数的阿姆斯壮数(水仙花数)题目:从键盘输入一个三位数,判断该数是否为阿姆斯壮数(水仙花数:一个n位数,其各位数字的n次方之和等于该数本身,三位数即百位³+十位³+个位³=本身)。c

#include<stdio.h>

#include<math.h>

intmain(void){

intn,original,digit,sum=0;

printf("请输入一个三位数:");

scanf("%d",&n);

//先判断输入是否为三位数

if(n<100||n>999){

printf("输入不是三位数!\n");

return1;//异常退出,返回非0值

}

original=n;

//提取每一位数字,计算立方和

while(n!=0){

digit=n%10;//提取当前位数字

sum+=pow(digit,3);//累加当前位的立方

n/=10;

}

//对比立方和与原始值

if(sum==original)

printf("%d是阿姆斯壮数(水仙花数)。\n",original);

else

printf("%d不是阿姆斯壮数(水仙花数)。\n",original);

return0;

}解析:先判断输入是否为三位数,避免无效输入;通过循环提取每一位数字,利用pow()函数计算立方(需包含math.h头文件),累加后与原始值对比,符合阿姆斯壮数的定义。第二部分:字符串与数组(例11-20)例11:统计字符串中字母、数字、空格及其他字符的个数题目:从键盘输入一个字符串,统计字符串中大写字母、小写字母、数字、空格及其他字符的数量,分别输出统计结果。c

#include<stdio.h>

#include<string.h>

intmain(void){

charstr[100];//定义字符数组存储字符串,长度可调整

intupper=0,lower=0,digit=0,space=0,other=0;

intlen;

printf("请输入一个字符串:");

gets(str);//读取字符串(包含空格)

len=strlen(str);//获取字符串长度

//遍历字符串的每一个字符

for(inti=0;i<len;i++){

if(str[i]>='A'&&str[i]<='Z'){

upper++;//大写字母

}elseif(str[i]>='a'&&str[i]<='z'){

lower++;//小写字母

}elseif(str[i]>='0'&&str[i]<='9'){

digit++;//数字

}elseif(str[i]==''){

space++;//空格

}else{

other++;//其他字符

}

}

printf("大写字母:%d个\n",upper);

printf("小写字母:%d个\n",lower);

printf("数字:%d个\n",digit);

printf("空格:%d个\n",space);

printf("其他字符:%d个\n",other);

return0;

}解析:使用字符数组存储字符串,gets()函数可读取包含空格的字符串(注意:gets()存在安全隐患,实际开发中可使用fgets()替代);strlen()函数用于获取字符串长度(需包含string.h头文件);通过ASCII码范围判断字符类型,实现分类统计。例12:不使用库函数,求字符串的长度题目:从键盘输入一个字符串,不使用string.h头文件中的strlen()函数,通过循环计算字符串的长度并输出。c

#include<stdio.h>

intmain(void){

charstr[100];

intlen=0;//存储字符串长度,初始化为0

printf("请输入一个字符串:");

gets(str);

//循环遍历字符串,直到遇到结束符'\0'(C语言字符串默认以'\0'结尾)

while(str[len]!='\0'){

len++;//每遍历一个字符,长度加1

}

printf("字符串的长度为:%d\n",len);

return0;

}解析:C语言中,字符串以隐藏的结束符'\0'结尾,这是判断字符串结束的关键;通过while循环遍历字符数组,直到遇到'\0'停止,循环次数即为字符串长度,核心是理解字符串的存储机制。例13:不使用库函数,实现字符串反转题目:从键盘输入一个字符串,不使用string.h头文件中的函数,实现字符串反转(如输入"abcde",输出"edcba")。c

#include<stdio.h>

intmain(void){

charstr[100],temp;

intlen=0,i;

printf("请输入一个字符串:");

gets(str);

//第一步:计算字符串长度(复用例12的逻辑)

while(str[len]!='\0'){

len++;

}

//第二步:反转字符串,首尾字符交换,依次向中间靠拢

for(i=0;i<len/2;i++){

temp=str[i];//临时保存当前字符

str[i]=str[len-1-i];//把末尾字符赋值给当前位置

str[len-1-i]=temp;//把临时保存的字符赋值给末尾位置

}

printf("反转后的字符串:%s\n",str);

return0;

}解析:核心逻辑是“首尾交换”,通过循环遍历字符串前半部分,将第i个字符与第len-1-i个字符交换;循环终止条件为i<len/2,避免重复交换(如长度为5,交换0和4、1和3,中间的2无需交换)。例14:不使用库函数,实现字符串连接题目:从键盘输入两个字符串,不使用string.h头文件中的strcat()函数,将第二个字符串连接到第一个字符串的末尾并输出。c

#include<stdio.h>

intmain(void){

charstr1[200],str2[100];//str1需足够大,容纳两个字符串

inti=0,j=0;

printf("请输入第一个字符串:");

gets(str1);

printf("请输入第二个字符串:");

gets(str2);

//第一步:找到str1的结束符'\0'位置

while(str1[i]!='\0'){

i++;

}

//第二步:将str2的字符依次复制到str1的结束符之后

while(str2[j]!='\0'){

str1[i]=str2[j];

i++;

j++;

}

str1[i]='\0';//给连接后的字符串添加结束符

printf("连接后的字符串:%s\n",str1);

return0;

}解析:字符串连接的核心是“找到第一个字符串的结束位置,将第二个字符串的字符逐一复制过去”;注意str1的数组长度需足够大,避免溢出;复制完成后,必须手动添加结束符'\0',否则字符串会出现乱码。例15:判断两个字符串是否相等题目:从键盘输入两个字符串,不使用string.h头文件中的strcmp()函数,判断两个字符串是否完全相等,输出判断结果。c

#include<stdio.h>

intmain(void){

charstr1[100],str2[100];

inti=0,flag=1;//flag=1表示相等,0表示不相等

printf("请输入第一个字符串:");

gets(str1);

printf("请输入第二个字符串:");

gets(str2);

//遍历两个字符串,逐一对比字符

while(str1[i]!='\0'||str2[i]!='\0'){

//只要有一个字符不相等,就标记为不相等

if(str1[i]!=str2[i]){

flag=0;

break;

}

i++;

}

//最终判断:flag为1,且两个字符串同时结束(避免长度不同但前半部分相同的情况)

if(flag==1&&str1[i]=='\0'&&str2[i]=='\0'){

printf("两个字符串相等。\n");

}else{

printf("两个字符串不相等。\n");

}

return0;

}解析:判断字符串相等的两个条件:一是所有对应位置的字符都相同,二是两个字符串的长度相同(即同时到达结束符'\0');通过flag标记是否出现不同字符,循环结束后验证两个字符串是否同时结束,避免“abc”和“abcd”误判为相等。例16:将字符串中的小写字母转换为大写字母题目:从键盘输入一个字符串,将字符串中的所有小写字母转换为大写字母,其他字符保持不变,输出转换后的字符串。c

#include<stdio.h>

#include<string.h>

intmain(void){

charstr[100];

intlen,i;

printf("请输入一个字符串:");

gets(str);

len=strlen(str);

//遍历字符串,判断小写字母并转换

for(i=0;i<len;i++){

//小写字母ASCII码范围:97('a')~122('z'),大写字母:65('A')~90('Z')

//小写转大写:减去32('a'-'A'=32)

if(str[i]>='a'&&str[i]<='z'){

str[i]-=32;

}

}

printf("转换后的字符串:%s\n",str);

return0;

}解析:利用ASCII码的差值实现大小写转换,小写字母比对应的大写字母大32,因此减去32即可将小写转为大写;遍历字符串时,只对小写字母进行转换,其他字符(大写、数字、符号)保持不变。例17:一维数组的遍历与求和题目:从键盘输入10个整数,存入一维数组中,遍历数组并输出所有元素,同时计算数组中所有元素的和与平均值,输出结果。c

#include<stdio.h>

#defineN10//定义常量N,代表数组长度

intmain(void){

intarr[N];

intsum=0;

floatavg;

//输入10个整数,存入数组

printf("请输入10个整数:\n");

for(inti=0;i<N;i++){

printf("请输入第%d个整数:",i+1);

scanf("%d",&arr[i]);

sum+=arr[i];//累加求和

}

//遍历数组,输出所有元素

printf("数组中的元素为:");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

//计算平均值(转换为float类型,避免整数除法)

avg=(float)sum/N;

printf("数组元素的和:%d\n",sum);

printf("数组元素的平均值:%.2f\n",avg);//保留2位小数

return0;

}解析:使用#define定义常量N,便于后续修改数组长度;通过for循环实现数组的输入、遍历和求和;平均值计算时,将sum强制转换为float类型,避免整数除法导致的精度丢失,%.2f用于保留2位小数。例18:找出一维数组中的最大值和最小值题目:从键盘输入10个整数,存入一维数组中,找出数组中的最大值和最小值,输出其值及对应的下标(若有多个相同最值,输出第一个出现的下标)。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N];

intmax,min,max_idx,min_idx;

//输入数组元素

printf("请输入10个整数:\n");

for(inti=0;i<N;i++){

printf("请输入第%d个整数:",i+1);

scanf("%d",&arr[i]);

}

//初始化最大值、最小值及对应下标(默认第一个元素)

max=arr[0];

min=arr[0];

max_idx=0;

min_idx=0;

//遍历数组,更新最大值和最小值

for(inti=1;i<N;i++){

if(arr[i]>max){

max=arr[i];

max_idx=i;

}

if(arr[i]<min){

min=arr[i];

min_idx=i;

}

}

//输出结果

printf("数组中的最大值:%d,下标为:%d\n",max,max_idx);

printf("数组中的最小值:%d,下标为:%d\n",min,min_idx);

return0;

}解析:初始化时将数组第一个元素作为最值的初始值,下标设为0;遍历数组从第二个元素开始,逐一与当前最值对比,若大于最大值则更新最大值和下标,若小于最小值则更新最小值和下标;该方法只需遍历一次数组,效率较高。例19:将一维数组元素逆序存放题目:定义一个包含10个整数的一维数组(可手动初始化或键盘输入),将数组元素逆序存放(如原数组[1,2,3,...,10],逆序后[10,9,...,1]),输出原数组和逆序后的数组。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N]={1,2,3,4,5,6,7,8,9,10};//手动初始化数组

inttemp;

//输出原数组

printf("原数组:");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

//逆序存放:首尾交换,与字符串反转逻辑一致

for(inti=0;i<N/2;i++){

temp=arr[i];

arr[i]=arr[N-1-i];

arr[N-1-i]=temp;

}

//输出逆序后的数组

printf("逆序后的数组:");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

return0;

}解析:核心逻辑与字符串反转一致,通过首尾元素交换实现逆序;数组初始化可选择手动初始化或键盘输入(替换为scanf循环即可);循环终止条件为i<N/2,避免重复交换,确保逆序效果。例20:统计一维数组中指定元素出现的次数题目:从键盘输入10个整数存入一维数组,再输入一个指定整数,统计该整数在数组中出现的次数并输出(若未出现,输出0)。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N];

inttarget,count=0;

//输入数组元素

printf("请输入10个整数:\n");

for(inti=0;i<N;i++){

printf("请输入第%d个整数:",i+1);

scanf("%d",&arr[i]);

}

//输入指定整数(目标值)

printf("请输入要统计的整数:");

scanf("%d",&target);

//遍历数组,统计目标值出现次数

for(inti=0;i<N;i++){

if(arr[i]==target){

count++;

}

}

printf("整数%d在数组中出现了%d次\n",target,count);

return0;

}解析:使用count变量记录目标元素出现的次数,初始化为0;遍历数组时,每遇到一次目标元素,count加1;循环结束后,输出count的值,即可得到目标元素的出现次数,逻辑简单易懂,适合巩固数组遍历知识点。第三部分:排序与搜索算法(例21-30)例21:冒泡排序(升序)题目:从键盘输入10个整数,存入一维数组中,使用冒泡排序算法将数组元素按升序排列,输出排序前和排序后的数组。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N];

inttemp;

//输入数组元素

printf("请输入10个整数:\n");

for(inti=0;i<N;i++){

printf("请输入第%d个整数:",i+1);

scanf("%d",&arr[i]);

}

//输出排序前的数组

printf("排序前的数组:");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

//冒泡排序核心逻辑:两两对比,交换位置,每轮将最大元素“冒泡”到末尾

for(inti=0;i<N-1;i++){//外层循环:控制排序轮数(N个元素需N-1轮)

for(intj=0;j<N-1-i;j++){//内层循环:控制每轮对比次数(每轮减少1次)

if(arr[j]>arr[j+1]){//若前一个元素大于后一个,交换

temp=arr[j];

arr[j]=arr[j+1];

arr[j+1]=temp;

}

}

}

//输出排序后的数组

printf("排序后的数组(升序):");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

return0;

}解析:冒泡排序的核心是“两两对比、逐步冒泡”,外层循环控制排序轮数(N个元素需N-1轮),内层循环控制每轮的对比次数(每轮结束后,最大元素已排到末尾,对比次数减少1);通过交换相邻元素,实现升序排列,逻辑简单,适合初学者入门排序算法。例22:冒泡排序(降序)题目:基于例21,修改冒泡排序算法,将数组元素按降序排列,输出排序前和排序后的数组。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N];

inttemp;

//输入数组元素

printf("请输入10个整数:\n");

for(inti=0;i<N;i++){

printf("请输入第%d个整数:",i+1);

scanf("%d",&arr[i]);

}

//输出排序前的数组

printf("排序前的数组:");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

//降序冒泡排序:只需修改内层循环的判断条件(arr[j]<arr[j+1])

for(inti=0;i<N-1;i++){

for(intj=0;j<N-1-i;j++){

if(arr[j]<arr[j+1]){//前一个元素小于后一个,交换(实现降序)

temp=arr[j];

arr[j]=arr[j+1];

arr[j+1]=temp;

}

}

}

//输出排序后的数组

printf("排序后的数组(降序):");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

return0;

}解析:降序冒泡排序与升序的区别仅在于内层循环的判断条件,将“arr[j]>arr[j+1]”改为“arr[j]<arr[j+1]”,即可实现每轮将最小元素“冒泡”到末尾,最终得到降序数组;核心逻辑不变,仅修改对比规则。例23:选择排序(升序)题目:从键盘输入10个整数,存入一维数组中,使用选择排序算法将数组元素按升序排列,输出排序前和排序后的数组。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N];

inttemp,min_idx;//min_idx存储每轮找到的最小元素下标

//输入数组元素

printf("请输入10个整数:\n");

for(inti=0;i<N;i++){

printf("请输入第%d个整数:",i+1);

scanf("%d",&arr[i]);

}

//输出排序前的数组

printf("排序前的数组:");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

//选择排序核心逻辑:每轮找到最小元素,与当前轮次的起始位置交换

for(inti=0;i<N-1;i++){//外层循环:控制轮次(N个元素需N-1轮)

min_idx=i;//假设当前起始位置的元素是最小的

//内层循环:寻找当前轮次的最小元素下标

for(intj=i+1;j<N;j++){

if(arr[j]<arr[min_idx]){

min_idx=j;//更新最小元素下标

}

}

//将最小元素与当前起始位置元素交换

temp=arr[i];

arr[i]=arr[min_idx];

arr[min_idx]=temp;

}

//输出排序后的数组

printf("排序后的数组(升序):");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

return0;

}解析:选择排序的核心是“先选后换”,每轮遍历未排序部分,找到最小元素的下标,再与未排序部分的起始位置元素交换;相比冒泡排序,选择排序的交换次数更少,效率更高,适合理解“选择”与“交换”的排序思路。例24:插入排序(升序)题目:从键盘输入10个整数,存入一维数组中,使用插入排序算法将数组元素按升序排列,输出排序前和排序后的数组。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N];

inttemp,j;

//输入数组元素

printf("请输入10个整数:\n");

for(inti=0;i<N;i++){

printf("请输入第%d个整数:",i+1);

scanf("%d",&arr[i]);

}

//输出排序前的数组

printf("排序前的数组:");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

//插入排序核心逻辑:将未排序元素插入到已排序部分的合适位置

for(inti=1;i<N;i++){//外层循环:从第二个元素开始(第一个元素默认已排序)

temp=arr[i];//保存当前未排序元素

j=i-1;//j指向已排序部分的最后一个元素

//内层循环:寻找插入位置,将大于temp的元素向后移动

while(j>=0&&arr[j]>temp){

arr[j+1]=arr[j];//元素后移

j--;

}

arr[j+1]=temp;//将temp插入到合适位置

}

//输出排序后的数组

printf("排序后的数组(升序):");

for(inti=0;i<N;i++){

printf("%d",arr[i]);

}

printf("\n");

return0;

}解析:插入排序的核心是“逐步插入、逐步有序”,将数组分为已排序部分和未排序部分,每次取未排序部分的第一个元素,插入到已排序部分的合适位置(比它大的元素向后移动);插入排序适合数据量较小或接近有序的数组,效率较高。例25:二分查找(有序数组)题目:定义一个升序排列的一维数组,从键盘输入一个目标整数,使用二分查找算法判断该整数是否在数组中,若存在,输出其下标;若不存在,输出“未找到”。c

#include<stdio.h>

#defineN10

intmain(void){

//定义升序排列的数组(二分查找要求数组必须有序)

intarr[N]={1,3,5,7,9,11,13,15,17,19};

inttarget,left=0,right=N-1,mid;//left左边界,right右边界,mid中间位置

intflag=0;//flag=1表示找到,0表示未找到

printf("请输入要查找的整数:");

scanf("%d",&target);

//二分查找核心逻辑:不断缩小查找范围,直到找到目标或范围为空

while(left<=right){

mid=(left+right)/2;//计算中间位置(避免溢出可写为left+(right-left)/2)

if(arr[mid]==target){//找到目标,记录下标并退出循环

flag=1;

break;

}elseif(arr[mid]<target){//目标在右半部分,调整左边界

left=mid+1;

}else{//目标在左半部分,调整右边界

right=mid-1;

}

}

//输出查找结果

if(flag==1){

printf("找到目标整数%d,下标为:%d\n",target,mid);

}else{

printf("未找到目标整数%d\n",target);

}

return0;

}解析:二分查找的前提是“数组有序”,核心逻辑是“折半缩小范围”,通过计算中间位置mid,对比arr[mid]与目标值,调整左、右边界,逐步缩小查找范围;相比顺序查找,二分查找效率极高,时间复杂度为O(logN),适合大规模有序数组。例26:顺序查找(无序/有序数组)题目:从键盘输入10个整数存入一维数组(无序),再输入一个目标整数,使用顺序查找算法判断该整数是否在数组中,若存在,输出其第一个出现的下标;若不存在,输出“未找到”。c

#include<stdio.h>

#defineN10

intmain(void){

intarr[N];

inttarget,id

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论