IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言函数复习(传值传址【二分查找】,递归【阶乘,汉诺塔等】) -> 正文阅读

[C++知识库]C语言函数复习(传值传址【二分查找】,递归【阶乘,汉诺塔等】)

函数

函数的传值调用

函数的形参和实参占用不同的代码块,对形参的修改并不会修改实参的值

函数的传址调用

传址调用指的是将函数外部创建的内存地址传给函数形参的一种调用方式

这种传参方式可以在函数内部操作函数外部的变量

练习

二分查找

#include<stdio.h>

int binary_2(int arr[] , int k,int len);

int main() {
	int arr[ ] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr) / sizeof(arr[0]);
	int element ;
	printf("请输入你想要查找的元素");
	scanf("%d", &element);
	int ret;
	ret = binary_2(arr ,element,len);
	if (ret == -1) {
		printf("没有找到指定元素\n");
	}
	else {
		printf("找到了,元素的下标是%d\n",ret);
	}

	return 0;
}
int binary_2(int arr[] , int k,int len) {
	//int len = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = len - 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;
}

注意点:

1)一个是函数的len要在main函数内部进行计算,因为如果在函数内部计算,size(arr) 的值实际上是4 , 为什么呢,因为传入的是一个指针变量,指向的是第一个元素的地址,算出来的大小就是int* 大小

#include<stdio.h>
int main() {
素的下标是%d\n",ret);
	printf("%d\n", sizeof(arr));//40
	printf("%d\n", sizeof(arr[0]));//4

	return 0;
}

2)第二个要注意的是,传入的形参int arr[] 为什么是指针变量呢 , int arr[] 等价于 int * arr,两者是一样的

函数的模块化使用

从一个源文件A到另一个源文件B中 ,想要在源文件A中使用源文件B中的函数 ,

1)首先要在源文件A中加入 #include “ 你想要使用的函数名”

  1. 在头文件中新建一个和B一样名字的头文件(.h)结尾

举一个例子:

源文件A,名字是str.c :

#include<stdio.h>
#include"add.h"

int main2() {
	int x = 1, y = 4;
	int sum = Add(x, y);
	printf("%d", sum);
	return 0;
}

源文件B,名字是add.c :

#include<stdio.h>

int Add(int x, int y) {
	return x + y;
}

要主动添加的头文件C,名字是add.h(这个一般和头文件相同) :

#ifndef __ADD_H_// if not define __XX_X_
#define __ADD_H_

int Add(int x, int y);//这里是函数的申明

#endif

这个是格式,理解一下:第一行发现没有定义的话,如果定义过的话,就不用定义了,避免了重复定义

函数的递归

什么是递归

函数调用自身的一种编程技巧(recursion)

主要的思维:化大为小,一层一层的拨

我觉得可以想象成一个倒立的金字塔,最底下一层是开放的,上面几层都有权限不能开放,递归的过程就是向上开锁的过程

练习1:

编写函数逐个打印出数字“1234”中的 1 , 2, 3,4
#include<stdio.h>

void print(int i) {
	if (i > 9)
	{
		print(i/10);
	}
	printf("%d\n", i%10);
}

int main() {
	unsigned int i = 1234;
	//通过调用自定义print函数来完成1,2,3,4输出
	/*
	第一次把1234分成“123”和4
	继续分“12"和”3“”4“
	再继续”1“2”3“4”
	这可是由大化小的编程思想
	*/
	print(i);


	return 0;
}

解题思路:

由大化小,设置权限,层层递推!

练习2:

通过自己写的my_strlen起到strlen的作用,输出字符串的个数,用两种方式

提示:一种是创建临时变量,一种不创建

#include<stdio.h>

int my_strlen1(char * );
int my_strlen2(char *);
int main() {
	char arr[] = "superzkx";
	int len1 = my_strlen1(arr);//这是通过临时变量求的函数
	int len2 = my_strlen2(arr);//这是第二种方式
	printf("%d\n", len1);
	printf("%d\n", len2);

	return 0;
}

int my_strlen1(char* arr) {//思想是通过保存一个临时变量
	int coust = 0;
	while (*arr != '\0') {
		*arr++;
		coust++;
	}
	return coust;
}

int my_strlen2(char* arr) {//这是指针往后一个个指,第一步化成1+"uperzkx"...
	if (*arr != '\0') {
		return 1 + my_strlen2(arr + 1);
	}
	return 0;
}

由此可见,递归将原来的while换成了if,其中的return 其实起到的是while的作用

练习3:

函数计算n!的值

#include<stdio.h>

int main() {
	int n;
	int sum1, sum2;
	printf("请输入要计算阶乘的数");
	scanf("%d", &n);
	sum1 = factorial_1(n);
	sum2 = factorial_2(n);
	printf("sum1==%d,sum2==%d", sum1, sum2);
	return 0;
}

int factorial_1(int n) {//循环的方法
	int i;
	int sum = 1;
	for (i = 1; i <= n; i++) {
		sum = sum * i;
	}
	return sum;
}
int factorial_2(int n) {//递归的方法
	if (n == 1)
		return 1;
	else if (n > 1) {
		return n * factorial_2(n - 1);

	}
}

可以看出 循环 和 递归 其实是可以互相表示的

练习4:

计算斐波那契数列(不算栈溢出)

#include<stdio.h>

int Fibo1(int n);
int Fibo2(int n);

int main() {
	int n;
	int sum1, sum2;
	printf("请输入要计算Fibo的数");
	scanf("%d", &n);
	sum1 = Fibo1(n);
	sum2 = Fibo2(n);
	printf("sum1== %d,sum2== %d", sum1, sum2);
	return 0;
}

//普通的递归方法
int Fibo1(int n) {
	if (n == 1)
		return 1;
	else if (n == 2)
		return 1;
	else
		return Fibo1(n - 1) + Fibo2(n - 2);
}

int Fibo2(int n) {
	int a = 1;
	int b = 1;
	int c = 0;
	if (n == 1) {
		return a;
	}
	if (n == 2) {
		return b;
	}
	while (n > 2) {
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
	//1  1  2  3  5  8  13  21  34
	//a  b  c  
	//   a  b  c
}

经典递归问题:

汉诺塔

#include<stdio.h>

void Hanoi(int n, char A, char B, char C);

int main() {
	int n =0;
	char A = 'A';
	char B = 'B';
	char C = 'C';
	printf("请输入汉诺塔的层数(目标是将A柱移动到C柱)\n");
	scanf("%d", &n);
	
	Hanoi(n,A,B,C);
	return 0;
}

void Hanoi(int n,char A, char B ,char C ) {
	if (n == 1) {
		printf("将%c-->%c\n",A,C);
	}
	else {
		Hanoi(n - 1, A, C, B);//将前n-1个	从 A 通过C 全部移到B
		printf("%c-->%c\n",A,C);//然后A最后一个大的到C
		Hanoi(n - 1, B, A, C);//最后B通过A到C

	}
}

主要思想:n>=2时(n>=3)时更明显,把前n-1个甜甜圈看成一个整体,实际上重复的就是n=2时候的操作

就是!

将前n-1个 从 A 通过C 全部移到B

然后A最后一个大的到C

最后B通过A到C

简简单单 KO!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 10:32:07  更:2021-07-23 10:34:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 17:14:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码