2021.2.26----2.28函数和递归

《函数和递归》

一.函数的分类

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值