《函数和递归》
文章目录
一.函数的分类
1.库函数
学习网站
www.cplusplus.com
en.cppreference.com英文版/zh.cppreference.com中文版
MSDN
stackoverflower.com
github
库函数分类
IO函数
字符串操作函数
内存操作函数
时间/日期函数
数学函数
其他库函数
例:
strcpy—string copy—字符串拷贝
strlen—string length—字符串长度有关
memset—memory set—内存设置
2.自定义函数
二.函数参数
1.实际参数
常量,变量,表达式,函数
2.形式参数
当实参传给形参的时候,形参其实是实参的一份临时拷贝,对形参的修改是不会影响实参的
三.函数调用
1.传值调用
2.传址调用
练习
打印100-200间素数
二分查找法:在有序数组中找数,找7
#include<stdio.h>
int binary_search(int arr[], int k, int sz)
//本质上arr是一个指针
{
//int sz = sizeof(arr) / sizeof(arr[0]);不能放在这,因为sizeof(arr)结果为4,sz结果为1
int left = 0;
int right = sz - 1;
while(left<=right)//注意一定是<=
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
//二分查找
//在一个有序数组中查找具体的某个数
//如果找到了返回这个数的下标;找不到返回-1
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]);//应放在这里
int ret = binary_search(arr, k, sz);
//传送过去的是数组arr首元素的地址
if (ret == -1)
{
printf("找不到指定的数字");
}
else
{
printf("找到了,下标是%d", ret);
}
return 0;
}
四.函数的嵌套调用和链式访问
五.函数的声明和定义
使用:
1.函数声明
先声明后使用
函数声明一般放在头文件中
2.函数定义
函数定义一般放在源文件中
六.函数递归
存在限制条件
每次递归调用后越来越接近这个限制条件
练习
不创建临时变量,求字符串长度
#include<stdio.h>
//只用自定义函数,不用递归:(创建临时变量)
//int my_strlen(char* str)
//{
// int count = 0;
// while (*str != '\0')
// {
// count++;
// str++;
// }
// return count;
//}
//使用递归:大事化小(不创建临时变量)
//my_strlen("bit");
//1+my_strlen("bi");
//1+1+my_strlen("b");
//1+1+1+my_strlen("");
//1+1+1+0
//3
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str + 1);
else
return 0;
}
int main()
{
char arr[] = "bit";
//int len=strlen(arr);//求字符串长度
//printf("%d\n",len);
int len = my_strlen(arr);//arr是数组,数组传参,传过去的不是整个数组,而是第一个元素的地址
//模拟实现了一个strlen函数
printf("len=%d\n", len);
return 0;
}
1.递归和迭代
求n的阶乘
#include<stdio.h>
//循环
int Fac1(int n)
{
int i = 0;
int ret = 1;
for (i = 1; i <= n; i++)
{
ret *= i;
}
return ret;
}
//递归
int Fac2(int n)
{
if (n <= 1)
return 1;
else
return n * Fac2(n - 1);
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fac2(n);
printf("%d\n", ret);
return 0;
}
求第n个斐波那契数
//斐波那契数列:1 1 2 3 5 13 21 34 55 …
#include<stdio.h>
//递归,计算复杂,耗时很长
//int count = 0;
int Fib1(int n)
{
//if (n == 3)//测试第三个斐波那契数的计算次数
//{
// count++;
//}
if (n <= 2)
return 1;
else
return Fib1(n - 1) + Fib1(n - 2);
}
//循环,速度快
int Fib2(int n)
{
int a=1;
int b=1;
int c=1;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fib2(n);
printf("%d\n", ret);
//printf("count=%d", count);
return 0;
}
2.函数递归经典题目
汉诺塔问题
青蛙跳台阶问题-------《剑指offer》67道笔试题
练习题
1.写一个函数求a的二进制(补码)表示中有几个1
法一
#include<stdio.h>
int count_bit_one(unsigned int n)//注意unsigned,否则n若是负数则结果不对
{
int count = 0;
while (n)
{
if (n % 2 == 1)
{
count++;
}
n = n / 2;
}
return count;
}
int main()
{
int a = 0;
scanf("%d", &a);
//写一个函数求a的二进制(补码)表示中有几个1
int count = count_bit_one(a);
printf("%d", count);
return 0;
}
法二
#include<stdio.h>
int count_bit_one(unsigned int n)
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((n >> 1) & 1) == 1)
{
count++;
}
}
return count;
}
int main()
{
int a = 0;
scanf("%d", &a);
//写一个函数求a的二进制(补码)表示中有几个1
int count = count_bit_one(a);
//10000000000000000000000000000001 -1的原码
//11111111111111111111111111111110 反码
//11111111111111111111111111111111 补码
//00000000000000000000000000000001
printf("%d", count);
return 0;
}
法三(高效)
#include<stdio.h>
int count_bit_one(unsigned int n)
{
int count = 0;
int i = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
//n = n & (n - 1)
//n=13
//1101 n
//1100 n-1
//1100 n
//1011 n-1
//1000 n
//0111 n-1
//0000 n
int main()
{
int a = 0;
scanf("%d", &a);
//写一个函数求a的二进制(补码)表示中有几个1
int count = count_bit_one(a);
printf("%d", count);
return 0;
}
2.逆序排列abcdef
法一:不用递归
#include<stdio.h>
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
void reverse_string(char arr[])
{
int left = 0;
int right = my_strlen(arr) - 1;
while (left < right)
{
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
left++;
right--;
}
}
int main()
{
char arr[] = "abcdef";
reverse_string(arr);
printf("%s\n", arr);
return 0;
}
法二:递归
#include<stdio.h>
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
void reverse_string(char arr[])
{
char tmp = arr[0];
int len = my_strlen(arr);
arr[0] = arr[len - 1];
arr[len - 1] = '\0';
if (my_strlen(arr + 1) >= 2)
{
reverse_string(arr + 1);
}
arr[len - 1] = tmp;
}
int main()
{
char arr[] = "abcdef";
reverse_string(arr);
printf("%s\n", arr);
return 0;
}
3.使用递归,写一个函数,输入一个非负整数,返回组成他的数字之和
例如:
输入:1729
返回:19
#include<stdio.h>
//DigitSum(1729)
//DigitSum(172)+1729%10
//DigitSum(17)+172%10+1729%10
//DigitSum(1)+17%10+172%10+1729%10
//1+7+2+9=19
int DigitSum(unsigned int num)
{
if (num > 9)
{
return DigitSum(num / 10) + num % 10;
}
else
{
return num;
}
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
int ret = DigitSum(num);
printf("ret=%d\n", ret);
return 0;
}