【数据结构与算法】学习笔记-《算法笔记》-2

选择结构

  • 对于if语句而言,如果条件表达式是"!=0"或"==0",有一个信达雅的写法:
    如if(n!=0)改写为if(n)
  • switch 语句格式
switch(表达式){
	case 常量表达式1:
	    …
	    break;
	case 常量表达式2:
	    …
	    break;
	    ……
	default:
	    …
 }

如果没有break,将会全部执行。

练习:
例题4-1 一元二次方程求根

题目描述 求一元二次方程ax2+bx+c=0的根,三个系数a, b, c由键盘输入,且a不能为0,但不保证b2-4ac>0。
程序中所涉及的变量均为double类型。 输入 以空格分隔的一元二次方程的三个系数,双精度double类型 输出
分行输出两个根如下(注意末尾的换行): r1=第一个根 r2=第二个根 结果输出时,宽度占7位,其中小数部分2位。
如果方程无实根,输出一行如下信息(注意末尾的换行): No real roots!

#include <cstdio>
#include<cmath>

int main()
{
	double a, b, c, p;
	scanf("%lf %lf %lf", &a, &b, &c);
	p =( b * b) - (4 * a*c);
	if (a != 0 && p >= 0)
	{
		printf("r1=%7.2f\nr2=%7.2f", (-b + sqrt(p)) / (2 * a), (-b - sqrt(p)) / (2 * a));
	}
	else
	{
		printf("No real roots!");
	}
	return 0;
}

例题4-2 比较交换实数值

题目描述 从键盘输入2个实数,按照代数值由小到大的顺序输出这两个数。 输入 用空格分隔的两个实数。 输出
从小到大输出这两个实数,中间以空格来分隔,小数在前,大数在后。 小数点后保留2位小数。 末尾输出换行符。

#include <cstdio>

int main()
{
	double a, b, c;
	scanf("%lf %lf", &a, &b);
	if (a > b)
	{
		c = a;
		a = b;
		b = c;
	}
	printf("%.2f %.2f\n", a, b);
	return 0;
}

例题4-3 比较交换3个实数值,并按序输出

题目描述
从键盘输入3个实数a, b, c,通过比较交换,将最小值存储在变量a中,最大值存储在变量c中,中间值存储在变量b中,并按照从小到大的顺序输出这三个数a, b, c。
末尾输出换行。
输入
输入以空格分隔的三个实数
输出
按照从小到大的顺序输出这三个实数,中间以空格分隔,最小值在前,最大值在后。小数点后保留2位小数。
注意末尾的换行。

#include "stdafx.h"
#include <cstdio>

int main()
{
	double a, b, c,d;
	scanf("%lf %lf %lf", &a, &b,&c);
	if (a > b)
	{
		d = a;		a = b;		b = d;
	}
	if (b > c)
	{
		d = b;		b = c;		c = d;
	}
	if (a>b)
	{
		d = a;		a = b;		b = d;
	}
	printf("%.2f %.2f %.2f\n", a, b,c);
	return 0;
}

习题4-4 三个整数求最大值

题目描述
有3个整数a, b, c,由键盘输入,输出其中最大的数。
输入
以空格分割的三个整数。
输出
三个数中的最大值,末尾换行。

#include <cstdio>

int main()
{
	int a, b, c,max;
	scanf("%d %d %d", &a, &b,&c);
	max = a;
	if (max < b)
		max=b;
	if (max < c)
		max = c;
	printf("%d\n",max);
	return 0;
}

习题4-10-1 奖金计算

题目描述
某企业发放的奖金根据利润提成。利润I低于或等于100000时,奖金可提10%;利润高于100000元,低于200000元(100000<I<=200000)时,低于100000元的部分仍按10%提成,高于100000元的部分提成比例为7.5%;200000<I<=400000时,低于200000元的部分仍按上述方法提成(下同),高于200000元的部分按5%提成;400000<I<=600000元时,高于400000元的部分按3%提成;600000<I<=1000000时,高于600000元的部分按1.5%提成;I>1000000元时,超过1000000元的部分按1%提成。
从键盘输出当月利润I,求应发奖金数,奖金精确到分。
要求用if语句实现。
输入
企业利润,小数,双精度double类型
输出
应发奖金数,保留2位小数,末尾换行。

#include <cstdio>

int main()
{
	double I,bonus;
	scanf("%lf", &I);
	if (I <= 100000)	
		bonus = I * 0.1;
	if (I > 100000 && I <= 200000)
		bonus = 10000 + (I - 1000000 * .075);
	if (I > 200000 && I <= 400000)
		bonus = 100000 * 0.175 + (I - 200000)*.05;
	if (I > 400000 && I <= 600000)
		bonus = 100000 * 0.225 + (I - 400000)*.03;
	if (I >600000 && I <=1000000)
		bonus = 100000 * 0.255 + (I - 600000)*.015;
	if (I > 1000000)
		bonus = 100000 * 0.27 + (I - 1000000)*0.01;
	printf("%.2f\n", bonus);
	return 0;
}

循环结构

  • while语句:
while(条件){
……
}//注意这里没有分号
  • do while语句
do{
	…
}while(条件);//注意这里有分号
  • for语句
for(表达式A;表达式B;表达式C){
	…
}//注意这里没有分号

另外,C语言中不允许在for语句的表达式A中定义变量,但C++可以。

  • break /continue 语句

练习:
例题5-1-1 连续自然数求和

求1+2+3+…+100
要求用while语句实现
输入

输出
要求的和,末尾输出换行。

#include <cstdio>

int main()
{
	int sum=0,i=1;
	while(i<=100)
	{
		sum += i;
		i++;
	} 
	printf("%d\n", sum);
	return 0;
}

例题5-1-2 连续自然数求和

题目描述
求1+2+3+…+100,即求
要求用do…while语句实现
输入

输出
计算结果,注意末尾输出换行。

#include <cstdio>

int main()
{
	int sum=0,i=1;
	do
	{
		sum += i;
		i++;
	} while (i <= 100);
	printf("%d\n", sum);
	return 0;
}

例题5-1-3 连续自然数求和

题目描述
求1+2+3+…+100,即求
要求用for语句实现
输入

输出
计算结果,末尾输出换行。

#include <cstdio>

int main()
{
	int sum=0;
	for (int i = 1; i <= 100; i++)
	{
		sum += i;
	}
	printf("%d\n", sum);
	return 0;
}

例题5-1-4 连续自然数求和

题目描述
输入一个正整数N,求1+2+…+N,即求
要求在程序中使用break语句。
输入
要求输入的数据一定是一个正整数。
输出
计算的结果,连续N个自然数的和,末尾输出换行。

#include <cstdio>

int main()
{
	int sum=0,i=1,N;
	scanf("%d", &N);
	while(1)
	{
		if (i > N)	break;
		else
		{
			sum += i;
			i++;
		}
	} 
	printf("%d\n", sum);
	return 0;
}

例题5-1-5 连续自然数求和

题目描述
编程实现求1+2+3+…和的程序,要求得到使使和数大于1000的最小正整数。
输入

输出
输出使1+2+3+…+N>1000的最小正整数N,末尾输出换行。

#include <cstdio>

int main()
{
	int sum=0,i=1;
	while(1)
	{
		if (sum <= 1000)
		{
			sum += i;
			i++;
		}
		else
		{
			printf("%d\n", i-1);
			break;
		}
	} 
	return 0;
}

例题5-6 矩阵输出

题目描述 输出以下4*5的矩阵
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
要求使用循环实现,注意每行输出5个数字,每个数字占3个字符的宽度,右对齐。

#include <cstdio>

int main()
{
	for(int i=1;i<=4;i++)
		for (int j = 1; j <= 5; j++)
		{
			if (j%5)
				printf("%3d", i*j);
			else
				printf("%3d\n", i*j);
		}
	return 0;
}

例题5-7 求圆周率pi的近似值

题目描述
用如下公式π/4=1-1/3+1/5-1/7
求圆周率PI的近似值,直到发现某一项的绝对值小于10-6为止(该项不累加)。
要求输出的结果总宽度占10位,其中小数部分为8位。
程序中使用浮点型数据时,请定义为双精度double类型。
如果需要计算绝对值,可以使用C语言数学库提供的函数fabs,如求x的绝对值,则为fabs(x).
输入

输出
PI=圆周率的近似值
输出的结果总宽度占10位,其中小数部分为8位。
末尾输出换行。

#include <cstdio>
#include<cmath>

int main()
{
	double i=0,pi=0;
	while ((1 / (2*i+1)) >= 1E-6)//注意这里的1E-6
	{
		pi += (pow(-1,i)/( 2*i+1));//pow 最好两个参数都为double
		i++;
	}
	printf("PI=%10.8f\n", 4 * pi);
	return 0;
}

例题5-8 Fibonacci数列

题目描述
输入一个正整数n,求Fibonacci数列的第n个数。
Fibonacci数列的特点:第1,2个数为1,1。从第3个数开始,概述是前面两个数之和。即:
要求输入的正整数n不超过50.
输入 一个不超过50的正整数 输出 Fibonacci数列的第n个数,末尾输出换行。

#include <cstdio>
#include<cmath>

int main()
{
	int n, output,a=1,b=1;
	scanf("%d", &n);
	if (n <= 50)
	{
		if (n == 1 || n == 2)	printf("1\n");
		else
		{
			for (int i = 3; i <= n; i++)
			{
				output = a + b;
				a = b;
				b = output;
			}
			printf("%d\n", output);
		}
	}
}

习题5-10 分数序列求和
题目描述

有如下分数序列
2/1,3/2,5/3,8/5,13/8,21/13…求出这个数列的前 20 项之和。
求出次数列的前20项之和。
请将结果的数据类型定义为double类型。
输入 无 输出 小数点后保留6位小数,末尾输出换行。

int main()
{
	double mun, den=3,a=2,b=3,output=(double)2/1+(double)3/2;
	for (int i = 3; i <= 20; i++)
	{
		mun = a + b;
		a = b;
		b = mun;
		output += (mun / den);
		den = b;
	}
	printf("%.6f\n", output);
}

数组

  • 如果想要给整个数组都赋初值0,可以有如下形式:
int a[10]={0};
int a[10]={};
  • 如果数组的大小比较大(大概10^6级别),则需要将定义在主函数外面,否则会使程序异常退出,原因是函数内部申请的局部变量来自系统栈,允许申请的空间较小;而函数外部申请的全局变量来自静态存储区,允许申请的空间较大。
  • memset——对数组中每一个元素赋相同的值
    格式: memset(数组名,值,sizeof(数组名));
    一般有两种函数可以实现:memset/fill;
    使用memset 要添加 string.h;
    建议初学者赋0或-1,因为memset使用 “按字节赋值”;
    如果要赋其他数字(比如1),建议使用fill;
    memset的执行速度大于fill。
    示例:
#include "stdafx.h"
#include <cstdio>
#include<cstring>

int main()
{
	int a[5] = { 1,2,3,4,5 };
	memset(a, 0, sizeof(a));
	for (int i = 0; i < 5; i++) 
	{
		printf("%10d", a[i]);
	}
	printf("\n");
	memset(a, -1, sizeof(a));
	for (int i = 0; i < 5; i++)
	{
		printf("%10d", a[i]);
	}
	printf("\n");
	memset(a, 1, sizeof(a));
	for (int i = 0; i < 5; i++)
	{
		printf("%10d", a[i]);
	}
	printf("\n");
}

输出结果:
0 0 0 0 0
-1 -1 -1 -1 -1
16843009 16843009 16843009 16843009 16843009
请按任意键继续. . .

  • 字符数组的初始化有两种方式:
char str[15]={'G','O','O','D',' ','S','T','O','T','Y','!'};
char str[15]="GOOD STORY!";//注意单双引号的差别

注意,第二种方法仅限于初始化,程序其他的地方不能直接赋值整个字符串

  • 字符数组输入函数:scanf / getchar / gets
  • 字符串数组输出函数: printf / putchar / puts
  • scanf “%s” 识别 空格作为字符串的结尾,不加&;
  • getchar / putchar 输入输出单个字符,可以用来吸收换行符
    示例:
int main()
{
	char str[5][5];
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			str[i][j] = getchar();
		}
		getchar();//这句可以把输入中每行末尾的换行符吸收掉!!!
	}
	putchar('\n\n\n');
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			putchar(str[i][j]);
		}
		putchar('\n');//注意单引号
	}
}

有吸收换行符则输出结果=输入结果,没有吸收会误识别换行符
在这里插入图片描述
在这里插入图片描述

  • gets用来输入一行字符串,以换行符作为结束,
    因此,scanf后如果要使用gets,需要先用getchar吸收scanf后的换行符

  • puts用输出一行字符串,并紧跟着一个换行

  • 字符数组的存放方式
    一维/二维数组的第二维 的末尾都有一个空字符\0表示存放的字符串的结尾;
    空字符\0在使用gets或scanf输入字符串时会自动添加在字符串的后面并占用一个字符位;
    puts/printf就是通过识别\0作为字符串的结尾来输出的。
    只有char型数组需要\0作为结尾,int不需要;
    \0不是空格;
    字符数组的长度一定比实际存储字符串的长度至少多1;
    如果不是使用scanf函数的%s或gets函数输入字符串(如使用getchar),请一定在输入的每个字符串后加入“\0”,否则printf和pufs输出字符串会因为无法识别字符串末尾而输出一大堆乱码。

  • string.h头文件中的函数
    memset / strlen / strcmp / strcpy / strcat
    strlen(字符数组): 得到字符数组中第一个\0前的字符的个数;
    strcmp(字符数组1,字符数组2):比较,1小返回负数,相等0,1大正数;
    strcpy(字符数组1,字符数组2):把字符数组2包括结束符"\0"一起复制给1;
    strcat(字符数组1,字符数组2):把2接到1后面

  • stdio.h头文件中的函数
    sscanf / sprintf
    可以看成string+scanf/sring+printf
    sscanf(字符数组1,“格式”,&字符串2);把字符数组1里的内容写到2所在地址;
    sprintf(字符数组1,“格式”,字符串2);把字符串2写到1字符串数组里;

示例:

#include "stdafx.h"
#include <cstdio>
#include<cstring>

int main()
{
	int n;
	char str[100] = "123";
	sscanf(str, "%d", &n);
	printf("%d\n", n);
	return 0;
}

输出结果:123

int main()
{
	int n=123;
	char str[100];
	sprintf(str, "%d", n);
	printf("%s\n", str);
	return 0;
}

输出结果:123;

sscanf和printf可以进行复杂格式的输入和输出
示例:
将字符数组中str的内容按"%d:%lf,%s"的格式写到int型变量n、double型变量db、char型数组str2中,再将它们反序组合到str3中

#include "stdafx.h"
#include <cstdio>
#include<cstring>

int main()
{
	int n;
	double db;
	char str1[100]="2019:3.14,hello",str2[100],str3[100];
	sscanf(str1, "%d:%lf,%s", &n, &db, str2);
	printf("n=%d,\ndb=%f,\nstr2=%s\n", n, db, str2);
	sprintf(str3, "%s:%lf,%d", str2, db, n);
	printf("str3=%s", str3);
	return 0;
}

输出结果:
n=2019,
db=3.140000,
str2=hello
str3=hello:3.140000,2019请按任意键继续. . .

练习
习题6-4 有序插入

题目描述 有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入到数组中。
假设数组长度为10,数组中前9个数(这9个数要求从键盘上输入,输入时要满足自小到大的输入顺序)已经按从小到大进行排序。
然后再从键盘上输入一个整数,将此整数插入到前有序的9个数中,使得最终的10个数依然是从小到大有序的。
输入 第一行输入以空格分隔的9个整数数,要求按从小到大的顺序输入。
第二行输入一个整数
输出 从小到大输出这10个数,每个数一行。

#include <cstdio>
#include<cstring>

int main()
{
	int a[15],b;
	//scanf("%d %d %d %d %d %d %d %d %d",)
	for (int i = 0; i <= 8; i++)
	{
		scanf_s("%d",&a[i]);
	}
	getchar();
	scanf_s("%d", &b);
	for (int i = 0; i <= 8; i++)
	{
		if (a[i] > b)
		{
			for (int j = 8; j >=i; j--)
			{
				a[j + 1] = a[j];
			}
			a[i] = b;
			break;
		}
	}
	for (int i = 0; i <= 9; i++)
	{
		printf("%d\n", a[i]);
	}
	return 0;
}

习题6-5 数组元素逆置

题目描述 将一个长度为10的整型数组中的值按逆序重新存放。

如:原来的顺序为1,2,3,4,5,6,7,8,9,0,要求改为0,9,8,7,6,5,4,3,2,1

输入 从键盘上输入以空格分隔的10个整数。

输出 按相反的顺序输出这10个数,每个数占一行。

#include <cstdio>
#include<cstring>

int main()
{
	int a[10],b[10];
	for (int i = 0; i <= 9; i++)
	{
		scanf_s("%d", &a[i]);
		b[9 - i] = a[i];
	}
	//getchar();
	for (int i = 0; i <= 9; i++)
	{
		printf("%d\n", b[i]);
	}
	return 0;
}

习题6-6 杨辉三角

按要求输入如下格式的杨辉三角

1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

最多输出10层

输入 输入只包含一个正整数n,表示将要输出的杨辉三角的层数。 输出 对应于该输入,请输出相应层数的杨辉三角,每一层的整数之间用一个空格隔开

#include <cstdio>
#include<cstring>

int main()
{
	int a[10][10],n;
	scanf_s("%d", &n);
	a[0][0] = 1;
	printf("%d\n", a[0][0]);
	for (int i = 2; i <= n; i++)
	{
		for(int j=1;j<=i;j++)
			if (j == 1 )
			{
				a[i - 1][j - 1] = 1;
				printf("%d ", a[i - 1][j - 1]);
			}
			else if (j == i)
			{
				a[i - 1][j - 1] = 1;
				printf("%d\n", a[i - 1][ j - 1]);
			}
			else
			{
				a[i - 1][ j - 1] = a[i - 2][ j - 2] + a[i - 2][ j - 1];
				printf("%d ", a[i - 1][j - 1]);
			}
		
	}
	return 0;
}

习题6-12 解密

题目描述 有一行电文,已按如下规律译成密码:

A–>Z a–>z

B–>Y b–>y

C–>X c–>x

… …

即第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求根据密码译回原文,并输出。

输入 输入一行密文 输出 解密后的原文,单独占一行。

#include <cstdio>
#include<cstring>

int main()
{
	char str[100],str1[100];
	scanf_s("%s", str,100);
	int n;
	n = strlen(str);
	for (int i = 0; i <= n; i++)
	{
		if (str[i] >= 65 && str[i] <= 90)
			str1[i] =26- (str[i] -65)+64;
		else if (str[i] >= 97 && str[i] <= 122)
			str1[i] = 26 - (str[i] - 97)+96;
		else
			str1[i] = str[i];
		printf("%c", str1[i]);
	}
	return 0;
}

习题6-13 字符串比较

题目描述 比较两个字符串s1和s2的大小,如果s1>s2,则输出一个正数;若s1=s2,则输出0;若s1<s2,则输出一个负数。

要求:不用strcpy函数;两个字符串用gets函数读入。

例如:“A"与"C"相比,由于"A”<“C”,应输出负数,同时由于"A"与"C"的ASCII码差值为2,因此应输出"-2"。

同理:"And"和"Aid"比较,根据第2个字符比较的结果,“n"比"i"大5,因此应该输出"5”

输入 输入2行字符串

输出 一个整数,表示这两个字符串 比较的差值,单独占一行。

#include <cstdio>
#include<cstring>

int main()
{
	char str1[100], str2[100];
	gets_s(str1);
	gets_s(str2);
	int n = strlen(str1),output;
	for (int i = 0; i <= n; i++)
	{
		if (str1[i] != str2[i])
		{
			output = str1[i] - str2[i];
			printf("%d", output);
		}
	}
	return 0;
} 

例题6-1 逆序输出数组元素

题目描述 从键盘上输入10个整数,存储在一个长度为10的整型数组中,要求将输入的10个数逆序输出。

如输入为:0,1,2,3,4,5,6,7,8,9 输出为9,8,7,6,5,4,3,2,1,0
输入 10个整数,以空格分隔 输出 将输入的10个整数逆序输出,每个数占一行。

#include <cstdio>
#include<cstring>


int main()
{
	int a[10], b[10];
	for (int i = 0; i <= 9; i++)
	{
		scanf_s("%d", &a[i]);
		b[9 - i] = a[i];
	}
	//getchar();
	for (int i = 0; i <= 9; i++)
	{
		printf("%d\n", b[i]);
	}
	return 0;
}

例题6-2 数组求解Fibonacci数列问题

题目描述 Fibonacci数列的特点:第1,2个数为1,1。从第3个数开始,概述是前面两个数之和。即:

要求输出Fibonacci数列的前20个数。

输入 无 输出 Fibonacci数列的前20个数,每个数占一行。

#include <cstdio>
#include<cstring>


int main()
{
	int a[20];
	a[0] = 1;
	a[1] = 1;
	printf("%d\n", a[0]);
	printf("%d\n", a[1]);
	for (int i = 2; i <= 19; i++)
	{
		a[i] = a[i - 1] + a[i - 2];
		printf("%d\n", a[i]);
	}
	return 0;
}

例题6-3 冒泡排序

题目描述 从键盘上输入10个整数,用冒泡法对这10个数进行排序(由小到大)。 输入 以空格分隔的10个整数 输出
依次输出排好序的10个整数,每个数占一行。

#include <cstdio>
#include<cstring>


int main()
{
	int a[10],b;
	for (int i = 0; i <= 9; i++)
	{
		scanf("%d", &a[i]);
	}
	for (int i = 0; i <= 8; i++)
	{
		for (int j = 0; j <= 8 - i; j++)
		{
			if (a[j] > a[j + 1])
			{
				b = a[j];
				a[j] = a[j + 1];
				a[j + 1] = b;
			}
		}
	}
	for (int i = 0; i <= 9; i++)
		printf("%d\n", a[i]);
	return 0;
}

例题6-4 矩阵转置

题目描述 将一个2行3列的矩阵(二维数组)行列互换,存储到另一个3行2列的矩阵中。

要求以整型数据为例来解答。

输入 输入2行数据,每行3个整数,以空格分隔。 输出 行列互换后的矩阵,3行,每行2个数据,以空格分隔。

#include <cstdio>
#include<cstring>


int main()
{
	int a[2][3],b[3][2];
	for (int i = 0; i <= 1; i++)
	{
		for (int j = 0; j <=2; j++)
		{
			scanf("%d", &a[i][j]);
			b[j][i] = a[i][j];
		}
	}
	for (int i = 0; i <= 2; i++)
	{
		for (int j = 0; j <= 1; j++)
		{
			if (j)	printf("%d\n", b[i][j]);
			else    printf("%d ", b[i][j]);
		}

	}
	return 0;
}

例题6-9 字符串求最大值

题目描述 从键盘上输入3个字符串,求出其中最大者。
输入 输入3行,每行均为一个字符串。

输出 一行,输入三个字符串中最大者。

#include <cstdio>
#include<cstring>


int main()
{
	char str1[100], str2[100],str3[100],max[100];
	scanf("%s", str1);
	scanf("%s", str2);
	scanf("%s", str3);
	if (strcmp(str1, str2) <= 0)	sscanf(str2, "%s", max);
	else sscanf(str1, "%s", max);
	if(strcmp(max, str3) <= 0)	sscanf(str3, "%s", max);
	printf("%s", max);
	return 0;
}
发布了43 篇原创文章 · 获赞 4 · 访问量 1225

猜你喜欢

转载自blog.csdn.net/weixin_42176221/article/details/99682341