数据结构(七)递归、快速排序

news2024/12/24 22:15:49

文章目录

  • 一、递归
    • (一)使用递归实现1~n求和
      • 1. 代码实现:
      • 2. 调用过程:
      • 3. 输出结果:
    • (二)青蛙跳台阶问题
      • 1. 问题分析
      • 2. 代码实现
      • 3. 输出结果
      • 4. 代码效率优化
      • 5. 优化后的输出结果
  • 二、快速排序
    • (一)概念
    • (二)基本思想
    • (三)排序流程
    • (三)代码实现

一、递归

递归就是在函数内部继续调用自身的逻辑。

注:

  1. 递归的本质就是函数调用,他并不是C语言程序结构的一种。
    C语言的程序结构只有三种:循序结构、分支(选择)结构、循环结构
  2. 每个递归必须有一个出口,否则函数无限次调用下去,会把内存资源耗尽,导致堆栈溢出,出现段错误

(一)使用递归实现1~n求和

1. 代码实现:

#include <stdio.h>

//计算 1~n 的求和结果 并返回
int my_sum(int n){
    if(1 == n) return 1;
    return my_sum(n-1) + n;
}

int main(int argc, char const *argv[])
{
    int ret = my_sum(100);
    printf("sum = %d\n", ret);
    return 0;
}

2. 调用过程:

以n=5为例,
首先在main函数中调用my_sum(5)
my_sum(5)的返回值是my_sum(4)+n,
因此会继续调用my_sum(4),my_sum(4)的返回值是my_sum(3)
继续调用my_sum(3),my_sum(3)的返回值是my_sum(2)
继续调用my_sum(2),my_sum(2)的返回值是my_sum(1)
当n==1时,即是递归函数的出口,返回1给my_sum(2),
my_sum(2)的返回值即是2+1=3,返回3给my_sum(3),
my_sum(3)的返回值是3+3=6,返回6给my_sum(4),
my_sum(4)的返回值就是6+4=10,返回10给my_sum(5),
最后得到my_sum(5)的结果就是10+5=15,返回15给main函数。

3. 输出结果:

在这里插入图片描述

(二)青蛙跳台阶问题

共有10阶台阶,青蛙每次只能跳1阶或者2阶
问:青蛙跳上这10阶台阶,共有多少种跳法?

1. 问题分析

跳上10阶台阶的方法等于从第8阶台阶跳上10阶和从第9阶台阶跳上10阶的方法之和,跳上9阶台阶的方法等于从第8阶台阶和从第7阶台阶跳上9阶的方法之和,然后依次类推…
当计算跳上1阶台阶的方法时,就是1种,跳上2阶台阶的方法就是2种,这时就是递归函数的出口

2. 代码实现

#include <stdio.h>

//定义一个全局变量用于记录函数调用次数
int count = 0;
//功能:计算跳上n阶台阶的跳法之和 返回计算的结果
int func(int n){
    count++;
    //递归的出口
    if(1 == n) return 1;
    if(2 == n) return 2;
    return func(n-1) + func(n-2);
}

int main(int argc, const char *argv[])
{
    int ret = 0;
    ret = func(10);
    printf("ret = %d\n", ret);
    printf("count=%d\n",count);
    return 0;
}

3. 输出结果

在这里插入图片描述

4. 代码效率优化

如果只是用递归,会有大量重复运算,效率会比较低
可以以空间换时间,保存已经计算过的值来提高效率

#include <stdio.h>

#define NUM_JUMP 10 //台阶数量
//定义一个全局变量用于记录函数调用次数
int count = 0;
//定义一个数组用于保存调用函数的值,保存跳上每阶台阶的方法
int sum[NUM_JUMP]={0};//数组的值全部初始化为0

int my_jump(int n){
    count++;
    if(n==1) return 1;
    if(n==2) return 2;
    if(sum[n]) return sum[n]; //当sum[n]不为空时,说明已经计算过该值,可以直接返回
    //如果sum[n]==0时,说明该值没计算过,计算该值并保存到sum数组中
    sum[n]=my_jump(n-1)+my_jump(n-2);
    return sum[n];
}

int main(int argc, char const *argv[])
{
    int ret = my_jump(10);
    printf("jump = %d\n", ret);//89
    printf("count = %d\n",count);
    return 0;
}

5. 优化后的输出结果

在这里插入图片描述
可见优化后的函数调用次数远远小于优化前的函数调用次数,牺牲部分空间换来效率的提高

二、快速排序

(一)概念

快速排序相当于对冒泡排序的一个优化,也是基于交换的排序算法
时间复杂度 O(nlogn)

(二)基本思想

通过一趟排序,将待排序数据分成两部分,其中一部分数据都比另一部分小,而这两部分数据的内部不要求有序;
然后再对这两部分数据做同样的操作,也各自分成一大一小两部分,依次类推,直到整个数据组有序

(三)排序流程

定义两个下标变量,分别指向待排序的数组段的头和尾
以下图为例:
在这里插入图片描述
定义一个flag变量记录左侧第一个元素flag=arr[low](为了编程方便,也可以记录右侧第一个元素),然后从右向左开始依次比较flag和数组元素的大小
注:此处不要写成flag=arr[0]; 因为之后要对左右半边分别递归使用该函数,当对右半边排序时,应该使flag等于右半边的最左侧的数
如果flag<arr[high],就执行high- -,即下标high向左移动
在这里插入图片描述
如果flag>arr[high],就执行arr[low]=arr[high],low++,但是前提条件是low<high
在这里插入图片描述
此时再从左往右依次比较flag和arr[low]的大小
如果flag>arr[low],就执行low++
在这里插入图片描述
如果flag<arr[low],就执行arr[high]=arr[low],high- -,但是前提条件是low<high
在这里插入图片描述

循环上述两个步骤直到low==high时,将arr[low]=flag或者arr[high]=flag
此时flag左边都是比flag小的数,flag右边都是比flag大的数,但是两侧无序
在这里插入图片描述
之后再对左半边和右半边分别排序
此处仅以右半边为例,左半边同理,只是low和high的值不同。
右半边:low=5,high=9(左半边:low=0,high=3)
在这里插入图片描述
首先使flag=arr[low],此处为7
然后判断flag<arr[high]? 如果小于,就执行high- -
在这里插入图片描述

如果大于就执行arr[low]=arr[high],low++
在这里插入图片描述
之后判断flag>arr[low]? 如果大于,就执行low++
如果小于就执行arr[high]=arr[low],high- -
在这里插入图片描述
直到low==high时,arr[low]=flag或者arr[high]=flag
在这里插入图片描述
左半边同理,此处不再赘述。

(三)代码实现

#include <stdio.h>

int print(int *arr,int len){
    if(NULL==arr) return -1;
    for(int i=0;i<len;i++){
        printf("%d ",arr[i]);
    }
    putchar(10);
    return 0;
}

int my_sort(int *arr,int low,int high){
    if(NULL==arr) return -1;
    int flag=arr[low];
    while(low < high){
        while(flag<arr[high]&&low<high){
            high--;
        }
        if(low<high){
            arr[low]=arr[high];
            low++;
        }
        while(flag>arr[low]&&low<high){
            low++;
        }
        if(low<high){
            arr[high]=arr[low];
            high--;
        }
    }
    arr[low]=flag;
    return low;
}

int quick_sort(int *arr,int low,int high){
    if(NULL==arr) return -1;
    if(low < high){
        int ret=my_sort(arr,low,high);
        quick_sort(arr,low,ret-1);
        quick_sort(arr,ret+1,high);
    }
    return 0;
}

int main(int argc, char const *argv[]){
    int arr[10]={5,2,3,10,7,1,4,9,6,8};
    printf("排序前:\n");
    print(arr,10);

    printf("排序后:\n");
    quick_sort(arr,0,9);
    print(arr,10);
    
    return 0;
}

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

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

相关文章

STM32系列-STM32介绍

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” STM32介绍 STM32介绍 ST&#xff1a;指的是意法半导体 M&#xff1a;指定微处理器 32&#xff1a;表示计算机处理器位数 ARM分成三个系列&#xff1a; Cortex-A&#xff1…

PostgreSQL数据库提权

前面讲述了mysql、SqlServer、Redis数据库相关的提权方式&#xff0c;有兴趣的也可以去看看。 这里讲的postgreSQL数据库提权就是任意命令执行漏洞(CVE-2019-9193)。 目录 数据库简介 漏洞原理 影响版本 漏洞利用 利用前提 漏洞复现 复现准备 复现过程 漏洞修复 数据…

基于C#开发web网页管理系统模板流程-主界面管理员入库和出库功能完善

前言 紧接上篇->基于C#开发web网页管理系统模板流程-主界面管理员录入和编辑功能完善-CSDN博客 本篇将完善主界面的管理员入库和出库功能&#xff0c;同样的&#xff0c;管理员入库和出库的设计套路适用于动态表的录入和编辑 首先还是介绍一下本项目将要实现的功能 &#xf…

【aI】LiveKit Agents Playground

demo 是跑在 playground中的。 语音助手demo 可以语音对话 概念 Concepts Agent: A function that defines the workflow of a programmable, server-side participant. This is your application code. Worker: A container process responsible for managing job queuing …

业内宝刊!影响因子3连涨,OA可选,Elsevier旗下这本SSCI解救你的选刊纠结症

【SciencePub学术】今天小编给大家带来了一本经济类的高分优刊解读&#xff0c;隶属于Elsevier出版社&#xff0c;JCR1区&#xff0c;中科院2区&#xff0c;影响因子高达4.8&#xff0c;且实时影响因子还在持续上涨中&#xff0c;领域相符的学者可着重考虑&#xff01; Emergin…

使用 Flask 实现异步请求处理

文章目录 为什么需要异步请求处理&#xff1f;在 Flask 中实现异步请求处理使用 Flask-Cors 扩展 总结 在开发 Web 应用程序时&#xff0c;异步请求处理是提高性能和并发能力的重要方法之一。Flask 是一个轻量级的 Web 框架&#xff0c;它提供了易于使用的工具来实现异步请求处…

【CCF-CSP】202309-1 202309-2 坐标变换

坐标变换&#xff08;其一&#xff09; 代码&#xff1a; #include <bits/stdc.h> using namespace std; int main(){int n,m,x,y,sumx0,sumy0;cin>>n>>m;for(int i1;i<n;i){cin>>x>>y;sumxx,sumyy;}for(int i1;i<m;i){cin>>x>&…

深入解析三层架构:构建稳定高效的软件系统

概述 顾名思义&#xff0c;三层架构分为三层&#xff0c;分别是“数据访问层”、“业务逻辑层”、“表示层”。 数据访问层&#xff1a;数据访问层在作业过程中访问数据系统中的文件&#xff0c; 实现对数据库中数据的读取保存操作。 表示层&#xff1a;主要功能是 显示数据和…

易查分小程序 学生成绩管理小程序

亲爱的老师们&#xff0c;是不是每次成绩公布后&#xff0c;家长们的连环夺命call让你头大&#xff1f;担心孩子们的成绩信息安全&#xff0c;又想快速分享给家长&#xff0c;这可咋整&#xff1f;别急&#xff0c;易查分小程序来帮忙啦&#xff01; 安全有保障 智能验证码&a…

Java+IDEA+SpringBoot药物不良反应ADR智能监测系统源码 ADR智能化监测系统源码

JavaIDEASpringBoot药物不良反应ADR智能监测系统源码 ADR智能化监测系统源码 药物不良反应&#xff08;Adverse Drug Reaction&#xff0c;ADR&#xff09;是指在使用合格药品时&#xff0c;在正常的用法和用量下出现的与用药目的无关的有害反应。这些反应往往因药物种类、使用…

Vite + Vue3 + Electron 创建打包桌面程序

10 【Vite Vue3 Electron 创建打包桌面程序】 1.使用 Vite 构建 Electron 项目 1.1 创建 Vite 应用&#xff0c;安装 Electron 依赖 创建一个 Vite 项目 npm init vitelatest安装 Electron 相关依赖 npm install electron -D npm install vite-plugin-electron -D 1.2 在…

网络工程师---第四十三天

1、网络地址转换请简述DNS服务器迭代查询与递归的区别&#xff1f; 2、请从技术方面简述RAIDO、RAID1、RAID3、 RAID5的特点&#xff1f; 3、请从层次结构、部署设备和功能配置方面描述层次化的网络结构&#xff1f; 4、请简述IPSECVPN和AH和ESP的区别&#xff1f; 5、请简述ID…

5G工业数采网关是什么?天拓四方

随着工业4.0时代的到来&#xff0c;数字化、网络化、智能化成为工业发展的新趋势。在这个过程中&#xff0c;5G工业数采网关作为一种关键设备&#xff0c;发挥着越来越重要的作用。本文将详细解析5G工业数采网关是什么&#xff0c;以及它在工业领域中的应用和重要性。 一、5G工…

Android Graphics图形栈SurfaceFlinger之间各种Layer以及对应Buffer之间的关系

Android Graphics图形栈SurfaceFlinger之间各种Layer以及对应Buffer之间的关系 SurfaceFlinger layer之间的对应关系

云衔科技:为什么推荐使用zoho crm客户管理系统?

在当今快速变化的商业环境中&#xff0c;企业对高效、智能化的客户关系管理&#xff08;CRM&#xff09;系统的需求日益增长。Zoho CRM&#xff0c;作为全球领先的企业级CRM解决方案提供商&#xff0c;凭借其全面的功能、高度的可定制性、以及无缝集成的生态系统&#xff0c;成…

4、xss-labs之level4、lecel5

一、level4 1、测试分析 level4跟之前的3一样的思路&#xff0c;闭合value的值&#xff0c;但是通过双引号闭合&#xff0c;然后使用onclick的属性弹窗绕过 输入3的payload&#xff1a; 2、所以构造payload payload&#xff1a;"οnclickalert(1)// 二、level5 1、测…

适用于Android的最佳数据恢复软件

如果您的 Android 设备崩溃&#xff0c;您需要找到一种方法来取回您的数据。幸运的是&#xff0c;有许多数据恢复程序可以帮助您恢复丢失的文件。有些是免费的&#xff0c;而另一些则需要付费。这是适用于Android设备的最佳数据恢复软件列表。 什么是数据恢复软件&#xff1f; …

基于盲源分离和半盲源分离的心电信号伪影消除方法(MATLAB 2018)

心电信号是通过测量放置在人体皮肤上的电极之间的电位差来获取的&#xff0c;其本身具有信号微弱、频段低、不稳定等特性。因此ECG信号在实际采集时极易受到不同噪声的影响&#xff0c;这会造成心电图本身的波形形态特征的失真&#xff0c;从而导致错误诊断和对患者的不当治疗。…

新建一个esri_sde_gists的服务

需求 新建一个esri_sde_gists的服务 步骤&#xff1a; 需要拷贝ora11gexe目标为新的目录&#xff0c;例如ora11gexe_gists 运行drivers找到etc下面的services文件&#xff0c;添加端口5152&#xff1a; 检查sde的library并创建&#xff1a; CREATE or REPLACE LIBRARY ST_S…

数据驱动的UI艺术:智能设计的视觉盛宴

数据驱动的UI艺术&#xff1a;智能设计的视觉盛宴 引言 在当今这个数据泛滥的时代&#xff0c;大数据不仅仅是一种技术手段&#xff0c;它更是一种艺术形式。当大数据遇上UI设计&#xff0c;两者的结合便催生了一种全新的艺术形式——数据驱动的UI艺术。本文将探讨如何将数据…