图解函数递归、数组详解

news2024/11/15 9:13:14

目录

一.修炼必备

二.图解递归的执行过程

三.数组

3.1 一维数组

3.2 二维数组

3.3 数组的共同问题


一.修炼必备

  1.入门必备:VS2019社区版,下载地址:Visual Studio 较旧的下载 - 2019、2017、2015 和以前的版本 (microsoft.com)

  2.趁手武器:印象笔记/有道云笔记

  3.修炼秘籍:牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网 (nowcoder.com)

  4.雷劫必备:leetcode 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 

  注:遇到瓶颈怎么办?百度百科_全球领先的中文百科全书 (baidu.com)

二.图解递归的执行过程

  1.什么是递归?

   ——递归是指将复杂的问题转换成简单的问题进行解决,即是”大事化小,小事简单明了“,在编程语言中,常使用在函数进行递归调用(函数自身调用自身

  2.递归的条件

   1)递归有限制条件,一旦递归到这个限制条件就停止递归

   2)每一次递归都会接近这个限制条件

   3)进行设计递归函数的时候注意要设置好限制条件,不然会”死归了“

  3.一个小case快速了解递归

   1)递归代码

#include <stdio.h>

void printNum(unsigned int num)
{
    if (num > 9)
    {
        printNum(num / 10);//获取下一位
    }
    printf("%u ", num % 10);//得到个位的数
}

int main()
{
    unsigned int num = 0;
    scanf("%u", &num);

    printNum(num);
    return 0;
}

   2)图解:

  4.图解递归过程

   1)求阶乘

#include <stdio.h>

int fac(int n)
{
    //n <= 1是限制条件
    if (n <= 1)
        return 1;
    else
        return n * fac(n - 1);//每次递归逐渐接近限制条件
}

int main()
{
    int n = 0;
    scanf("%d", &n);

    int res = fac(n);
    printf("%d\n", res);
    return 0;
}

   图解过程:

   2)第n个斐波那契数

#include <stdio.h>

int Fib(int n)
{
    //n <= 2:限制条件
    if (n <= 2)
        return 1;
    else
        return Fib(n - 1) + Fib(n - 2);
}

int main()
{
    int n = 0;
    scanf("%d", &n);

    int fib = Fib(n);
    printf("%d\n", fib);
    return 0;
}

   图解过程:

三.数组

3.1 一维数组

  1.什么是数组?

   —— 数组是一组相同类型元素的集合

  2.数组创建和初始化

   1)数组的创建:数据类型 + 数组名 +[]

int arr[10];//整型数组,数据类型:int 数组名:arr

double num[10];//浮点型数组,数据类型:double 数组名:num

char ch[10];//字符数组,数据类型:char 数组名:ch

注:[]中只能是常量表达式(c99之前,c99后可以使用【变长数组:允许使用变量给数组的大小进行指定,但是数组不能进行初始化】

   2)数组的初始化:数据类型 数组名[数组的大小] = {初始化值1, 初始化值2, ……};

i.完全初始化:数组完全初始化可不指定数组大小,数组大小是初始化值的个数

int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

ii.不完全初始化:数组只初始化部分的数据,剩下部分的值按照数据类型判断默认值:int : 0 double : 0.0 ch : '\0'(本质还是0)

int arr[10] = { 1,2,3 };//0

double num[10] = { 1.0,2.0 };//0.0

char ch[10] = { 'a','b','c' };//'\0'

注:如果数组不想指定大小,那么进行完全初始化,若是不想指定大小又不进行初始化,则会导致程序崩溃

  3.请思考以下问题

//请思考以下代码的不同
char ch[] = "abc";
char ch1[3] = { 'a','b','c' };

  4.数组的使用

   —— 数组是通过下标来进行使用的, 数组的下标可以准确的指定其值(需要使用[]操作符)

#include <stdio.h>

//数组的使用 - 逆序输出数组中的值
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int len = sizeof(arr) / sizeof(arr[0]);//计算数组的大小
    int i = 0;

    for (i = len-1; i >= 0; i--)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

  5.数组的细节讨论

   1)数组的下标是从0开始的

#include <stdio.h>

int main()
{
    //数组的下标是从0开始的
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    printf("%d\n", arr[0]);//arr[0]是数组的第一个元素
    return 0;
}

   2)数组在内存中是连续存储的

#include <stdio.h>

//数组在内存中是连续存储的
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int len = sizeof(arr) / sizeof(arr[0]);
    int i = 0;

    for (i = 0; i < len; i++)
    {
        printf("&arr[%d] = %p\n", i, &arr[i]);//&arr[i]取出arr[i]的地址
    }
    return 0;
}

   图解:

3.2 二维数组

  1.什么是二维数组

   —— 二维数组是以一个行和列组成的矩阵,二维数组可以看成两个一位数组的组合

  2.二维数组的创建和初始化

   1)二维数组的创建:数据类型 数组名[第一维大小][第二维大小];

#include <stdio.h>

int main()
{
    //int arr[3][3];//创建二维数组
    int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };//创建二维数组并初始化
    return 0;
}

   2)二维数组的初始化

完全初始化:把数组中的所有值都进行初始化

不完全初始化:只进行初始化数组中部分的值,剩下的值是默认值

注:二维数组在已经初始化的情况下,只可以省略第二维,不能省略第一维

#include <stdio.h>

int main()
{
    //完全初始化的两种形式
    int arr1[3][3] = { 1,2,3,4,5,6,7,8,9 };//形式1:不加{}
    int arr2[3][3] = { {1,2,3},{4,5,6},{7,8,9} };//形式2:加{}
    //解释:{}代表第一维的长度,arr2中第一维有3个,初始化中有3个{}

    //不完全初始化的两种形式
    //说明,前面的1,2,3占据了第一维空间,4占据了第二维的第一个内存空间,剩下的是默认值
    int arr3[3][3] = { 1,2,3,4 };//形式1
    int arr4[3][3] = { {1,2,3}, {4} };//形式2

    //不初始化:二维数组中全部是默认值
    int arr5[3][3];//全部是默认值:0
    
    //省略第二维
    int arr6[][3] = { {1,2,3},{4,5,6},{7,8,9} };       
    return 0;
}

  3.二维数组的使用

   ——二位数组也是通过下标进行访问数组中的元素

#include <stdio.h>

int main()
{
    int arr[3][3];//创建数组
    int i, j;
    for (i = 0; i < 3; i++)
        for (j = 0; j < 3; j++)
            scanf("%d", &arr[i][j]);

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

  4.思考以下的问题

   1)如何求二维数组的长度

   2)如何求二维数组中第一维的长度

   3)如何求二维数组中第二维的长度

#include <stdio.h>

int main()
{
    //二维数组的长度
    int arr[3][4] = { 1,2,3,4,5,6,7,8,9 };
    int len1 = sizeof(arr) / sizeof(arr[0][0]);//二维数组的长度
    printf("%d\n", len1);//12

    //二维数组中第二维的长度
    int len2 = sizeof(arr[0]) / sizeof(arr[0][0]);
    printf("%d\n", len2);//4

    //二维数组中第一维的长度
    //int len3 = len1 / len2;//法一
    int len3 = sizeof(arr) / sizeof(arr[0]);//法二
    printf("%d\n", len3);//3
    return 0;
}

  5.二维数组在内存中的存储

   ——跟一维数组一样,二维数组在内存中是连续存储的

#include <stdio.h>

//二维数组在内存中的存储
int main()
{
    int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };
    int i, j;
    int len1 = sizeof(arr) / sizeof(arr[0]);//第一维的大小
    int len2 = sizeof(arr[0]) / sizeof(arr[0][0]);//第二维的大小

    for (i = 0; i < len1; i++)
    {
        for (j = 0; j < len2; j++)
        {    
            //&:取出对应值的地址
            printf("arr[%d][%d] = %p\n", i, j, &arr[i][j]);
        }
    }
    return 0;
}

   图解:

3.3 数组的共同问题

  1.数组越界

   ——假设数组有n个元素,其下标的范围是0~n-1,数组的下标是从0开始的,最后一个下标是n-1

#include <stdio.h>

//数组越界
int main()
{
    int arr[5] = { 1,2,3,4,5 };
    int i = 0;

    //错误,数组的下标范围是0-4,而不是0-5
    for (i = 0; i <= 5; i++)
    {}
    return 0;
}

  2.数组作为数组参数

   1)若是以数组名作为参数,那么则为传址调用

   2)若是以数组元素作为参数,看数组元素前面是否有&符合,若是有,则为传址调用,若是没有,则为传值调用

#include <stdio.h>

void PrintNum(int x)
{
    x = 11;
    printf("%d\n", x);
}

void Print(int* arr, int len)
{
    int i = 0;
    for (i = 0; i < len; i++)
    {
        printf("%d ", *(arr + i));
    }
    printf("\n");
}

void ChangeNum(int* x)
{
    *x = 11;
}



int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int len = sizeof(arr) / sizeof(arr[0]);

    PrintNum(arr[0]);//传值:数组元素作为实参
    Print(arr, len);//传址:数组名作为实参
    ChangeNum(&arr[0]);//传址:数组元素的地址作为实参
    Print(arr, len);//传址:数组名作为实参
    return 0;
}

  3.冒泡排序

   1)思想:将数列中的相邻两个值进行比较,如果顺序有误则交换这两个值的位置,然后再用这个值进行比较,一直比较到最后一个值,得到第一个数中最大/最小的值,在进行下一趟的比较

   2)流程详解

   3)代码详解

#include <stdio.h>

//冒泡排序
void bubble_sort(int arr[], int len)
{
    int i, j;
    //趟数
    for (i = 0; i < len - 1; i++)
    {
        //一趟比较的次数
        for (j = 0; j < len - i - 1; j++)
        {
            //比较
            if (arr[j] > arr[j + 1])
            {
                int temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
            }
        }
    }
}

int main()
{
    int arr[10] = { 10,5,1,7,3,9,6,4,2,8 };
    int len = sizeof(arr) / sizeof(arr[0]);//数组长度

    bubble_sort(arr, len);

    int i = 0;
    for (i = 0; i < len; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

   4)执行结果:

  4.数组名详解

   1)数组名是数组首元素的地址(两个例外)

   2)sizeof(数组名)计算的是整个数组的大小,sizeof内部放数组名,数组名表示整个数组

   3)&数组名:取出的是整个数组的地址

#include <stdio.h>

int main()
{
    int arr[10] = { 1,2,3,4,5 };

    //sizeof(数组名)计算的是整个数组的大小
    printf("%d\n", sizeof(arr));//40个字节的大小
    //数组名是数组首元素的地址(两个例外)
    printf("%p\n", arr);
    printf("%p\n", &arr[0]);//数组首元素的地址
    //& 数组名:取出的是整个数组的地址
    printf("%p\n", &arr);
    printf("%p\n", &arr + 1);//跳过了40个字节
    return 0;
}

   图解: 

  !!!恭喜你,突破至筑基二层!!!

  注:由于CSDN中的排本不够美观,若是想要看更美观的排版,请参加有道云笔记:有道云笔记

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/175792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视频文缩略图SDK:GleamTech VideoUltimate Crack

Video Reader and Thumbnailer for .NET Core 和 .网络框架 读取地球上的任何视频文件格式。逐帧读取视频文件。生成有意义的缩略图。 VideoUltimate是最快&#xff0c;最简单的.NET视频阅读器和缩略图器&#xff0c;可以读取任何视频文件格式 在地球上。它允许您逐帧读取视频…

C++ 一文解决 数据库ODB 安装/调试/使用的问题

引用&#xff1a; ODB Download (codesynthesis.com) Installing ODB on Linux/UNIX (codesynthesis.com) 缘起&#xff1a; 在开发过程中发现&#xff0c;现有的软件缺乏持久层&#xff08;Persistence Layer&#xff09;&#xff0c;即专注于实现数据持久化应用领域的某个…

广义零样本学习的转移增量

摘要&#xff1a;零样本学习&#xff08;ZSL&#xff09;是一种成功的从未知类中对对象进行分类的范例。然而&#xff0c;它在广义零样本学习&#xff08;GZSL&#xff09;设置中遭受严重的性能降级&#xff0c;即以识别来自可见类和不可见类的测试图像。在本文中&#xff0c;为…

C语言-qsort函数基本使用

个人主页&#xff1a;平行线也会相交 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 平行线也会相交 原创 收录于专栏【C/C】 先来看一下qsort函数的介绍&#xff1a; Compare 函数的返回值描述>0elem1将被排在elem2前面0elem1等于elem2<0elem1 将被…

LeetCode刷题模版:171-174、179

目录 简介171. Excel 表列序号172. 阶乘后的零173. 二叉搜索树迭代器174. 地下城游戏【未理解】179. 最大数结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,…

Redis学习【1】之Nosql概述

文章目录一 从技术发展探究使用Nosql的原因1.1 单机Mysql时代1.2 Memcached&#xff08;缓存&#xff09; MySQL 垂直拆分[读写分离]1.3 MySQL主从读写分离1.4 分表分库 水平拆分 Mysql 集群1.5 如今时代1.6 使用NoSQL的原因二 Nosql初识2.1 NoSQL的特点【解耦】三 NoSQL的四…

树状数组的原理和区间和

目录 一、前言 二、树状数组的原理 1、杂论 2、从二叉树到树状数组 3、神奇的 lowbit(x) 操作 4、tree[ ]数组&#xff1a;将一维信息转换为树形信息存储 5、基于 tree[ ] 的计算 6、tree[]的更新&#xff08;要加lowbit&#xff09; 三、树状数组的应用 1、单点修改…

流媒体方案之Nginx

1.Nginx可以作为流体服务器。2三种web服务器的比较3.推流端: FFmpeg使用RTMP协议向Nginx推流拉流端: •VLC播放器使用RTMP或HTTPFLV协议从Nginx拉流•浏览器使用HTTPFLV协议从Nginx拉流(安装flv.js)4.有两种方法&#xff1a;下载源码&#xff0c;手工编译使用Buildroot&#xf…

Redis分布式锁 | 黑马点评

目录 一、分布式锁概述 二、基于Redis的分布式锁 1、思路分析 2、初级版本 3、误删问题 4、改进分布式锁 5、原子性问题 6、使用Lua脚本解决原子性问题 7、setnx实现分布式锁存在问题 三、Redisson 1、Redisson快速入门 2、Redisson可重入锁原理 3、Redisson可重试…

从某一点出发沿任意一方向旋转矩阵计算思考与实现

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 上期讲到 绕任一向量旋转矩阵计算思考与实现 点击前往 点击前往 问题提出 之前讲到绕任一向量旋转矩阵实现&#xff0c;原来的向量都是从原点出发&#xff0c;现在把…

Ajax面试题目

更多Ajax面试题目可以查看专栏内容 1.AJAX应用和传统Web应用有什么不同&#xff1f; 传统的web前端与后端的交互中&#xff0c;浏览器直接访问Tomcat的Servlet来获取数据。Servlet通过转发把数据发送给浏览器。当我们使用AJAX之后&#xff0c;浏览器是先把请求发送到XMLHttpR…

Swift之struct二进制大小分析

随着Swift的日渐成熟和给开发过程带来的便利性及安全性&#xff0c;京喜App中的原生业务模块和基础模块使用Swift开发占比逐渐增高。本次讨论的是struct对比Class的一些优劣势&#xff0c;重点分析对包体积带来的影响及规避措施。 一、基础知识 1、类型对比 引用类型&#xff…

独立看门狗与窗口看门狗

定义 看门狗的本质是一个定时器&#xff0c;在启动后&#xff0c;需要在一定时间内再给它一个信号&#xff0c;俗称“喂狗”&#xff0c;如果没有按时“喂狗”&#xff0c;说明MCU可能处于非正常状态&#xff0c;这时看门狗就向MCU发送个复位信号&#xff0c;使整个系统重启&a…

51单片机数码管显示

文章目录前言一、数码管简介二、数码管原理图三、数码管显示原理四、静态数码管代表编写五、动态数码管总结前言 这篇文章将介绍数码管的显示其中包含了动态数码管和静态数码管两种。 一、数码管简介 数码管其实就是由多个发光二极管封装在一起组成“8”字型的器件当分别点亮…

【数据结构】超详细——堆的实现

一、堆的概念及性质 1.1 什么是堆&#xff1f; 堆是一种完全二叉树&#xff08;具体在下一章讲述&#xff09;&#xff0c;若二叉树的深度h&#xff0c;除了第h层外其余各层节点数满了&#xff0c;只有第h层缺额且该层结点靠左&#xff1b;任何一个数组可以看作完全二叉树&…

【14】C语言_函数简介

目录 1、C语言中函数的分类: 2、库函数 3、自定义函数 1、C语言中函数的分类: 1.库函数 2.自定义函数 2、库函数 为什么会有库函数? 1.我们知道在我们学习C语言编程的时候&#xff0c;总是在一个代码编写完成之后迫不及待的想知道结果&#xff0c;想把这个结果打印到我们的屏…

ESP32设备驱动-LX1972可见光传感器驱动

LX1972可见光传感器驱动 1、LX1972介绍 LX1972 是一款低成本硅光传感器,其光谱响应非常接近人眼。专利电路在 520nm 处产生峰值光谱响应,IR 响应小于峰值响应的 5%,高于 900nm。 光电传感器是一个 PIN 二极管阵列,具有线性、准确和非常可重复的电流传递函数。 芯片上的…

扫盲-从零开始搭建阿里云流媒体服务器/音视频编解码/

1.基础概念 2.简单模式-HTTP文件服务器 存储采用NAS&#xff0c;服务器配置 采用FASTDFS (192条消息) Linux新手入门系列&#xff1a;FastDFS单机部署一键安装脚本_IT小胖豆的博客-CSDN博客 有几个坑&#xff1a; 常用命令&#xff1a; tail -20f /usr/local/nginx/logs/er…

3小时精通opencv(三)图片裁剪与形状绘制

3小时精通opencv(三)图片裁剪与形状绘制 参考视频资源:3h精通Opencv-Python 文章目录3小时精通opencv(三)图片裁剪与形状绘制图片裁剪绘制形状绘制直线绘制矩形绘制圆形绘制文字整体代码图片裁剪 图片裁剪不需要使用opencv中特有的函数, 对于opencv中读取到的图像, 直接当做矩…

15. python数据类型转换

1. 隐式类型转换 - 自动完成 在隐式类型转换中&#xff0c;Python 会自动将一种数据类型转换为另一种数据类型&#xff0c;不需要我们去干预。 (1) 以下实例中&#xff0c;我们对两种不同类型的数据进行运算&#xff0c;较低数据类型&#xff08;整数&#xff09;就会转换为较…