C语言递归算法实现经典例题

一.递归

1.什么是递归

递归是一种编程技术,它通过在函数内部反复调用自身来解决问题。当一个程序调用自己时,这就称为递归调用。递归可以有助于简化某些算法的实现和理解。在递归过程中,每个调用都会将一些数据保存在栈上,直到递归结束后才能被处理并弹出栈。

递归通常有两个部分:基本情况和递归情况。基本情况是在函数执行之前判断是否需要递归,如果不需要,则直接返回结果。递归情况是函数需要递归时,它会调用自身,但是传入的参数通常会有所不同,以便最终能够达到基本情况而结束递归。

虽然递归可以使代码更加简洁,但是需要注意的是,在一些情况下,它可能会导致性能问题或者栈溢出等问题。因此,在编写递归代码时,需要仔细考虑算法的边界条件和递归深度等因素。

2.递归函数

递归函数是一种函数,它在其定义中调用自身。通常情况下,递归函数包含两个部分:基本情况和递归情况。

基本情况是指在递归函数中需要判断是否需要终止递归的条件。当满足这个条件时,递归就会停止。

递归情况是指在递归函数中需要调用自身的情况。在每次调用时,函数的参数都应该有所不同,以便最终能够达到基本情况而停止递归。

递归函数通常用于处理树形结构、图形结构或其他类型的嵌套结构数据。例如,在二叉树中查找某一个值,就可以使用递归函数来实现。

3.说明

虽然递归算法比较简单,但是它是一种编程的思想,在解决部分问题时,它非常适用。并且他一般作为一种工具,搭配其他思想一起使用。它是C语言数据结构与算法中最简单的算法,这里举几个例子来学会使用它。

二.斐波那契数列

1.问题描述

斐波那契数列是一个经典的数学问题,由0和1开始,之后的每一项都是其前面两项的和。也就是说,斐波那契数列的前几个数是:0、1、1、2、3、5、8、13、21、34……依次类推。

斐波那契数列在自然界中有很多应用,比如植物的叶子排列、蜂窝的构造等等。除此之外,在计算机科学领域内,斐波那契数列也有着广泛的应用,例如在排序算法、密码学等领域。

斐波那契数列的通项公式是:F(n) = F(n-1) + F(n-2),其中F(0)=0,F(1)=1。根据这个公式可以使用递归函数或循环语句来实现求斐波那契数列的第n项。

2.思路

像这种可以求出通项公式的数列是我们平时典型的递归函数运用,通项公式可以定义为函数,它的第一个值一般是我们的递归函数出口。所谓递归函数的出口就是结束递归的标志。

现在理清思路后,我们来用代码完成求斐波拉契数列的第n项:

3.C语言代码

#include <stdio.h>

int fibonacci(int n) {
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    else
        return fibonacci(n - 1) + fibonacci(n - 2);
}

int main() {
    int num, i;
    printf("Enter the number of terms: ");
    scanf("%d", &num);
    printf("Fibonacci series terms are:\n");
    for (i = 0; i < num; i++) {
        printf("%d ", fibonacci(i));
    }
    printf("\n");
    return 0;
}

三.汉诺塔

1.问题描述

该问题的主要材料包括三根高度相同的柱子和一些大小及颜色不同的圆盘,三根柱子分别为起始柱A,辅助柱B及目标柱C。

**操作规则:**每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于任意杆上。

wUhV.jpg

2.分析

汉诺塔是一种经典的递归问题,它涉及到将一组不同大小的圆盘从一个柱子移动到另一个柱子。以下是汉诺塔的具体过程:

  1. 将所有圆盘从起始柱子上除最下面一个圆盘之外的其他圆盘全部移动到中间柱子。
  2. 将最下面的圆盘从起始柱子上移动到目标柱子上。
  3. 将中间柱子上除了最下面的圆盘之外的其他圆盘全部移动到目标柱子上。

在完成这三个步骤时,需要遵守以下规则:

  1. 一次只能移动一个圆盘。
  2. 大圆盘不能放在小圆盘上面。

通过递归调用上述步骤,可以将所有的圆盘从起始柱子移动到目标柱子。由于每次递归都会将一个圆盘从起始柱子移动到目标柱子,因此每个圆盘最多只会被移动一次,所以总共需要移动2^n - 1 次(n 表示圆盘的数量)。

3.C语言代码

#include <stdio.h>

void hanoi(int n, char A, char B, char C) {
    if (n == 1) {
        printf("Move disk 1 from %c to %c\n", A, C);
    } else {
        hanoi(n-1, A, C, B);
        printf("Move disk %d from %c to %c\n", n, A, C);
        hanoi(n-1, B, A, C);
    }
}

int main() {
    int n = 3; // 将3个盘子从A移动到C
    hanoi(n, 'A', 'B', 'C');
    return 0;
}

四.子集问题

1.问题描述

子集问题(Subset):给定一个含有n个元素的集合S,求出S的所有子集。可以使用递归实现。

2.思路分析

子集问题是一个基本的组合问题,它涉及到从一个给定的集合中选择一些元素组成新的集合。这个问题在计算机科学和数学中非常常见,解决子集问题可以帮助我们更好地理解组合问题和算法设计。

下面是一个简单的思路分析:

  1. 首先,我们需要确定如何表示集合。在大多数编程语言中,集合通常是用数组或列表来表示的。

  2. 接着,我们需要考虑如何生成所有可能的子集。一种常见的方法是使用递归算法。

  3. 对于递归算法,我们需要考虑以下几点:

    a. 基本情况:当集合为空时,只有一个空集。

    b. 递归情况:对于非空集合,我们可以选择将第一个元素包含在子集中或者不包含在子集中,然后对剩余的元素进行递归处理。

  4. 在递归过程中,我们需要维护一个当前子集的列表,并在每次递归结束后将其添加到结果集合中。

  5. 最后,我们可以返回结果集合,其中包含了原始集合的所有可能子集。

需要注意的是,由于子集问题的解空间非常大,因此在实际应用中,需要根据具体的场景进行优化,以减少时间和空间复杂度。

3.C语言代码

下面是一个使用C语言递归实现子集问题的示例代码:

#include <stdio.h>

void subset(int set[], int subset[], int n, int k, int start, int curr){
    if (curr == k) {
        printf("{");
        for (int i = 0; i < k; i++) {
            printf("%d ", subset[i]);
        }
        printf("}\n");
        return;
    }
    for (int i = start; i < n; i++){
        subset[curr] = set[i];
        subset(set, subset, n, k, i+1, curr+1);
    }
}

int main() {
    int set[] = {1, 2, 3};
    int n = sizeof(set)/sizeof(set[0]);
    int subset[n];
    for (int i = 0; i <= n; i++) {
        subset(set, subset, n, i, 0, 0);
    }
    return 0;
}

该代码中,subset函数使用了递归实现。其中,set表示原始集合,subset表示当前子集,n表示原始集合的大小,k表示当前子集的大小,start表示遍历起始位置,curr表示当前子集中元素的个数。

在函数中,首先判断当前子集是否已达到目标大小 k,如果已经达到则输出该子集,并返回上一层递归。否则,从遍历起始位置开始循环原始集合,将元素依次加入当前子集,并对剩余元素进行递归处理。

main 函数中,我们遍历所有可能的子集大小,并调用 subset 函数进行求解。最终结果会依次输出到标准输出。

五.归并排序

1.问题描述与分析

归并排序(Merge Sort)是一种基于分治思想的高效排序算法,通过将待排序数组递归地拆分为两个子数组,对每个子数组进行排序,然后将两个有序的子数组合并成一个有序的数组,最终得到排序完成的整个数组。

具体而言,归并排序的过程可以分为三个步骤:

  1. 分割:将待排序数组从中间位置划分为左右两个子数组,递归地对左右两个子数组进行分割,直到每个子数组只包含一个元素。
  2. 归并:将两个有序的子数组合并成一个有序的数组,直到所有子数组都被合并为一个完整的有序数组。
  3. 返回:返回排序完成的数组。

2.C语言代码

下面是用 C 语言递归实现归并排序的代码:

#include <stdio.h>
#include <stdlib.h>

void merge(int *arr, int l, int m, int r) {
    int i, j, k;
    int n1 = m - l + 1;
    int n2 = r - m;

    int L[n1], R[n2];

    for (i = 0; i < n1; i++)
        L[i] = arr[l + i];
    for (j = 0; j < n2; j++)
        R[j] = arr[m + 1 + j];

    i = 0;
    j = 0;
    k = l;
    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            arr[k] = L[i];
            i++;
        } else {
            arr[k] = R[j];
            j++;
        }
        k++;
    }

    while (i < n1) {
        arr[k] = L[i];
        i++;
        k++;
    }

    while (j < n2) {
        arr[k] = R[j];
        j++;
        k++;
    }
}

void mergeSort(int *arr, int l, int r) {
    if (l < r) {
        int m = l + (r - l) / 2;

        mergeSort(arr, l, m);
        mergeSort(arr, m + 1, r);

        merge(arr, l, m, r);
    }
}

int main() {
    int arr[] = {38, 27, 43, 3, 9, 82, 10};
    int n = sizeof(arr) / sizeof(arr[0]);
    
    mergeSort(arr, 0, n - 1);

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

在上面的代码中,merge 函数用于将两个有序子数组合并为一个有序数组,mergeSort 函数用于递归地分割和排序子数组。

六.说明

新星计划:数据结构与算法,@西安第一深情,创作打卡1!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《Java并发编程实战》课程笔记(一)

并发领域的全景图 并发编程的三个核心问题 并发编程可以总结为三个核心问题&#xff1a;分工、同步、互斥。 分工指的是如何高效地拆解任务并分配给线程&#xff1b; Java SDK 并发包里的 Executor、Fork/Join、Future 本质上都是⼀种分工方法。除此之外&#xff0c;并发编程…

rsync远程同步

rsync介绍 rsync简介 rsync&#xff08;Remote Sync&#xff0c;远程同步&#xff09; 是一个开源的快速备份工具&#xff0c;可以在不同主机之间镜像同步整个目录树&#xff0c;支持增量备份&#xff0c;并保持链接和权限&#xff0c;且采用优化的同步算法&#xff0c;传输前…

阿里拆了中台,中台还有未来吗?

hi&#xff0c;我是熵减&#xff0c;见字如面。 近日&#xff0c;阿里在继年初3月份的16N的战略变革的基础上&#xff0c;对持续建设和运营8年的中台的调整终于落地了。 阿里对中台的这一举措&#xff0c;引发了外界对于中台战略是否还有意义的大量质疑和讨论。 甚至有人将中台…

ov2640子设备视频操作详细分析

ov2640子设备视频操作详细分析 文章目录 ov2640子设备视频操作详细分析ov2640_subdev_video_ops视频操作ov2640_s_stream开始流ov2640_g_fmt 获取格式ov2640_s_fmt设置格式ov2640_try_fmt尝试格式ov2640_cropcap裁剪能力ov2640_g_crop获取裁剪ov2640_enum_fmt枚举格式ov2640_g_…

六级备考26天|CET-6|仔细阅读|考研英语2023年英语(一)|8:20~10:00

text1 4/5 text2 3/5 text3 2/5 text4 3/5 12/20 目录 text 1 1. 重点词汇 2. 原文 3. 题目 text 1 1. 重点词汇 sympathise / ˈsɪmpəθaɪz / vi.同情&#xff1b;吊唁&#xff1b;共鸣 &#xff08;等于 sympathize&#xff09; ener…

黑客入门教程从零基础入门到精通,看完这一篇就够了

学前感言: 1.这是一条坚持的道路,三分钟的热情可以放弃往下看了. 2.多练多想,不要离开了教程什么都不会了.最好看完教程自己独立完成技术方面的开发. 3.有时多google,baidu,我们往往都遇不到好心的大神,谁会无聊天天给你做解答. 4.遇到实在搞不懂的,可以先放放,以后再来解决…

Scrum的执行过程及产品Backlog梳理的目的、时间、内容

Scrum的迭代运行过程 产品Backlog梳理 目的&#xff1a; •对下个Sprint的需求进行需求细节梳理和精化&#xff0c;识别技术风险和依赖&#xff0c;完成估算和优先级排序。 时间&#xff1a; •本Sprint开始后第6天&#xff0c;2小时以内 。 内容&#xff1a; •理解需求…

手把手教你用Python调用彩云机器翻译API

一、引言 彩云这个小而美的机器翻译一直很低调&#xff0c;它让人眼前一亮的是之前我们分享的网页翻译插件&#xff0c;可以把外文网站翻译成英中对照的样式&#xff0c;便于我们学习。之前我们也写过文章介绍过&#xff1a; PythonFan&#xff1a;如何用Google翻译英文网页成…

PyTorch RNN的原理及其手写复现。

PyTorch RNN的原理及其手写复现。 0、前言代码实现记忆单元(考虑过去的信息)分类包括&#xff1a;1.RNN 2.GRU 3.LSTM模型类别&#xff1a;1.单向循环(左到右) 2.双向循环&#xff08;考虑未来信息&#xff09; 3.多层单向或双向循环优缺点应用场景具体公式 0、前言 先给出代码…

单位、家庭建筑物电气、电子设备防雷举措

前 言 在现实的学习、工作、生活中&#xff0c;有时会面对自然灾害、重特大事故、环境公害及人为破坏等突发事件&#xff0c;为了控制事故的发展&#xff0c;就不得不需要事先制定应急预案。那要怎么制定科学的应急预案呢﹖下面是小编为大家整理的单位、住宅建筑物、电子电气防…

如何搭建一个高效、可靠的积分商城系统?

互联网购物的普及&#xff0c;积分商城系统已经成为商家和消费者之间互动的一种常见方式。它不仅可以帮助商家增加品牌影响力&#xff0c;还可以提高顾客体验&#xff0c;从而增加销售额。下面就如何搭建一个高效、可靠的积分商城系统作一些简单介绍。 第一步&#xff1a;确定需…

DHTMLX Suite JS PRO 8.1.1 Crack

适用于现代 Web 应用程序的强大 JavaScript 小部件库 - DHTMLX 套件 用于创建现代用户界面的轻量级、快速且通用的 JavaScript/HTML5 UI 小部件库。 DHTMLX Suite 有助于推进 Web 开发和构建具有丰富功能的数据密集型应用程序。 DHTMLX Suite 是一个 UI 小部件库&#xff0c;用…

Spring Boot中使用Spring Batch处理批量任务

Spring Boot中使用Spring Batch处理批量任务 Spring Batch是Spring框架的一个模块&#xff0c;它提供了一组API和工具&#xff0c;用于处理批量任务。在本文中&#xff0c;我们将会介绍如何在Spring Boot中使用Spring Batch来处理批量任务。我们将会使用一个简单的示例来说明如…

Install Prometheus Monitoring On Kubernetes Cluster

目录 Node & Software & Docker Images Lists ​Prometheus introduction Download Kubernetes Prometheus Manifest Files Install Prometheus Monitoring Kubernetes Create a Namespace Create a Cluster Role And Binding It Create a Config Map Create…

二、CNNs网络架构-卷积分离网络架构

《A review of convolutional neural network architectures and their optimizations》论文指出AlexNet的优异性能证明了可以通过增加网络深度提高网络性能。随着网络层数的不断增加&#xff0c;不断增加的计算负担和不显著的性能提升使得更先进的网络架构成为另一个主要的研究…

搭建监控日志系统

在微服务或者集群架构中&#xff0c;一次请求的调用会跨多个服务&#xff08;web&#xff0c;mysql&#xff0c;feign等&#xff09;、多个模块&#xff08;用户模块&#xff0c;商品模块等&#xff09;、多个容器&#xff08;用户模块可能有多个实例&#xff09;&#xff0c;这…

Linux命令(21)之usermod

Linux命令之usermod 1.usermod介绍 usermod命令用来更改/etc/passwd或/etc/shadow文件下用户属性&#xff0c;包括但不限于shell类型、用户id&#xff0c;用户gid、家目录、锁定及解锁用户等等。 2.usermod用法 usermod [参数] [用户名] usermod常用参数 参数说明-u修改UID…

Restful接口开发与测试—接口测试

开发完接口&#xff0c;接下来我们需要对我们开发的接口进行测试。接口测试的方法比较多&#xff0c;使用接口工具或者Python来测试都可以&#xff0c;工具方面比如之前我们学习过的Postman或者Jmeter &#xff0c;Python脚本测试可以使用Requests unittest来测试。 测试思路…

四维轻云平台常见问题及解决方法

1、在地图中看不见加载的点云或倾斜摄影模型数据&#xff1f; 若点云或模型数据加载后&#xff0c;在地图中看不见&#xff0c;可能是地形的高度高于倾斜模型的高度&#xff0c;导致数据漂浮在空中或者在地形以下&#xff0c;可通过增加数据的移动值Y来调整点云或者模型数据的…

支付宝SDK接口调试- cpolar内网穿透工具实现公网地址调试(1)

文章目录 1.测试环境2.本地配置3. 内网穿透3.1 下载安装cpolar内网穿透3.2 创建隧道 4. 测试公网访问5. 配置固定二级子域名5.1 保留一个二级子域名5.2 配置二级子域名 6. 使用固定二级子域名进行访问 转发自cpolar内网穿透的文章&#xff1a;Java支付宝沙箱环境支付&#xff0…