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

文章目录

  • 一、递归
    • (一)使用递归实现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};//数组的值全部初始化为0int 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);//89printf("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.mzph.cn/news/843355.shtml

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

相关文章

Euler 欧拉系统介绍

Euler 欧拉系统介绍 1 简介重要节点与版本EulerOS 特色EulerOS 与 openEuler 区别联系Euler 与 HarmonyOS 区别联系 2 openEuler特色支持 ARM&#xff0c;x86&#xff0c;RISC-V 等全部主流通用计算架构融入 AI 生态嵌入式实时能力提升引入 OpenHarmony 一些突出功能 参考 1 简…

将 KNX 接入 Home Assistant 之二 准备软件

写在前面&#xff1a; 在KNX官网也有关于 Home Assistant 的教程&#xff0c;地址是 Get started with Home Assistant x KNX 需要的东西是 a KNX IP Interface or Routera Raspberry Pian SD Card at least 32 GB 安装 Home Assistant 系统 下载镜像&#xff1a; 地址&…

idea中git检出失败

之前clone好好的&#xff0c;今天突然就拉取不下来了。很多时候是用户凭证的信息没更新的问题。由于window对同一个地址都存储了会话。如果是新的会话&#xff0c;必须要更新window下的凭证。 然后根据你的仓库找到你对应的账户&#xff0c;更新信息即可。

反射器和联邦实验

拓扑 要求 IP配置 [R1-GigabitEthernet0/0/0]ip add 12.0.0.1 24 [R1-LoopBack0]ip add 192.168.1.1 24 [R1-LoopBack1]ip add 10.0.0.1 24[R2-GigabitEthernet0/0/0]ip add 12.0.0.2 24 [R2-GigabitEthernet0/0/1]ip add 172.16.0.1 21 [R2-GigabitEthernet0/0/2]ip add 17…

(IDEA修改Java版本)java: 警告: 源发行版 X 需要目标发行版 X

搜索关键词&#xff1a;一致、发行 错误信息 其他错误&#xff1a; java: 错误: 不支持发行版本 6 java: -source 1.5 中不支持 lambda 表达式 (请使用 -source 8 或更高版本以启用 lambda 表达式) 思路 有两个地方要检查&#xff0c;JDK版本保持一致即可。 比如统一用JDK8或…

FM1800隧道广播插播控制器

隧道广播插播控制器是一款群载波&应急广播插播控制器采用SDR软件无线电技术&#xff0c;产生独立的插播信号与“群载波”信号&#xff0c;本设备可通过软件无线电技术将音频信号调制成调频载波或“群载波”信号&#xff0c;分别送入插播主机&#xff0c;实现隧道广播远端机…

20240528解决飞凌的OK3588-C的核心板可以刷机不能连接ADB的问题

20240528解决飞凌的OK3588-C的核心板可以刷机不能连接ADB的问题 2024/5/28 16:34 OS&#xff1a;Linux R4/Buildroot 硬件接了3条线出来&#xff0c;一直可以刷机&#xff0c;但是链接ADB异常。 【总是链接不上】 Z:\OK3588_Linux_fs\kernel\arch\arm64\boot\dts\rockchip\OK3…

Android11 事件分发流程

在Android 11 输入系统之InputDispatcher和应用窗口建立联系一文中介绍到&#xff0c;当InputDispatcher写入数据后&#xff0c;客户端这边就会调用handleEvent方法接收数据 //frameworks\base\core\jni\android_view_InputEventReceiver.cpp int NativeInputEventReceiver::h…

炒黄金怎么追单?-融知财经网

在黄金投资领域,当市场行情呈现出有利的走势时,许多交易者会选择追加下单以扩大盈利。追单作为一种投资策略,旨在利用市场波动获取额外收益。然而,要想在追单中取得成功,需要掌握一定的技巧和策略。融知财经网给介绍黄金交易中追单的一些关键技巧,帮助投资者理智追单,稳健获利。…

线性插值的频域特性

1、抽取和插值的简单说明 抽取和插值是变采样过程中常用的两种手段&#xff0c;其中抽取的目的是降低数据的采样率&#xff0c;以降低对系统存储深度或计算量的要求。插值的目的是提高数据的采样率&#xff0c;以提高系统的计算精度。 M M M倍抽取通常是通过每隔 M M M…

Docker安装Nginx 并实现通过nginx部署静态网址

Docker镜像就是一个只读的模板&#xff0c;可以用来创建Docker容器。 例如&#xff1a;一个镜像可以包含一个完整的centos操作系统环境&#xff0c;里面仅安装了mysql、nginx等或用户需要的其他应用程序。 Docker提供了一个非常简单的机制来创建镜像或者更新现有的镜像&#…

GTD时间管理法

Part 1. What is GTD? | 什么是GTD&#xff1f; GTD is a framework that enhances focus and productivity. Through techniques such as capturing all tasks in a trusted system and breaking down complex projects into actionable items, GTD allows individuals to co…

美业系统SaaS收银系统源码-顾客在系统付款了但系统未显示怎么办?美业系统实测

美业SaaS系统 连锁多门店美业收银系统源码 多门店管理 / 会员管理 / 预约管理 / 排班管理 / 商品管理 / 活动促销 PC管理后台、手机APP、iPad APP、微信小程序 1. 提供门店名称、付款凭证和会员手机号 2. 到订单明细查询&#xff0c; 按门店名称和会员手机号查询看是否有相…

百度智能云千帆AppBuilder升级!开放多源模型接入,思考模型再次加速!

>>【v0.5.4版本】 上线时间&#xff1a;2024/5/24 关键发版信息&#xff1a; 大模型优化&#xff1a;开放多源模型接入&#xff0c;思考模型再次加速&#xff01; Agent思考模型&#xff1a;新增AppBuilder专用版模型ERNIE Speed-AppBuilder&#xff0c;自主任务规划…

【软考】下篇 第15章 面向服务架构设计理论与实践

目录 一、SOA定义二、微服务微服务优势微服务与SOA对比微服务架构模式方案微服务设计约束 三、SOA参考架构四、SOA设计的标准要求五、SOA设计原则六、SOA设计模式七、SOA实施 一、SOA定义 面向服务的体系结构 (Service-Oriented Architecture,SOA), 从应用和原理的角度看&…

openLayers加载wms图层并定位到该图层

openLayers定位到wms图层 我们的wms是加载geoserver发布的服务&#xff0c;wms加载的图层是没法通过layer.getSource().getExtent()来获取到extents&#xff08;边界&#xff09;的&#xff1b;实现思路是通过postgis的函数(st_extent(geom))来获取extents; 返回前端后格式化一…

23-LINUX--TCP连接状态

一.TCP服务的特点 传输层协议主要有两个&#xff1a;TCP 协议和 UDP协议。TCP 协议相对于UDP协议的特点是&#xff1a;面向连接、字节流和可靠传输。 使用TCP协议通信的双方必须先建立连接&#xff0c;然后才能开始数据的读写。双方都必须为该连接分配必要的内核资源&a…

lammps案例:reaxff势模拟Fe(OH)3高温反应过程

大家好&#xff0c;我是小马老师。 本文分享一个reaxff反应势的案例。 该案例主要模拟Fe(OH)3在高温下的反应过程&#xff0c;主要代码来自lammps自带的案例。 lammps自带案例没有产物输出&#xff0c;故在此基础上稍加修改&#xff0c;增加了产物输出命令。 反应过程如下图…

JavaWeb开发 3.Web开发 Web前端开发 ③ HTML、CSS

没有一朵花&#xff0c;一开始就是一朵花 —— 24.5.28 HTML、CSS知识在博主前端专栏&#xff0c;可以对照博客大致进行了解 https://blog.csdn.net/m0_73983707/category_12654678.htmlhttps://blog.csdn.net/m0_73983707/category_12654678.html

232转Profinet网关接扫码枪与PLC通讯在物流分拣线上的应用

一、背景 随着生活节奏的加快&#xff0c;网络购物需求非常大&#xff0c;从而造成快递站需要快速提取快递信息已达到快速出站的效果&#xff0c;这就用到了扫码枪&#xff0c;扫码枪作为采集设备&#xff0c;能够迅速准确地读取货物信息。并将数据传输至PLC控制器&#xff0c…