Python 数学建模——ARMA 时间序列分析

news2024/12/28 6:58:21

文章目录

    • 前言
    • 使用前提
      • 平稳性检验
      • 白噪声检验
    • 用法
    • 代码实例
      • 第一步——平稳性分析
        • 方法一
        • 方法二
        • 方法三
      • 第二步——白噪声分析
      • 第三步——确定参数
      • 第四步——模型构建与检验
        • 检验模型效果
        • 预测未来数据

前言

  常见的时间序列分析方法有很多,之前介绍了一个稍微新颖的 Prophet 时间序列分析法,这个方法的好处是可以综合考虑节假日的影响(节假日可能导致异常值的出现),并站在不同的时间跨度上考量周际 ( T = 7 d ) (T=7\mathrm d) (T=7d)、月际 ( T = 30 d ) (T=30\mathrm d) (T=30d)、年际 ( T = 365 d ) (T=365\mathrm d) (T=365d) 的周期性及其影响。Prophet 还能考虑外生变量的影响,这是它的突出特点。详情请看博客:Python 数学建模——Prophet 时间序列预测_多变量prophet-CSDN博客。
  但是 Prophet 的缺点也很多,例如当时间序列不是“日期”的序列时,Prophet 将稍显逊色。本篇博客我们将介绍一个新的时间序列分析方法——ARMA 时间序列分析的使用方法

ARMA 的具体原理可以参考其他博客,本篇博客主要介绍 ARMA 的使用方法Python 实现

使用前提

  ARMA 模型进行时间序列分析,适合用于平稳非白噪声序列。对于非平稳序列应该使用 ARIMA 模型(即使用差分等方法,后面会稍作介绍),或者取对数等方式,转化为平稳序列进行分析。
  基于这个适用前提,任何一个时间序列在使用 ARMA 之前,都必须进行平稳性检验白噪声检验

平稳性检验

  检验一个时间序列的平稳性,有 3 3 3 种可行的检验方式。下面将逐一介绍。其中第三种基于假设检验的定量方法很好地摈弃了主观性,因此应该是平稳性检验的最佳选择。前两种方式可以用于数据可视化,带来有关平稳性的直接视觉冲击。

  1. 从时间序列上来看,有明显上升、明显下降趋势的为非平稳序列,稳定在一定范围附近的为平稳序列。
  2. 自相关图、偏自相关图上看,具有较强长期相关性(即大部分自相关系数的绝对值都较大,或者说远离0)的是非平稳序列,比如下面最左边的那张图。相对而言自相关系数的绝对值没那么大的,就具有短期相关性,是平稳序列,如下图右边两张图。

图片来自于参考文献。可以看到最左边图,阴影部分达到了 ± 0.75 \pm0.75 ±0.75,自相关系数的绝对值已经很大、严重偏离 0 0 0 了,说明后期的数据严重依赖于前期的数据,具有比较长期的相关性,不适合使用 ARMA。然而中间这张图,阴影部分在 ± 0.4 \pm0.4 ±0.4 范围左右,则可以认为没有长期相关性。右边这张图也是没有长期相关性。

  1. 基于假设检验的平稳性检验方法,或者说是单位根检验。Python 库提供的基于假设检验的方法statsmodels.tsa.stattools.adfuller,对一个时间序列给出 p p p 值,若 p < 0.05 p<0.05 p<0.05,则接受“序列是平稳序列”的原假设。

白噪声检验

  白噪声检验也是直接调用 Python 库提供的statsmodels.stats.diagnostic.acorr_ljungbox方法。这个方法基于假设检验给出一个 p p p 值,当 p < 0.05 p<0.05 p<0.05 时接受“序列是非白噪声数据”的原假设。

用法

  ARMA 模型有两个参数 p , q p,q p,q,要确定参数,考虑下面的两个指标:

  • AIC:赤池信息量准则(Akaike information criterion),定义为 A I C = n ln ⁡ σ ^ ε 2 + 2 ( p + q + 1 ) \mathrm{AIC}=n{{\ln{\hat{\sigma }}}_{\varepsilon }^{2}}+2(p+q+1) AIC=nlnσ^ε2+2(p+q+1)
  • BIC:贝叶斯信息量准则(Bayesian information criterion),定义为 B I C = n ln ⁡ σ ^ ε 2 + ( p + q ) ln ⁡ n \mathrm{BIC}=n{{\ln{\hat{\sigma }}}_{\varepsilon }^{2}}+(p+q)\ln{n} BIC=nlnσ^ε2+(p+q)lnn

  这两个指标都是关于 p , q p,q p,q 的函数,它们是研究者针对 ARMA 模型复杂度设计的惩罚项,用于避免过拟合问题。好的参数 p , q p,q p,q 应该要使得上面两个指标尽可能小
  确定参数是可以只用 AIC/BIC 其中一个,也可以混合起来用,实际操作中通过穷举一些 ( p , q ) (p,q) (p,q) 值,从中挑选最佳参数。即 ( p , q ) = argmin ⁡ p , q A I C ( p , q ) (p,q)=\operatorname{argmin}\limits_{p,q}\mathrm{AIC}(p,q) (p,q)=argminp,qAIC(p,q),或者 ( p , q ) = argmin ⁡ p , q B I C ( p , q ) (p,q)=\operatorname{argmin}\limits_{p,q}\mathrm{BIC}(p,q) (p,q)=argminp,qBIC(p,q)

代码实例

  有一份太阳黑子数据,展示了从 1700 1700 1700 1988 1988 1988 年每年太阳黑子的观测数量。部分如下所示:

yearcount
1700 1700 1700 5 5 5
1701 1701 1701 11 11 11
1702 1702 1702 16 16 16
1703 1703 1703 23 23 23
1704 1704 1704 36 36 36
1705 1705 1705 58 58 58

点击下载路径,Ctrl+S下载上表所示sunspots.csv表单。

第一步——平稳性分析

  这是一个“年份”的时间序列,不适合使用 Prophet 时间预测模型。考虑使用 ARMA,先进行平稳性分析。

方法一

基于方法一,可以画出时间序列,代码如下:

import pandas as pd, numpy as np
import statsmodels.api as sm
import matplotlib.pylab as plt
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
plt.rc('axes',unicode_minus=False)
plt.rc('font',family='SimHei'); plt.rc('font',size=16)
d=pd.read_csv('sunspots.csv'); dd=d['counts']
years=d['year'].values.astype(int)
plt.plot(years,dd.values,'-*');
plt.savefig("原始数据折线图.pdf")

  画出时间序列图如下图所示。肉眼观察图像,认为太阳黑子数量稳定在一定范围附近,没有明显上升或者明显下降的趋势,原序列基本平稳。

方法二

  基于方法二,我们还可以画自相关图和偏自相关图。代码如下所示:

# 接着上面的代码
ax1=plt.subplot(121); plot_acf(dd,ax=ax1,title='自相关',lags = len(dd) - 1)
ax2=plt.subplot(122); plot_pacf(dd,ax=ax2,title='偏自相关',lags = len(dd) - 1)
plt.savefig("原序列的自相关与偏自相关图.pdf")
# lags 参数是我自己加的,原代码里面没有,其含义应该是相关图横坐标的范围
# 如果不加 lags 参数,自相关、偏自相关图的横坐标就只到 25 左右,很不能说明问题

  画出结果如下图所示。自相关图蓝色阴影在 ± 0.4 \pm0.4 ±0.4 之内,偏自相关图几乎没有阴影。从而认为原序列没有很长的长期相关性,从而是平稳序列。

方法三

  基于方法三,我们可以调库,使用ADF方法得到置信因子 p p p 的值:

# 接着上面的代码
from statsmodels.tsa.stattools import adfuller as ADF
print(ADF(dd))
"""
结果如下,返回值依次为adf、pvalue、usedlag、nobs、critical values、icbest、regresults、resstore
(-2.3842262328920083, 0.1462380194095098, 8, 280, {'1%': -3.453922368485787, '5%': -2.871918329081633, '10%': -2.5723001147959184}, 2267.166855421211)

看出 pvalue = 0.1462380194095098
"""

  遗憾的是,这个最严谨的方法认为太阳黑子是非平稳序列,理论上原数据不适合使用 ARMA 预测。对于非平稳序列我们的处理手段是:差分,或者取对数。取对数就是将原数据 x i x_i xi 转换为 x ^ i = log ⁡ x i \hat x_i=\log x_i x^i=logxi,而一阶差分则是将原数据 x i x_i xi 转换为 x ^ i = x i − x i − 1 \hat x_i = x_i-x_{i-1} x^i=xixi1
  ARIMA 相比于 ARMA 的区别,就是引入了 n n n 阶差分,使得原来的非平稳序列 { x i } \{x_i\} {xi} 转变为平稳序列 { x ^ i } \{\hat x_i\} {x^i},从而继续使用 ARMA 进行时间序列分析。我们看一下太阳黑子一阶差分数据的平稳性

# 接着上面的代码
print(ADF(dd.diff().dropna()))
"""
(-14.076125927559811, 2.8827295545409215e-26, 7, 280, {'1%': -3.453922368485787, '5%': -2.871918329081633, '10%': -2.5723001147959184}, 2263.2365299490502)

可以看出 pvalue = 2.8827295545409215e-26,相当地平稳
"""

  结果相当平稳,因此可以使用太阳黑子的一阶差分数据进行时间序列分析,分析结果求前缀和得到原来的太阳黑子数据。下面我将分别使用原数据dd(虽然不适合用 ARMA,但还是使用着看看)以及它的一阶差分数据dd.diff().dropna()进行时间序列分析,然后对比它们的结果。

第二步——白噪声分析

  使用下面的代码,分别对原数据、一阶差分数据进行白噪声分析。结果显示,它们都不是白噪声数据。光看着一点,它们都符合 ARMA 使用条件。

# 接着上面的代码
from statsmodels.stats.diagnostic import acorr_ljungbox
print(acorr_ljungbox(dd,lags=1)) # 原数据
# 结果 (array([193.5490947]), array([5.34166945e-44]))
# 其中 pvalue = 5.34166945e-44 < 0.05,确定为非白噪声数据
print(acorr_ljungbox(dd.diff().dropna(),lags=1)) # 一阶差分数据
# 结果 (array([80.51235627]), array([2.88892777e-19]))
# 其中 pvalue = 2.88892777e-19 < 0.05,确定为非白噪声数据

第三步——确定参数

  需要确定参数 p , q p,q p,q。按照参考文献中的说法,我们需要把满足 0 ≤ p , q ≤ ⌊ n / 10 ⌋ 0\le p,q\le ⌊n/10⌋ 0p,qn/10 的参数全部尝试一遍,在这之中找出最好的参数对 ( p , q ) (p,q) (p,q) 。但是我们的数据横跨 289 289 289 年, ⌊ n / 10 ⌋ = 28 ⌊n/10⌋ = 28 n/10=28,这样时间开销太大了,程序会跑得很慢。
  实际上, ( p , q ) (p,q) (p,q) 太大就没必要尝试下去了。为了更快地跑出结果,我这里尝试 0 ≤ p , q < 6 0\le p,q<6 0p,q<6 的所有参数(也跑了很久),并且只使用 BIC 指标
  先确定原数据的参数:

# 接着上面的代码
bic_matrix = []  # BIC矩阵
for p in range(6):
    tmp = []
    for q in range(6):
        try:  # 存在部分报错,所以用try来跳过报错。
            tmp.append(sm.tsa.ARMA(dd, (p, q)).fit().bic)
        except:
            tmp.append(float("inf"))
    bic_matrix.append(tmp)
print(np.argmin(np.array(bic_matrix)))
# 结果为 26,即 p = 4,q = 2

  再试一试一阶差分数据的参数:

# 接着上面的代码
bic_matrix = []  # BIC矩阵
for p in range(6):
    tmp = []
    for q in range(6):
        try:  # 存在部分报错,所以用try来跳过报错。
            tmp.append(sm.tsa.ARMA(dd, (p, q)).fit().bic)
        except:
            tmp.append(float("inf"))
    bic_matrix.append(tmp)
print(np.argmin(np.array(bic_matrix)))
# 结果为 14,即 p = 2,q = 2

  至此,确定原数据 ARMA 的参数 p = 4 , q = 2 p=4,q=2 p=4,q=2,一阶差分数据的参数 p = 2 , q = 2 p=2,q=2 p=2,q=2

第四步——模型构建与检验

检验模型效果

  按照下面的代码训练模型:

# 接着上面的代码

################ 获取原数据的预测值 ################
zmd=sm.tsa.ARMA(dd,(4,2)).fit()
dhat=list(zmd.predict())
#################################################

############## 获取一阶差分数据的预测值 ##############
zmd2=sm.tsa.ARMA(dd.diff.dropna(),(2,2)).fit()
dhat2=list(zmd2.predict())
# 进行前缀和操作,恢复为原数据
dhat2.insert(0,dhat[0])
from itertools import accumulate
dhat2 = list(accumulate(dhat2))
##################################################

  上面获取的数据,是对已知的 1700 − 1988 1700-1988 17001988 年数据的拟合,用于检验模型的正确性的。实际上,在获取zmd对象后,可以调用zmd.summary()对此次 ARMA 模型训练结果进行总结。比如print(zmd.summary())的结果就是:

                              ARMA Model Results                              
==============================================================================
Dep. Variable:                 counts   No. Observations:                  289
Model:                     ARMA(4, 2)   Log Likelihood               -1197.676
Method:                       css-mle   S.D. of innovations             15.159
Date:                Sat, 14 Sep 2024   AIC                           2411.353
Time:                        15:20:12   BIC                           2440.684
Sample:                             0   HQIC                          2423.106
                                                                              
================================================================================
                   coef    std err          z      P>|z|      [0.025      0.975]
--------------------------------------------------------------------------------
const           49.7380      6.211      8.009      0.000      37.566      61.910
ar.L1.counts     2.8101      0.086     32.694      0.000       2.642       2.979
ar.L2.counts    -3.1179      0.218    -14.294      0.000      -3.545      -2.690
ar.L3.counts     1.5248      0.213      7.165      0.000       1.108       1.942
ar.L4.counts    -0.2366      0.080     -2.954      0.003      -0.394      -0.080
ma.L1.counts    -1.6480      0.057    -29.016      0.000      -1.759      -1.537
ma.L2.counts     0.7885      0.055     14.396      0.000       0.681       0.896
                                    Roots                                    
=============================================================================
                  Real          Imaginary           Modulus         Frequency
-----------------------------------------------------------------------------
AR.1            0.8639           -0.5664j            1.0330           -0.0924
AR.2            0.8639           +0.5664j            1.0330            0.0924
AR.3            1.0928           -0.0000j            1.0928           -0.0000
AR.4            3.6248           -0.0000j            3.6248           -0.0000
MA.1            1.0450           -0.4197j            1.1262           -0.0608
MA.2            1.0450           +0.4197j            1.1262            0.0608
-----------------------------------------------------------------------------

  这里面可能有一些比较重要的信息。接下来我们就原数据,原数据的预测数据、一阶差分数据的预测数据进行作图:

# 接着上面的代码
plt.figure(figsize=(10, 6))
plt.plot(years,dd,'-')
plt.plot(years,dhat,'--')
plt.plot(years,dhat2,'--')
plt.rcParams['font.family'] = 'KaiTi'
plt.legend(('原始观测值','原数据预测值','一阶差分数据预测值'))
plt.grid()
plt.show()

  作图结果如下所示。本不适合 ARMA 预测的原数据,预测后与原始观测值非常符合;而适合 ARMA 预测的一阶差分数据,进行前缀和操作后,预测结果反而非常糟糕。这并不是因为一阶差分数据拟合效果太差,而是它在通过前缀和操作变回原数据的过程中,误差不断积累变大,最终导致结果产生严重的偏离。
  手动差分数据不可取,要想对非平稳数据进行时间序列分析,还应用 ARIMA 模型合适。

经过尝试,对于原数据 { x i } \{x_i\} {xi},使用 x ^ i = ln ⁡ ( x + 0.02 ) \hat x_i=\ln(x+0.02) x^i=ln(x+0.02) (因为原数据中含有 0 0 0 值,不可直接取对数,故加 0.02 0.02 0.02)会通过平稳性分析 p = 0.03817 < 0.05 p=0.03817<0.05 p=0.03817<0.05)和白噪声分析,获取最佳参数 p = 2 , q = 4 p=2,q=4 p=2,q=4 且获取比较良好的拟合效果,有兴趣的读者可以尝试一下。使用这样的 { x ^ i } \{\hat x_i\} {x^i} 进行预测的结果如下图所示:

预测未来数据

  若要预测接下来的数据,可以用下面的代码(二选一,都行):

# 从已知数据的后一天开始预测
begin = d.shape[0]
# 预测 5 天
end = begin + 5
dnext = zmd.predict(begin, end)
print(dnext)  #显示预测值
"""结果如下:
289    139.440487
290    153.467594
291    143.350740
292    114.224154
293     76.024077
294     40.746472
"""

  或者可以这样:

# 预测后面 5 天的数据
dnext = zmd.forecast(5)
print(dnext[0])  #显示预测值
"""结果如下:
[139.44048728 153.46759385 143.35074018 114.22415414  76.02407734]
"""

  这里的zmd.forecast得到的数据分别是预测结果、标准误差、置信区间。dnext[0]只打印预测结果。
原理和代码参考文献:python之时间序列算法(ARMA)_python arma-CSDN博客

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

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

相关文章

55 mysql 的登录认证流程

前言 这里我们来看一下 mysql 的认证的流程 我们这里仅仅看 我们最常见的一个 认证的处理流程 我们经常会登录的时候 碰到各种异常信息 认证失败的大体流程 大概的流程是这样 客户端和服务器建立连接之后, 服务器向客户端发送 salt 然后 客户端根据 salt 将客户端传入的…

MySQL权限控制(DCL)

我的mysql里面的一些数据库和一些表 基本语法 1.查询权限 show grants for 用户名主机名;例子1&#xff1a;查询权限 show grants for heima%;2.授予权限 grant 权限列表 on 数据库名.表名 to 用户名主机名;例子2&#xff1a; 授予权限 grant all on itcast.* to heima%;…

<<编码>>第 12 章 二进制加法器--二进制加法器 示例电路

info::操作说明 鼠标单击逻辑输入切换 0|1 状态 另: 因节点较多, 为避免过多连线, 此处采用标签虚拟连接方式, 相同的标识符表示连接在一起 关于标签虚拟连接的介绍见该链接: https://book.xiaogd.net/usage-of-circuitjs/circuitjs-label-simplify-circuit.html primary::在线…

《订单来了2024中秋预订趋势报告》发布:截至9月13日,商家中秋预订率上涨42.73%,山西文化巡礼成顶流

# 截至9月13日&#xff0c;订单来了酒店民宿已突破16万&#xff0c;商家中秋假期平均预订率较9月8日上涨42.73%。 对比6天前&#xff0c;酒店商家中秋平均预订率增长38.85%&#xff0c;民宿商家增长38.10%。 1%的酒店民宿达成「连续3天满房」成就&#xff0c;4%商家预订率超…

terminator-gnome

gnome import os#启动节点指令变量 stere"ros2 launch stereo_c start.py" utils"ros2 launch task utils.launch.py" #tab标题 stere_title"stere_driver" utils_title"utils"#一个终端界面打开5个tab cmd1f"gnome-terminal --…

嵌入式软件黑盒测试技术与案例分析培训

黑盒测试&#xff0c;也称为基于需求的测试&#xff0c;是目前嵌入式软件领域普遍开展的一种测试过程。目前&#xff0c;随着人们对软件质量要求的不断提升&#xff0c;行业对软件测试和验证的要求也在不断提高&#xff0c;对测试的充分性和准确性要求越来越苛刻。当前行业内&a…

工作流技术(WorkFlow)

什么是工作流 1.使用编程语言完成一套固定的审批流程 例如请假审批流程 订单配送流程 入职&#xff0c;辞职审批流程 2.使用场景 业务类&#xff1a;合同审批流程、订单处理流程、出入库审批流程等。 行政类&#xff1a;请假流程、出差流程、用车流程、办公用品申请流程…

代理IP设置后IP不变?可能的原因及解决方法

在使用代理IP时&#xff0c;有时会遇到代理设置后IP地址却没有变化的情况。这种问题可能会让人感到困惑&#xff0c;但其实背后有多种原因。本文将详细探讨这些原因&#xff0c;并提供相应的解决方法&#xff0c;帮助你顺利解决问题。 可能的原因 代理IP设置后IP地址不变的原…

智慧人居视音频解决方案探究和技术实现

智慧人居技术背景 智慧人居是一种利用先进技术和智能化系统&#xff0c;旨在提升居住环境的舒适性、便捷性和安全性的新型居住模式。随着物联网、大数据、人工智能等技术的不断发展&#xff0c;智慧人居正朝着更加智能化、个性化、集成化的方向发展。 智慧人居通过集成各种智…

【数据结构与算法 | 灵神题单 | 合并链表篇】力扣2, 21, 445, 2816

1. 力扣2&#xff1a;两数相加 1.1 题目&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可…

房产销售系统:SpringBoot技术应用案例

第二章关键技术的研究 2.1相关技术 房产销售系统是在Java MySQL开发环境的基础上开发的。Java是一种服务器端脚本语言&#xff0c;易于学习&#xff0c;实用且面向用户。全球超过35&#xff05;的Java驱动的互联网站点使用Java。MySQL是一个数据库管理系统&#xff0c;因为它的…

Blender/3ds Max/C4D哪个软件好?

在3D建模和动画制作领域&#xff0c;Blender、3ds Max和Cinema 4D&#xff08;C4D&#xff09;都是备受赞誉的软件。每个软件都有其独特的优势和特点&#xff0c;选择哪个软件取决于用户的具体需求和个人偏好。今天&#xff0c;成都渲染101云渲染就来分析一些这三款软件的情况&…

滑动窗口算法—最小覆盖子串

题目 ”最小覆盖子串“问题&#xff0c;难度为Hard&#xff0c;题目如下&#xff1a; 给你两个字符串 S 和 T&#xff0c;请你在 S 中找到包含 T 中全部字母的最短子串。如果 S 中没有这样一个子串&#xff0c;则算法返回空串&#xff0c;如果存在这样一个子串&#xff0c;则可…

GANs-生成对抗网络

参考&#xff1a; https://mp.weixin.qq.com/s?__bizMjM5ODIwNjEzNQ&mid2649887403&idx3&snf61fc0e238ffbc56a7f1249b93c20690&chksmbfa0f632460e035f00be6cc6eb09637d91614e4c31da9ff47077ca468caad1ee27d08c04ca32&scene27 https://cloud.tencent.com…

pywinauto install ~

1. 下载最新的python, Download Python | Python.org 博主用的版本是&#xff1a; python-3.12.6-amd64.exe 2. 安装python. (略) 3. 配置环境变量&#xff1a; 点击环境变量&#xff0c;并编辑PATH变量&#xff0c; 后面3条是新加的。 4. 安装pywinauto, 打开CMD输入 pip …

转置卷积与反卷积的区分

transposed convolution&#xff08;转置卷积&#xff09;和deconvolution&#xff08;反卷积&#xff09;是两个完全不同的概念。 deconvolution为“inverse of convolution”、“inverse filter”&#xff0c;翻译为反卷积、解卷积。在信号处理中&#xff0c;反卷积是指从卷积…

一家电子元件企业终止,业绩规模小,疑似通过收购调节收入利润

贝特电子终止原因如下&#xff1a;首先&#xff0c;报告期内贝特电子营收较低&#xff0c;收购东莞博钺股权可能构成重大资产重组&#xff0c;且假如扣除报告期内来自东莞博钺的净利润&#xff0c;贝特电子的净利润恐怕不符合深交所上市标准&#xff1b;其次&#xff0c;交易所…

彩漩科技亮相第一届人工智能教育应用论坛,入选TOP30榜单,展示创新教育科技产品

近日&#xff0c;由中国教育发展战略学会人工智能与机器人教育专业委员会指导&#xff0c;北京教育信息化产业联盟主办的第一届人工智能教育应用论坛暨 AI 教育科技成果展在北京隆重举办。本次活动以“AI 强校大时代 —— 用新质生产力打造金钥匙强校”为主题&#xff0c;汇聚了…

C++速通LeetCode简单第12题-二叉树的直径

递归&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}…

链表的快速排序(C/C++实现)

一、前言 大家在做需要排名的项目的时候&#xff0c;需要把各种数据从高到低排序。如果用的快速排序的话&#xff0c;处理数组是十分简单的。因为数组的存储空间的连续的&#xff0c;可以通过下标就可以简单的实现。但如果是链表的话&#xff0c;内存地址是随机分配的&#xf…