一、递归
什么是递归?
①程序调用自己本身
②要有终止条件
递归的方式主要思考方式在于:把大事化小
例1:接受一个整型值(无符号),按照顺序打印出它的每一位。例如:输入1234,输出 1 2 3 4
void print(int n){
if (n > 9){
printf(n / 10);
}
printf("%d ", n % 10);
}
int main(){
int num = 1234;
print(num);
return 0;
}
例2:编写函数不允许创建临时变量,求字符串长度。
//递归方式
int MyStrlenD(const char*str){
if (*str == '\0'){
return 0;
}
else{
return 1 + MyStrlenD(str + 1);
}
}
//循环方式
1. 给一个计数,用来统计有效字符的个数
2. 遍历字符串,只要没有遇到\0, 遇到一个字符给计数加1,直到遇到\0
int MyStrlenX(char str[]){
int size = 0;
for (int i = 0; str[i] != '\0'; i++){
size++;
}
return size;
}
int main(){
char *p = "abcdef";
int len1 = MyStrlenD(p);
int len2 = MyStrlenX(p);
printf("%d\n%d\n", len1, len2);
return 0;
}
例3、求n的阶乘(不考虑溢出)
int FacD(int n){
if (n == 1){
return 1;
}
int ret = n * FacD(n - 1);
return ret;
}
int FacX(int n){
int ret = 1;
for (int i = 1; i <= n; i++){
ret *= i;
}
return ret;
}
int main(){
printf("%d\n%d\n", FacD(5), FacX(5));
}
例4、求第n个斐波那契数。(不考虑溢出)
int fib(int n){
if (n <= 2)
return 1;
else
return fib(n - 1) + fib(n - 2);
}
int main(){
printf("%d\n", fib(10));
}
但这种方法计算位数多时将非常耗费时间。
解决方法:将递归改写为非递归。
int FibX(int n)
{
if (n <= 0){
return -1;
}
int f1 = 1;
int f2 = 1;
int f3 = 1;
for (int i = 3; i <= n; i++){
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
return f3;
}
int main(){
printf("%d\n", FibX(30));
}
例5、汉诺塔
1: A -> C 1
2: A->B A -> C B->C 3
3: A -> C A->B C->B A->C B->A B->C A -> C 7
4: 2^4-1 15
....... ...... ............ ..
64 : 2^64 -1
void Move(char pos1,char pos2)
{
printf("%c -> %c ",pos1,pos2);
}
//pos1:起始位置 pos2:过度位置 pso3:目标位置
void HanoTa(int n,char pos1,char pos2,char pos3)
{
if (n == 1)
{
Move(pos1, pos3);
return;
}
HanoTa(n - 1, pos1, pos3, pos2);
Move(pos1, pos3);
HanoTa(n - 1, pos2, pos1, pos3);
}
二、数组
数组的创建:
// 创建方法1
int arr1[10]; //定义了一个未赋值的整型数组,局部变量会存放的是随机值;若是全局变量则存放0;
//创建方法2
int arr2[10] = { } //在给括号里赋值时,是一位一位的赋值;
注意:在数组创建中,[]
中要给一个常量才可以,不能使用变量。
在C语言中使用const int i = 10
这种方法定义的是为“变常量”,在C++中为常量。
int arr1[10] = {1,2,3}; // [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]
int arr2[] = {1, 2, 3, 4}; // [1, 2, 3, 4]
int arr3[5] = {1, 2, 3, 4, 5} // [1, 2, 3, 4, 5]
char arr4[3] = {'a', 98, 'c'} // [a, b, c]
char arr5[] = {'a', 'b', 'c'} // [a, b, c]
char arr6[] = "abcdef" //[a, b, c, d, e, f, \0]
一维数组的使用
#include<stdio.h>
int main(){
int arr[10] = { 0 }; //数组不完全初始化
//计算数组的元素个数
int size = sizeof(arr) / sizeof(arr[0]);
//对数组内容赋值,数组是使用下标来访问的,下标从0开始
int i = 0; //下标
for (i = 0; i < 10; i++){
arr[i] = i;
}
//输出数组的内容
for (i = 0; i < 10; ++i){
printf("%d\n", arr[i]);
}
return 0;
}
注意:
当我们计算数组大小时,尽量将数组长度的计算放在main
函数中,使其作为实参传递给函数中。
当以函数的形式定义数组是,形参所定义的数组名表示的是数组首元素的地址,所以如果在函数中对数组大小进行sizefof()
计算,会因为计算的是地址大小,所以指针的大小会返回为4。
关于栈上的存放
局部变量是存放在栈上的,栈有两种特点:
①先进后出
②增长方向为:高地址到低地址进行增长,大小一般为1~2M
。