筑基二层 —— 图解函数递归、数组详解

news2024/9/25 11:16:24

目录

一.修炼必备

二.图解递归的执行过程

三.数组

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)图解:

6a1a53d969f54d3cb876bd81f501e605.png

 

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

   图解过程:

66d944a113da4bce9c506e2b292b7ca1.png

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

   图解过程:

59767d728cda46acafb891fa8a78a785.png

 

三.数组

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

   图解:

8583ced024fd481196b3a3d1576649f5.png

 

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

   图解:

c69c6b5919df42a6ada6878c1cab7fa6.png

 

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)流程详解

9246fcbdea9d4564b3d37c6dc4cb24d0.gif

   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)执行结果:

28cf304ec55b4b759b1a34945545fac4.png

 

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

   图解: b73d0d378157442e841c503ff312194f.png

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

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

 

 

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

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

相关文章

I.MX6ULL裸机开发笔记7:汇编点亮LED灯

一、vscode调整 加入汇编插件ARM vscode权限受限&#xff08;因为Ubuntu中的文件有的是root权限创建的&#xff0c;vscode以普通用户打开的话没有操作权限&#xff09;chmod 修改文件或者文件夹权限 二、编程步骤 使能GPIO时钟设置引脚复用位GPIO设置引脚属性&#xff08;上下…

深入跨域问题(3) - 利用 JSONP 解决跨域

目录 1.简单例子&#xff1a; 2.基本实现 3.JSONP 与 CORS 的对比 什么是跨域&#xff0c;在这篇文章内部就不再讲述了&#xff0c;本文主要着重于实现 JSONP 。 script 标签&#xff1a; 根据同源策略的限制&#xff0c;在 端口&#xff0c;域名&#xff0c;协议 这三者 …

AX7A200教程(3): DDR3突发读写

上一个章节我们新建工程&#xff0c;然后进行基本的初始化操作&#xff0c;这个章节将在上个工程的基础上进行突发读写因ddr3读写部分控制信号比较多&#xff0c;所以ddr3读写控制模块比较复杂&#xff0c;本章节着重于一个256位数据的突发读写&#xff0c;ddr读写控制模块暂不…

【JavaWeb】前端开发三剑客之CSS(下)

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【JavaWeb】 ✈️✈️本篇内容:CSS的深度学习&#xff01; &#x1f680;&#x1f680;代码托管平台github&#xff1a;JavaWeb代码存放仓库&#xff01; ⛵⛵作者…

(考研湖科大教书匠计算机网络)第二章物理层-第一、二节:物理层基本概念和传输媒体

文章目录一&#xff1a;物理层概念二&#xff1a;物理层传输媒体&#xff08;1&#xff09;导引型传输媒体A&#xff1a;同轴电缆B&#xff1a; 双绞线C&#xff1a;光纤①&#xff1a;光纤通信②&#xff1a;光纤D&#xff1a;电力线&#xff08;2&#xff09;非导引型传输媒体…

day22 多线程02

1.线程池 1.1 线程状态介绍 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢&#xff1f;Java中的线程 状态被定义在了java.lang.Thread.State…

[ESP][驱动]ST7701S RGB屏幕驱动

ST7701SForESP ST7701S ESP系列驱动&#xff0c;基于ESP-IDF5.0&#xff0c;ESP32S3编写。 本库只负责SPI的配置&#xff0c;SPI设置屏幕两方面。由于RGB库和图形库的配置无法解耦&#xff0c;具体使用的RGB库&#xff0c;图形库需要自行配置添加。 SPI的指令&#xff0c;地…

操作系统真相还原_第5章第2节:内存分页机制

文章目录分段机制分页机制一级页表二级页表启用分页机制的过程启用分页机制(二级页表)详解程序include.incmbr.sloader.s写入硬盘启动bochs执行分段机制 分页机制 一级页表 二级页表 启用分页机制的过程 1、准备好页目录项及页表 2、将页表地址写入控制寄存器cr3 3、寄存器cr0…

【ArcGIS微课1000例】0059:三种底图影像调色技巧案例教程

三种调整影像底图效果的技术,让你的图纸清新脱俗,做出的图更美观! 文章目录 方法一:影像源类型调整方法二:符号拉伸类型设置方法三:影像分析模块设置方法一:影像源类型调整 这种方法是最基础、最简单的一种方法,可以调整的内容有限。当大家发现导入了影像,然后影像图…

Spring Batch 基本概念和运行示例

基本概念 Spring Batch是批处理框架。 作业(Job)是状态以及状态之间转换的集合。 作业里包含步骤&#xff08;Spring Bean&#xff09;&#xff0c;每一个步骤解耦到独立的处理器中&#xff0c;并负责自己的数据&#xff0c;把所需的业务逻辑应用到数据上&#xff0c;然后把数…

【React】组件的创建与事件绑定

&#x1f4d8;前言 &#x1f6a9;&#x1f6a9;&#x1f6a9; &#x1f48e;个人主页: 阿选不出来 &#x1f4a8;&#x1f4a8;&#x1f4a8; &#x1f48e;个人简介: 一名大二在校生,学习方向前端,不定时更新自己学习道路上的一些笔记. &#x1f4a8;&#x1f4a8;&#x1f4a…

C规范编辑笔记(十三)

往期文章&#xff1a; C规范编辑笔记(一) C规范编辑笔记(二) C规范编辑笔记(三) C规范编辑笔记(四) C规范编辑笔记(五) C规范编辑笔记(六) C规范编辑笔记(七) C规范编辑笔记(八) C规范编辑笔记(九) C规则编辑笔记(十) C规范编辑笔记(十一) C规范编辑笔记(十二) 正文&#xff…

CSS背景:背景色/背景图像/背景重复/背景附着/简写背景属性(一文搞懂)

目录 CSS背景 CSS 背景色 实例 其他元素 实例 不透明度 / 透明度 实例 使用 RGBA 的透明度 实例 CSS 背景图像 实例 实例 实例 CSS 背景重复 实例 实例 CSS background-repeat: no-repeat 实例 CSS background-position 实例 CSS 背景附着 实例 实例 C…

linux系统中利用QT实现视频监控的基本方法

大家好&#xff0c;今天主要和大家分享一下&#xff0c;如何利用QT实现视频监控的基本操作。 目录 第一&#xff1a;视频监控基本简介 第二&#xff1a;实验流程图 第三&#xff1a;视频监控之服务器 第四&#xff1a;视频监控之客户端实现 第一&#xff1a;视频监控基本简…

Java基础之《netty(30)—RPC调用流程分析》

一、RPC基本介绍 1、RPC&#xff08;Remote Procedure Call&#xff09;—远程过程调用&#xff0c;是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序&#xff0c;而程序无需额外的为这个交互作用编程。 2、两个或多个应用程序都分布在不同的…

Kettle(4):excel数据抽取到mysql

1 准备工作 1.1 准备Excel文件 我这边直接使用上一篇导出的excel:file_user.xls 1.2 创建数据库 在mysql中创建数据库 1.3 在kettle中加载MySQL驱动 Kettle要想连接到MySQL&#xff0c;必须要安装一个MySQL的驱动&#xff0c;就好比我们装完操作系统要安装显卡驱动一样。加…

CMMI之工程类

工程类过程域涵盖了工程学科所共有的开发与维护活动。工程类过程域的书写使用了通用的工程术语&#xff0c;这样&#xff0c;涉及产品开发过程&#xff08;如软件工程、机械工程等&#xff09;的任何技术学科都能够将其用于过程改进。工程类过程域还将不同工程学科的关联过程整…

分享111个ASP源码,总有一款适合您

ASP源码 分享111个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 111个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1Afx8CxZIGwcGWB6aUOssZg?pwdr81w 提取码&#x…

CPU缓存架构缓存一致性协议详解

一、CPU高速缓存&#xff08;Cache Memory&#xff09;1.1 CPU高速缓存CPU缓存即高速缓冲存储器&#xff0c;是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存&#xff0c;CPU直接从内存中存取数据要等待一定时间周期&#xff0c;Cache中保存着…

《你当像鸟飞往你的山》教育让你内心的山更高,更广

《你当像鸟飞往你的山》教育让你内心的山更高&#xff0c;更广 塔拉韦斯特弗&#xff0c;美国作家、历史学家。1986年生于美国爱达荷州的山区。自学考取杨百翰大学&#xff0c;2009年获得剑桥大学哲学硕士学位&#xff0c;2014年获剑桥大学历史学博士学位。2018年出版处女座《你…