linux paddle For C++环境搭建

paddle介绍

Paddle是类似tesseract的文字识别ocr。因为tesseract-ocr的中文识别效果不好。因此才准备安装Paddle。Paddle最方便的安装方式的使用Python的包管理安装。pip3 install paddlepaddle。但我使用了一下感觉还是用C++更加方便,QT + OpenCV + Paddle应当还不错。所以才有了下面这一篇教程。

环境说明

  1. 电脑系统是Ubuntu23.04
  2. 安装的OpenCV是使用apt安装的,不是自己编译安装的
  3. 因为墙的原因,直接使用的Paddle编译好的库,没有使用源码安装

安装步骤

  1. 确保系统中已经安装openCV
# 搜索安装opencv
sudo apt search libopencv-dev
sudo apt install libopencv-dev
# 确定pkg-config能找到opencv头文件和库文件
pkg-config --libs --cflags opencv4
  1. 下载Paddle库文件

这里下载。我下载的是manylinux_cpu_avx_mkl_gcc8.2
下载完成后解压。

tar zxvf paddle_inference.tgz
cd paddle_inference/
# 这个目录中就是paddle的头文件和相关库文件
# 这里的库文件需要提取出来,加入到系统搜索目录
# 使用下面的命令提取出共享库文件
mkdir paddle_lib
find . -name "*.so*" | xargs -i cp {} ./paddle_lib
# 完成后paddle_lib目录下面就会有几个动态库文件
# 下面将这些动态库加入到系统搜索目录中
cp -a paddle_lib /usr/lib
vi /etc/ld.so.conf.d/paddle.conf
# 加入搜索目录
/usr/lib/paddle_lib
# 更新
ldconfig
  1. 下载推理模型model和PaddleOCR

PaddleOCR类似一个Paddle的命令行命令,但这个命令需要自己编译,不像tesseract可以直接使用apt安装。这里编译PaddleOCR是从源码编译的有点麻烦,如果只是想在C++中使用Paddle可以不用编译PaddleOCR,但了解如何编译PaddleOCR可以帮助您理解paddle的编译过程。

# 使用下面命令下载PaddleOCR
git clone https://gitee.com/paddlepaddle/PaddleOCR.git

这里下载推理模型。下载时点击"推理模型"链接下载,我下载的是ch_ppocr_server_v2.0_det_infer.tar,49.5M。下载后解压。
将解压后的文件放到PaddleOCR/PaddleOCR/deploy/cpp_infer/inference。这里的inference目录是自己新建的,用于存放模型文件。

cd PaddleOCR/deploy/cpp_infer/
mkdir inference
cd inference
mv ~/Downloads/ch_ppocr_server_v2.0_det_infer .

编译PaddleOCR

编译之前需要修改一些配置

cd PaddleOCR/deploy/cpp_infer/
git checkout release/2.7
vi tools/build.sh

# 这里的你的opencv目录,因为我使用的apt安装的,试了几次指定opencv目录都无效
# 因为这里设置失败,所以后面我直接更改的CMakeLists.txt
OPENCV_DIR= "你的opencv安装目录"
# 下面这个就是上面下载的Paddle库文件目录
LIB_DIR=your_paddle_inference_dir
# 下面这两个是使用显卡推理使用的,这里不使用
#CUDA_LIB_DIR=your_cuda_lib_dir
#CUDNN_LIB_DIR=your_cudnn_lib_dir

BUILD_DIR=build
rm -rf ${BUILD_DIR}
mkdir ${BUILD_DIR}
cd ${BUILD_DIR}
cmake .. \
    -DPADDLE_LIB=${LIB_DIR} \
    -DWITH_MKL=ON \
    -DWITH_GPU=OFF \
    -DWITH_STATIC_LIB=OFF \
    -DWITH_TENSORRT=OFF \
    -DOPENCV_DIR=${OPENCV_DIR} \
#    -DCUDNN_LIB=${CUDNN_LIB_DIR} \
#    -DCUDA_LIB=${CUDA_LIB_DIR} \
#    -DTENSORRT_DIR=${TENSORRT_DIR} \

# 根据你cpu核心数加个数字,多线编译
make -j16

# 再更改一下CMakeLists.txt第74行,这里的优化等级有问题。将-o3改为-O3
vi CMakeLists.txt
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O3 ${FLAG_OPENMP} -std=    c++11")

# 改了上面配置后就可以尝试编译一下了
sh tools/build.sh

# 如果你也和我一样找不到OpenCVConfig.cmake,可以像我一样直接更改CMakeLists.txt,不用cmake自带的find_package找opencv。我也试过更改CMAKE_PREFIX_PATH,明明目录下有OpenCVConfig.cmake,还是提示找不到OpenCVConfig.cmake。因此一气之下自己改CMakeLists.txt。如果找不到OpenCV会提示以下错误:
CMake Error at CMakeLists.txt:47 (find_package):
  Could not find a package configuration file provided by "OpenCV" with any
  of the following names:

    OpenCVConfig.cmake
    opencv-config.cmake

  Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set
  "OpenCV_DIR" to a directory containing one of the above files.  If "OpenCV"
  provides a separate development package or SDK, be sure it has been
  installed.

# 可以更改CMakeLists.txt 49行,改为如下内容
else ()
  #find_package(OpenCV REQUIRED PATHS ${OPENCV_DIR}/share/OpenCV NO_DEFAULT_PATH)
  find_package(PkgConfig)
  pkg_search_module(OPENCV4 REQUIRED opencv4)
  link_directories(${OPENCV4_LIBRARY_DIRS})
  link_libraries(${OPENCV4_LIBRARIES})
  include_directories(${OPENCV4_INCLUDE_DIRS})
  include_directories("${PADDLE_LIB}/paddle/include")
  link_directories("${PADDLE_LIB}/paddle/lib")
endif ()
#include_directories(${OpenCV_INCLUDE_DIRS})

# 再尝试编译
sh tools/build.sh

运行PaddleOCR

./ppocr --help
# 如果不报错,而是显示支持的选项就表示成功了,PaddleOCR的命令就可以使用的
# 只是一个帮助命令完全看不出推理有什么效果因此可以使用下面命令,看下推理效果
./build/ppocr --det_model_dir=../inference/ch_ppocr_server_v2.0_det_infer/ --image_dir=./doc/imgs/cmake_step3.png --det=true --rec=false
# 如果报找不到图片,可以使用绝对路径
# 运行成功后会在output目录下生成一个cmake_step3.png的图片,这个图片中的文字都会框出来

输入图片

输出图片

C++中使用paddle

这里主要依照官网的教程,Paddle官网教程

  1. 确定已经下载Paddle库,并解压
  2. 这里下载ResNet50推理模型
  3. 下载推理示例
git clone https://gitee.com/cuizhi/Paddle-Inference-Demo.git
# 将步骤1下载的Paddle库,复制到Paddle-Inference-Demo/c++/lib/
cp -a ~/Downloads/paddle_inference/ Paddle-Inference-Demo/c++/lib/
# 将步骤2下载的推理模型复制到Paddle-Inference-Demo/c++/cpu/resnet50
cp -a ~/Downloads/resnet50 Paddle-Inference-Demo/c++/cpu/resnet50
  1. 修改编译选项
# 因为我的电脑没有安装CUDA,因此需要关闭GPU选项
cd Paddle-Inference-Demo/c++/cpu/resnet50
vi complie.sh
# 26行开始关闭ONNXRUNTIME,这个第三方库老是与库里要求版本不一致
WITH_MKL=ON
WITH_ONNXRUNTIME=OFF
WITH_ARM=OFF
WITH_MIPS=OFF
WITH_SW=OFF

LIB_DIR=${work_path}/../../lib/paddle_inference

cmake .. -DPADDLE_LIB=${LIB_DIR} \
  -DDEMO_NAME=${DEMO_NAME} \
  -DWITH_MKL=${WITH_MKL} \
  -DWITH_ONNXRUNTIME=${WITH_ONNXRUNTIME} \
  -DWITH_ARM=${WITH_ARM} \
  -DWITH_MIPS=${WITH_MIPS} \
  -DWITH_SW=${WITH_SW} \
  -DWITH_STATIC_LIB=OFF

# 之后就可以编译了, 会生成resnet50_test
./compile.sh
  1. 运行程序
./build/resnet50_test --model_file resnet50/inference.pdmodel --params_file resnet50/inference.pdiparams
# 显示以下内容表示成功
I0310 08:20:42.485941  6242 device_context.cc:737] oneDNN v2.5.4
WARNING: Logging before InitGoogleLogging() is written to STDERR
I0310 08:20:42.643239  6242 resnet50_test.cc:76] run avg time is 157.477 ms
I0310 08:20:42.643280  6242 resnet50_test.cc:91] 0 : 0
I0310 08:20:42.643291  6242 resnet50_test.cc:91] 100 : 2.04163e-37
I0310 08:20:42.643296  6242 resnet50_test.cc:91] 200 : 2.1238e-33
I0310 08:20:42.643299  6242 resnet50_test.cc:91] 300 : 0
I0310 08:20:42.643303  6242 resnet50_test.cc:91] 400 : 1.6849e-35
I0310 08:20:42.643309  6242 resnet50_test.cc:91] 500 : 0
I0310 08:20:42.643317  6242 resnet50_test.cc:91] 600 : 1.05767e-19
I0310 08:20:42.643327  6242 resnet50_test.cc:91] 700 : 2.04094e-23
I0310 08:20:42.643334  6242 resnet50_test.cc:91] 800 : 3.85254e-25
I0310 08:20:42.643342  6242 resnet50_test.cc:91] 900 : 1.52391e-30

如果只是学习使用官方教程到这里就结束了,但我的目的是想将Paddle,openCV以及Qt一起使用,因此下面还要探索如果简单方便的将Paddle库引入到Qt中。

  1. 移植Paddle库到QT

Paddle库无非就是提供了头文件和库文件,要做的就是把其中的Paddle文件加入到Qt项目管理文件中,具体就是项目的.pro文件。废话不多说开造。

# 使用QT creator新建一个paddleTest项目
# paddleTest.pro文件中加入以下内容

# 这个是自己的Paddle库所在位置
PADDLE_PATH = /home/XXXXXXX/Downloads/paddle_inference/

INCLUDEPATH += \
    $$PADDLE_PATH/paddle/include \
    $$PADDLE_PATH/third_party/install/cryptopp/include \
    $$PADDLE_PATH/third_party/install/glog/include \
    $$PADDLE_PATH/third_party/install/mkldnn/include \
    $$PADDLE_PATH/third_party/install/mklml/include \
    $$PADDLE_PATH/third_party/install/protobuf/include \
    $$PADDLE_PATH/third_party/install/xxhash/include \
    $$PADDLE_PATH/third_party/install/gflags/include

LIBS += -L$$PADDLE_PATH/paddle/lib -lpaddle_inference
LIBS += -L$$PADDLE_PATH/third_party/install/gflags/lib -lgflags
LIBS += -L$$PADDLE_PATH/third_party/install/glog/lib -lglog
LIBS += -L$$PADDLE_PATH/third_party/install/mkldnn/lib -lmkldnn
LIBS += -L$$PADDLE_PATH/third_party/install/mklml/lib -liomp5 -lmklml_intel
LIBS += -L$$PADDLE_PATH/third_party/install/protobuf/lib -lprotobuf
LIBS += -L$$PADDLE_PATH/third_party/install/xxhash/lib -lxxhash

# mkldnn库名字有点问题,我的Paddle库中是libmkldnn.so.0,使用下列命令来一个软链接,其它有几个动态库也是如此都有一个版本号,也可以加一个软链接
ln -s libmkldnn.so.0 libmkldnn.so

# 新建一个main.cc,复制Paddle-Inference-Demo/c++/cpu/resnet50/resnet50_test.cc内容到main.cc
# 如果编译通过,那就没有问题了

# 最后就是运行了,将前面下载的resnet50的推理模型复制到build-paddleTest-unknown-Debug
# 下面命令运行程序, 和使前面和运行效果一致,表示成功移植
./paddleTest --model_file resnet50/inference.pdmodel --params_file resnet50/inference.pdiparams

到这里已经完成Paddle库和Qt一起使用,但还不够简单,每次加入的头文件和库文件也太多了,每次都要复制出来,太麻烦了。可以将这些文件提取出来放到固定文件,每次只需要加载这个文件就可以了。现成的方案是有的pkg-config,只需要提取出头文件,和库文件,再使用一个xxx.pc文件配置好,每次使用直接像opencv那样加载一下就完成了。库文件可以用前面提到的find . -name "*.so*" | xargs -i cp {} ./paddle_lib方法,这次不只提取.so动态库,.a的静态库也一并提取出来。

# 进入paddle_inference目录
# 提取库文件
cd ~/Downloads/paddle_inference
mkdir paddle_lib
find . -name "*.so*" | xargs -i cp {} ./paddle_lib
find . -name "*.a" | xargs -i cp {} ./paddle_lib

# 复制头文件,因为头文件有结构要求,只能手动提取,注意这里的头文件包含第三方库的头文件
mkdir paddle_include

# 完成后将库文件复制到/usr/lib/
# 将头文件复制到/usr/include/
# 下面就是我复制完成后的头文件内容,包含paddle和第三方库所有头文件

cpu_provider_factory.h     mkl_lapacke.h
crypto                     mkl_lapack.h
cryptopp                   mkl_service.h
dnnl_config.h              mkl_spblas.h
dnnl_debug.h               mkl_trans.h
dnnl.h                     mkl_types.h
dnnl.hpp                   mkl_version.h
dnnl_ocl.h                 mkl_vml_defines.h
dnnl_ocl.hpp               mkl_vml_functions.h
dnnl_sycl.h                mkl_vml.h
dnnl_sycl.hpp              mkl_vml_types.h
dnnl_sycl_types.h          mkl_vsl_defines.h
dnnl_threadpool.h          mkl_vsl_functions.h
dnnl_threadpool.hpp        mkl_vsl.h
dnnl_threadpool_iface.hpp  mkl_vsl_types.h
dnnl_types.h               oneapi
dnnl_version.h             onnxruntime_c_api.h
experimental               onnxruntime_cxx_api.h
gflags                     onnxruntime_cxx_inline.h
glog                       onnxruntime_run_options_config_keys.h
google                     onnxruntime_session_options_config_keys.h
i_malloc.h                 paddle2onnx
internal                   paddle_analysis_config.h
mkl_blas.h                 paddle_api.h
mkl_cblas.h                paddle_infer_contrib.h
mkl_direct_blas.h          paddle_infer_declare.h
mkl_direct_blas_kernels.h  paddle_inference_api.h
mkl_direct_call.h          paddle_mkldnn_quantizer_config.h
mkl_direct_lapack.h        paddle_pass_builder.h
mkl_direct_types.h         paddle_tensor.h
mkl_dnn.h                  provider_options.h
mkl_dnn_types.h            utf8proc.h
mkl.h                      xxhash.h

# 最后库文件和头文件都重命名为paddle
# 完成后可以再次使用Qt的测试项目测试一下,INCLUDEPATH就只添加/usr/include/paddle,LIBS只指定一次-L选项, -l选项保留,如下:
INCLUDEPATH += /usr/include/paddle/

LIBS += -L/usr/lib/paddle
LIBS += -lpaddle_inference
LIBS += -lgflags
LIBS += -lglog
LIBS +=	-lmkldnn
LIBS +=	-liomp5 -lmklml_intel
LIBS +=	-lprotobuf
LIBS +=	-lxxhash
  1. 编写paddle.pc文件

pkg-config可以很方便管理头文件和库文件引用,只需要一个.pc文件。因此可以自己编写一个.pc文件,以后就可以方便的使用pkg-config引用paddle库了。
经过以上提取,paddle所有头文件和第三方头文件我们都放到了/usr/include/paddle中。所有库文件,包含动态库和静态库都放到了/usr/lib/paddle中。

cd /usr
# 查找.pc文件存放位置
find . -iname opencv4.pc
# 找到如下位置
./lib/x86_64-linux-gnu/pkgconfig/opencv4.pc
# 可以照着写一个自己的paddle.pc
# Package Information for pkg-config

prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib/paddle
includedir=${prefix}/include/paddle

Name: Paddle
Description: Open Source Computer Vision Library
Version: 1.0.0
Libs: -L${exec_prefix}/lib/paddle -lpaddle_inference -lgflags -lglog -lmkldnn -liomp5 -lmklml_intel -lprotobuf -lxxhash
Cflags: -I${includedir}

# 完成后看下是否成功
pkg-config --cflags --libs paddle
# 输出如下,如果需要的库不在这里面,可以自己更改paddle.pc增加
-I/usr/include/paddle -L/usr/lib/paddle -lpaddle_inference -lgflags -lglog -lmkldnn -liomp5 -lmklml_intel -lprotobuf -lxxhash

# 进入paddleTest项目直接编译运行,编译通过
g++ -o main main.cc `pkg-config --cflags --libs paddle`
# 复制推理模型到当前目录,运行程序,效果与前面一致

到这里已经完成了paddle.pc文件编写,下面就可以在Qt creator中以2句简单的命令引入paddle库了.

CONFIG += link_pkgconfig
PKGCONFIG += paddle

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

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

相关文章

Go语言必知必会100问题-19 浮点数溢出问题

问题呈现 在Go语言中,有两种浮点数类型(虚数除外):float32和float64. 浮点数是用来解决整数不能表示小数的问题。我们需要知道浮点数算术运算是实数算术运算的近似,下面通过例子说明浮点数运算采用近似值的影响以及如…

⭐每天一道leetcode:83.删除排序链表中的重复元素(简单;链表遍历、删除经典题目)

⭐今日份题目 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 示例1 输入:head [1,1,2] 输出:[1,2] 示例2 输入:head [1,1,2,3,3] 输出:[1,2,3] …

【R语言爬虫实战】抓取省市级城市常务会议内容

🍉CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一|统计学|干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项,参与研究经费10w、40w级横向 文…

enumerate函数的用法

enumerate() 函数是 Python 内置函数之一,用于同时返回可迭代对象的索引和对应的值。 它的语法结构如下: enumerate(iterable, start0) iterable: 表示一个可迭代的对象,如列表、元组、字符串等。start: 可选参数,表示索引起始…

02hadoop伪分布式搭建

3. 环境安装 3.1 安装方式 单机模式 只能启动MapReduce 伪分布式 能启动HDFS、MapReduce 和 YARN的大部分功能 完全分布式 能启动Hadoop的所有功能 3.2 安装JDK 3.2.1 JDK安装步骤 下载JDK安装包(下载Linux系统的 .tar.gz 的安装包) https://www…

网络协议常见问题

网络协议常见问题 OSI(Open Systems Interconnection)模型OSI 封装 TCP/IP协议栈IP数据报的报头TCP头格式UDP头格式TCP (3-way shake)三次握手建立连接:为什么三次握手才可以初始化 Socket、序列号和窗口大小并建立 TCP 连接。每次建立TCP连接…

蓝桥杯递推与递归法|斐波那契数列|数字三角形|42点问题|数的计算|数的划分(C++)

递归是用来做dfs,是搜索算法的基础 递推是用来做dp部分,及部分其他算法,复杂度较低,不会出现爆栈问题递推法: 递推法是一种在数学和其他领域广泛应用的重要方法,它在计算机科学中被用作一种关键的数值求解…

自动化运维利器Ansible基础(环境部署)

Ansible 介绍及安装 1. 介绍 Ansible 是⼀个 IT ⾃动化⼯具。它能配置系统、部署软件、编 排更复杂的 IT 任务,如连续部署或零停机时间滚动更新。 Ansible ⽤ Python 编写,尽管市⾯上已经有很多可供选择的 配置管理解决⽅案(例如 Salt、Pupp…

OpenAI GPT LLMs 高级提示词工程方法汇总

原文地址:An Introduction to Prompt Engineering for OpenAI GPT LLMs Github:Prompt-Engineering-Intro 2023 年 3 月 2 日 提示工程指南 | Prompt Engineering Guide Naive 提示词:带有提示的情感分类器 prompt Decide whether a T…

复合查询【MySQL】

文章目录 复合查询测试表 单表查询多表查询子查询单行子查询多行子查询IN 关键字ALL 关键字ANY 关键字 多列子查询 合并查询 复合查询 测试表 雇员信息表中包含三张表,分别是员工表(emp)、部门表(dept)和工资等级表&…

GEE:基于ERA5数据集(U和V风速分量)计算风速的幅值和风向

作者:CSDN @ _养乐多_ 本文将介绍使用Google Earth Engine (GEE)平台提供的API加载ERA5月度数据集,该数据集包含了从1979年至今的全球月度气象数据。然后,定义了一个数据计算函数,用于将U和V风速分量转换为风速的幅值和风向。 结果如下图所示, 文章目录 一、核心函数1…

基于单片机的语音存储与回放系统设计

目 录 摘 要 I Abstract II 引 言 1 1 控制系统设计 3 1.1 系统方案设计 3 1.2 系统工作原理 4 1.2.1 单片机的选择 4 1.2.2 语音芯片的选择 5 2 硬件电路设计 6 2.1 时钟电路 6 2.2 复位电路 6 2.3 显示电路 7 2.4 电源电路 7 2.5 按键模块电路 8 2.6 LM386功放电路 8 2.7 总…

基于深度学习YOLOv8+Pyqt5的抽烟吸烟检测识别系统(源码+跑通说明文件)

wx供重浩:创享日记 对话框发送:39抽烟 获取完整源码源文件4000张已标注的数据集配置说明文件 可有偿59yuan一对一远程操作跑通 效果展示 基于深度学YOLOv8PyQt5的抽烟吸烟检测识别系统(完整源码跑通说明文件) 各文件说明 模型评价…

Seurat 中的数据可视化方法

本文[1]将使用从 2,700 PBMC 教程计算的 Seurat 对象来演示 Seurat 中的可视化技术。您可以从 SeuratData[2] 下载此数据集。 SeuratData::InstallData("pbmc3k")library(Seurat)library(SeuratData)library(ggplot2)library(patchwork)pbmc3k.final <- LoadData(…

【机器学习300问】31、不平衡数据集如何进行机器学习?

一、什么是不平衡的数据集&#xff1f; &#xff08;1&#xff09;认识不平衡数据 假如你正在管理一个果园&#xff0c;这个果园里主要有两种水果——苹果和樱桃。如果苹果树有1000棵&#xff0c;而樱桃树只有10棵&#xff0c;那么在收集果园的果实时&#xff0c;你会得到大量…

RocketMQ架构详解

文章目录 概述RocketMQ架构rocketmq的工作流程Broker 高可用集群刷盘策略 概述 RocketMQ一个纯java、分布式、队列模型的开源消息中间件&#xff0c;前身是MetaQ&#xff0c;是阿里研发的一个队列模型的消息中间件&#xff0c;后开源给apache基金会成为了apache的顶级开源项目…

全栈的自我修养 ———— css中常用的布局方法flex和grid

在项目里面有两种常用的主要布局:flex和grid布局&#xff08;b站布局&#xff09;&#xff0c;今天分享给大家这两种的常用的简单方法&#xff01; 一、flex布局1、原图2、中心对齐3、主轴末尾或者开始对其4、互相间隔 二、grid布局1、基本效果2、加间隔3、放大某一个元素 一、…

Nginx请求转发和Rewrite的URL重写及重定向的功能实现移动端和PC端前端服务转发和重定向配置。

应用场景说明一 应用系统分pc端和微信小程序&#xff0c;移动端和pc端分别申请二级子域名&#xff0c;通过Nginx域名解析匹配&#xff0c;将web访问统一转发至对应的域名请求中。部分配置如下所示&#xff1a; 1、WEB访问统一入口域名解析转发配置&#xff0c;PC端和移动端根域…

【论文整理】自动驾驶场景中Collaborative Methods多智能体协同感知文章创新点整理

Collaborative Methods F-CooperV2VNetWhen2commDiscoNetAttFusionV2X-ViTCRCNetCoBERTWhere2commDouble-MCoCa3D 这篇文章主要想整理一下&#xff0c;根据时间顺序这些文章是怎么说明自己的创新点的&#xff0c;又是怎么说明自己的文章比别的文章优越的。显然似乎很多文章只是…

数据结构与算法:链式二叉树

上一篇文章我们结束了二叉树的顺序存储&#xff0c;本届内容我们来到二叉树的链式存储&#xff01; 链式二叉树 1.链式二叉树的遍历1.1二叉树的前序&#xff0c;中序&#xff0c;后序遍历1.2 三种遍历方法代码实现 2. 获取相关个数2.1获取节点个数2.2获取叶节点个数2.3 获取树的…