MP4文件格式详解

一、基本概念

1.mp4概述

MP4文件中的所有数据都装在box(QuickTime中为atom)中,也就是说MP4文件由若干个box组成,每个box有类型和长度,可以将box理解为一个数据对象块。box中可以包含另一个box,这种box称为container box。一个MP4文件首先会有且只有一个“ftyp”类型的box,作为MP4格式的标志并包含关于文件的一些信息;之后会有且只有一个“moov”类型的box(Movie Box),它是一种container box,子box包含了媒体的metadata信息;MP4文件的媒体数据包含在“mdat”类型的box(Midia
Data Box)中,该类型的box也是container box,可以有多个,也可以没有(当媒体数据全部引用其他文件时),媒体数据的结构由metadata进行描述。

    下面是一些概念:

   track  表示一些sample的集合,对于媒体数据来说,track表示一个视频或音频序列。

   hint track  这个特殊的track并不包含媒体数据,而是包含了一些将其他数据track打包成流媒体的指示信息。

   sample  对于非hint track来说,video sample即为一帧视频,或一组连续视频帧,audio sample即为一段连续的压缩音频,它们统称sample。对于hint track,sample定义一个或多个流媒体包的格式。

   sample table  指明sampe时序和物理布局的表。

   chunk 一个track的几个sample组成的单元。

    在本文中,我们不讨论涉及hint的内容,只关注包含媒体数据的本地MP4文件。下图为一个典型的MP4文件的结构树。 

 

mp4文件格式解析(一)

2、Box

       首先需要说明的是,box中的字节序为网络字节序,也就是大端字节序(Big-Endian),简单的说,就是一个32位的4字节整数存储方式为高位字节在内存的低端。Box由header和body组成,其中header统一指明box的大小和类型,body根据类型有不同的意义和格式。

       标准的box开头的4个字节(32位)为box size,该大小包括box header和box body整个box的大小,这样我们就可以在文件中定位各个box。如果size为1,则表示这个box的大小为large size,真正的size值要在largesize域上得到。(实际上只有“mdat”类型的box才有可能用到large size。)如果size为0,表示该box为文件的最后一个box,文件结尾即为该box结尾。(同样只存在于“mdat”类型的box中。)

       size后面紧跟的32位为box type,一般是4个字符,如“ftyp”、“moov”等,这些box type都是已经预定义好的,分别表示固定的意义。如果是“uuid”,表示该box为用户扩展类型。如果box type是未定义的,应该将其忽略

 

(1、 mp4文件由许多Box和FullBox组成。

(2、 Box,每个Box由Header和Data组成。

(3、 FullBox,是Box的扩展,Box结构的基础上在Header中增加8bits version和24bits flags。

(4、 Header,包含了整个Box的长度size和类型type。当size==0时,代表这是文件中最后一个Box;当size==1时,意味着Box长度需要更多bits来描述,在后面会定义一个64bits的largesize描述Box的长度;当type是uuid时,代表Box中的数据是用户自定义扩展类型。

(5、 Data,是Box的实际数据,可以是纯数据也可以是更多的子Boxes。

(6、 当一个Box的Data中是一系列子Box时,这个Box又可成为Container Box。当一个Box里面不包含子Box时,这个Box称为leaf Box,而FullBox是mp4格式协议规定的某些特殊的Box。

 

Box header的结构用伪代码表示如下:

 

结构如下图:

 

                                                                                             BOX结构描述图

二、MP4文件格式(ISO-14496-12/14)

 

MP4文件就是由各式各样的Box组成的,下表中列出了所有必选或可选的Box类型,√代表Box必选。

ftyp

 

 

 

 

 

√  

file type and compatibility

pdin

 

 

 

 

 

 

progressive download information

moov

 

 

 

 

 

√  

container for all the metadata

 

mvhd

 

 

 

 

√  

movie header, overall declarations

 

trak

 

 

 

 

√  

container for an individual track or stream

 

 

tkhd

 

 

 

√  

track header, overall information about the track

 

 

tref

 

 

 

 

track reference container

 

 

edts

 

 

 

 

edit list container

 

 

 

elst

 

 

 

an edit list

 

 

mdia

 

 

 

√  

container for the media information in a track

 

 

 

mdhd

 

 

√  

media header, overall information about the media

 

 

 

hdlr

 

 

√  

handler, declares the media (handler) type

 

 

 

minf

 

 

√  

media information container

 

 

 

 

vmhd

 

 

video media header, overall information (video track only)

 

 

 

 

smhd

 

 

sound media header, overall information (sound track only)

 

 

 

 

hmhd

 

 

hint media header, overall information (hint track only)

 

 

 

 

nmhd

 

 

Null media header, overall information (some tracks only)

 

 

 

 

dinf

 

√  

data information box, container

 

 

 

 

 

dref

√  

data reference box, declares source(s) of media data in track

 

 

 

 

stbl

 

√  

sample table box, container for the time/space map

 

 

 

 

 

stsd

√  

sample descriptions (codec types, initialization etc.) 

 

 

 

 

 

stts

√  

(decoding) time-to-sample

 

 

 

 

 

ctts

 

(composition) time to sample

 

 

 

 

 

stsc

√  

sample-to-chunk, partial data-offset

information

 

 

 

 

 

stsz

 

sample sizes (framing)

 

 

 

 

 

stz2

 

compact sample sizes (framing)

 

 

 

 

 

stco

√  

chunk offset, partial data-offset information

 

 

 

 

 

co64

 

64-bit chunk offset

 

 

 

 

 

stss

 

sync sample table (random access points)

 

 

 

 

 

stsh

 

shadow sync sample table

 

 

 

 

 

padb

 

sample padding bits

 

 

 

 

 

stdp

 

sample degradation priority

 

 

 

 

 

sdtp

 

independent and disposable samples

 

 

 

 

 

sbgp

 

sample-to-group

 

 

 

 

 

sgpd

 

sample group description

 

 

 

 

 

subs

 

sub-sample information

 

mvex

 

 

 

 

 

movie extends box

 

 

mehd

 

 

 

 

movie extends header box

 

 

trex

 

 

 

√  

track extends defaults

 

ipmc

 

 

 

 

 

IPMP Control Box

moof

 

 

 

 

 

 

movie fragment

 

mfhd

 

 

 

 

√  

movie fragment header

 

traf

 

 

 

 

 

track fragment

 

 

tfhd

 

 

 

√  

track fragment header

 

 

trun

 

 

 

 

track fragment run

 

 

sdtp

 

 

 

 

independent and disposable samples

 

 

sbgp

 

 

 

 

sample-to-group

 

 

subs

 

 

 

 

sub-sample information

mfra

 

 

 

 

 

 

movie fragment random access

 

tfra

 

 

 

 

 

track fragment random access

 

mfro

 

 

 

 

√  

movie fragment random access offset

mdat

 

 

 

 

 

 

media data container

free

 

 

 

 

 

 

free space

skip

 

 

 

 

 

 

free space

 

udta

 

 

 

 

 

user-data

 

 

cprt

 

 

 

 

copyright etc.

meta

 

 

 

 

 

 

metadata

 

hdlr

 

 

 

 

√  

handler, declares the metadata (handler) type

 

dinf

 

 

 

 

 

data information box, container

 

 

dref

 

 

 

 

data reference box, declares source(s) of metadata items

 

ipmc

 

 

 

 

 

IPMP Control Box

 

iloc

 

 

 

 

 

item location

 

ipro

 

 

 

 

 

item protection

 

 

sinf

 

 

 

 

protection scheme information box

 

 

 

frma

 

 

 

original format box

 

 

 

imif

 

 

 

IPMP Information box

 

 

 

schm

 

 

 

scheme type box

 

 

 

schi

 

 

 

scheme information box

 

iinf

 

 

 

 

 

item information

 

xml

 

 

 

 

 

XML container

 

bxml

 

 

 

 

 

binary XML container

 

pitm

 

 

 

 

 

primary item reference

 

fiin

 

 

 

 

 

file delivery item information

 

 

paen

 

 

 

 

partition entry

 

 

 

fpar

 

 

 

file partition

 

 

 

fecr

 

 

 

FEC reservoir

 

 

segr

 

 

 

 

file delivery session group

 

 

gitn

 

 

 

 

group id to name

 

 

tsel

 

 

 

 

track selection

meco

 

 

 

 

 

 

additional metadata container

 

mere

 

 

 

 

 

metabox relation

先简单介绍几个重要的box,以便诸位在后续学习时心中有数:

1、  ftyp box,在文件的开始位置,描述的文件的版本、兼容协议等;

2、  moov box,这个box中不包含具体媒体数据,但包含本文件中所有媒体数据的宏观描述信息,moov box下有mvhd和trak box。

        >>mvhd中记录了创建时间、修改时间、时间度量标尺、可播放时长等信息。

        >>trak中的一系列子box描述了每个媒体轨道的具体信息。

3、  moof box,这个box是视频分片的描述信息。并不是MP4文件必须的部分,但在我们常见的可在线播放的MP4格式文件中(例如Silverlight Smooth Streaming中的ismv文件)确是重中之重。

4、  mdat box,实际媒体数据。我们最终解码播放的数据都在这里面。

5、  mfra box,一般在文件末尾,媒体的索引文件,可通过查询直接定位所需时间点的媒体数据。

附:Smooth Streaming中ismv文件结构,文件分为了多个Fragments,每个Fragment中包含moof和mdat。这样的结构符合渐进式播放需求。(mdat及其描述信息逐步传输,收齐一个Fragment便可播放其中的mdat)。

************************************

** 文件类型ftyp                              **

************************************

ftyp box 的数据结构的伪代码表示:

 

什么是brands?官方是这样描述的: 

Each brand is a printable four-character code, registered with ISO, that identifies a precise specification.//在ISO注册的4个字符。

下表来源于网络,列出了几种常见的基于基础文件格式的,媒体封装格式标识。

更多的内容可以查看http://www.ftyps.com/

 BrandExtensionMime Type
MP4mp41, mp42.mp4video/mp4, audio/mp4, application/mp4
3GPPvarious, e.g. 3gp4, 3gp5.3gpvideo/3gpp, audio/3gpp
3GPP23g2a.3g2video/3gpp2, audio/3gpp2
Motion JPEG 2000mjp2.mj2video/mj2
QuickTime"qt".movvideo/quicktime

结合实际文件,下图是MP4文件起始位置存放的数据 

length(4字节):0x0000001c:box的长度是28字节;

boxtype(4字节):0x66747970:“ftyp”的ASCII码,box的标识;

major_brand(4字节):0x69736f6d:“isom“的ASCII码;

minor_version(4字节):0x00000200:ismo的版本号;

compatible_brands(12字节):说明本文件遵从(或称兼容)ismo,iso2,mp41三种协议。

ftyp box通常放在文件的开始,通过对该box解析可以让我们的软件(播放器、demux、解析器)知道应该使用哪种协议对这该文件解析。

 

************************************

** 元数据moov                              **

************************************

movie box —— container box whose sub-boxes define the metadata for a presentation (‘moov’) 

moov包含的一系列次级box中存储着媒体播放所需的元数据(metadata)。

两点疑问:什么是元数据?moov有哪些次级box?

1)元数据:描述数据的数据。针对媒体文件而言元数据都有哪些呢?为了让大家直观了解:

上图是使用“格式工厂”获取某MP4文件的媒体信息,这些媒体信息基本都包含在moov中。

视频包括编码等级、分辨率、色域、码率、帧率、位深、时长等等……

音频又包括声道、采样率等音频特有属性。

这些元数据对于我们的价值在于:我们的系统(比如PC播放器,高清播放机)可以通过对moov box的解析,自动适配运行在某种模式下去播放影片。在嵌入式领域,由于DSP或ARM的Ram空间有限,经常需要动态加载本次播放所需的解码器(算法程序),通过自适配可以用最廉价的CPU,完成一款支持多码率多格式的全能播放器。


2)moov用哪些次级box来保存这些信息?

 

mvhd ——This box defines overall information which is media-independent, and relevant to the entire presentation.

全文件唯一的(一个文件中只能包含一个mvhd box),对整个文件所包含的媒体数据作全面的全局的描述。包含了媒体的创建与修改时间时间刻度、默认音量、色域、时长等信息。

 

首先mvhd是个Full Box,引用我第一篇文中解释:“ FullBox,是Box的扩展,Box结构的基础上在Header中增加8bits version和24bits flags。”,见下图:

图中标红的是moov box的长度与标识,

标蓝的是mvhd的长度0x6c,

标黄的是mvhd的标识与内容:

0x6D766864 是mvhd的ASCII标识;

0x00000000 是FullBox扩展出来的标识位,这里是全0,Version和flags都是0,参见前面的结构定义可知后面的时间与时长采用了32bit表示方式。

第一个0x7C25B080是创建时间,第二个0x7C25B080是最后修改时间。可见媒体未被修改过。这两个数值是怎么描述具体时间的呢?

 time is an integer that declares the creation time of the presentation (in seconds since midnight, Jan. 1, 1904, in UTC time) 

即,从UTC时间的1904年1月1日0点至今的秒数。我们手动算一下:

0x7C25B080 = 2082844800秒,大概是66.0465年(每年按365天算,不考虑闰年),1904+66=1970年中。看来这个媒体文件生成的并不规范,没有按照ISO的规范填写创建与修改时间(by the way,该文件是一年前使用iKu转码生成)。不过这里的时间并不影响播放器识别并播放影片。 

我们假设4字节的时间描述取其最大值0xFFFFFFFF,通过计算最多支持到2040年。如果,假设该参数是播放视频所必备的参数,那么到2040年后,也许所有的MP4文件一夜间就无法播放了~(0 == Version这种)。

0x000003E8 是timescale,该数值表示本文件的所有时间描述所采用的单位。0x3E8 = 1000,即将1s平均分为1000份,每份1ms。

0x000A06A2 是duration,媒体可播放时长,0xA06A2 =  657058,这个数值的单位与实际时间的对应关系就要通过上面的timescale参数。

duration / timescale = 可播放时长(s)。这里算出该视频能播放657.058s。使用MPC打开,时长与我们计算的一致。

timescale时间刻度贯穿在整个文件中,所有对于时间的描述都要以其为参照,例如解码时间DTS,展示时间PTS等最重要的时间描述。

0x00010000 媒体速率,这个值代表原始倍速。

0x0100 媒体音量,这个值代表满音量。

接下来的一系列值都是结构中的预定义值,参见结构定义即可。

trak box ——This is a container box for a single track of a presentation. A presentation consists of one or more tracks. Each track is independent of the other tracks in the presentation and carries its own temporal and spatial information.
Each track will contain its associated Media Box.

其次级box中包含了单个媒体轨道(Track)所特有的描述信息。

我们知道一部视频一般都有多个轨道组成。

例如,《让子弹飞》的正版DVD,1)有一条视频轨用于电影画面。2)至少有两条音频轨分别提供了普通话与四川话版,实际上为了营造更加逼真的现场效果,为了配合多声道家庭影院该影片还独有一条音效轨。3)多条字幕轨,简体中文,繁体中文,英文……。从中我们可以理解为什么trak box可以有多个:每个track都是独立的,具有自我特征与属性的,因此需要各自描述互不干涉。


我们一般所看的MP4文件中moov下都至少是mvhd-trak-trak-trak...这种构成。

 

tkhd box 的数据结构的伪代码表示:

类似我们moov中的mvhd box,但tkhd仅仅描述的单一Track的特性。 


上图是实际媒体中的tkhd的数据:

0x5c是tkhd box长度,0x746b6864是“tkhd”的ASCII码。

0x00 00 00 0f是使用了Full box中的flag位(Full box 8bits version + 24bits flag,详见我第一篇日志),这里flag= 0xf,即1111b。

这4位从低到高分别代表:

Track_enabled: Indicates that the track is enabled.  若此位为0,则该track内容无需播放(比如我们用一些非线编软件<如Sony Vegas>做视频剪辑时,有些Track仅为我们参考与模仿用,在输出时将该Track关掉)。
Track_in_movie: Indicates that the track is used in the presentation. 
Track_in_preview: Indicates that the track is used when previewing the presentation.

Track_in_poster: Indicates that the track is used in movie's poster.

/* -------------------------------------------------------------------------------------------------------*/

important:我们知道,MP4文件格式是ISO-14496-12基础文件格式的衍生品,14496-14中对-12协议进行了扩充与进一步定义。

重要的是该“14496-12 基础文件格式”协议如果认祖归宗,我们发现这种文件格式最初是由Apple公司的QuickTime媒体格式发展而来的。

即,mov格式发展出了“ISO 14496 - 12协议”,再由该协议衍生出了mp4,f4v,ismv,3gp等我们常见的媒体封装格式。

因此上述标志位的poster位,在14496-12中并没有见到描述,而在Apple的协议中却看到了准确定义。

详见 https://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap2/qtff2.html

/* -------------------------------------------------------------------------------------------------------*/


两个0xc5268eb6 是track的创建时间与最后修改时间;

紧随其后的0x00000002,代表track ID =2,Track ID是非0的,唯一的,不可重复使用的标识track的方式;

后面32bit全0是保留位; 

0x0009d97c是本track的时长,需要配合mvhd box中的timescale 计算实际的持续时间。

后续一些写死的字段不再分析,有些与mvhd重复,可以参见之前的文章。我们看两个关键字段:

layer,类似photoshop中图层的概念,数值小的在播放时更贴近用户(上层图层)。

alternate_group,track的备用分组ID,当该值为0时,意味着本track内容无备份;否则本track会可能会有零到多个备份track。当播放时相同group ID的track只选择一个进行播放。

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

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

相关文章

H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流

SkySeraph Apr 1st 2012 Email&#xff1a;skyseraph00163.com 一、MP4格式基本概念 MP4格式对应标准MPEG-4标准(ISO/IEC14496) 二、MP4封装格式核心概念 1 MP4封装格式对应标准为 ISO/IEC 14496-12&#xff08;信息技术 视听对象编码的第12部分: ISO 基本媒体文件格式/Info…

Linux应用程序在内存中的地址布局

栈&#xff1a;局部变量&#xff08;初始化的和未初始化的&#xff0c;但不包含局部静态变量&#xff09;、局部只读变量&#xff08;const&#xff09;堆&#xff1a;动态分配的区域&#xff08;如使用malloc函数申请的区域&#xff09;BSS段&#xff1a;存储未初始化的全局变…

wpa_supplicant与wpa_cli之间通信过程

wpa_supplicant编译&#xff1a; 1. wpa_supplicant/Android.mk : -- wpa_cli -- wpa_supplicant -- libwpa_client.so 2. hostapd/Android.mk : -- hostapd_cli -- hostapd 从通信层次上划分&#xff0c;wpa_supplicant提供向上的控制接口 control interface&#xff0c;用于与…

关于c语言字符串函数和一些内存函数的的简介

关于c语言字符串函数和一些内存函数的的简介 求字符串长度的函数 strlen函数介绍![在这里插入图片描述](https://img-blog.csdnimg.cn/20190301142458376.jpg)注模拟实现 . [1 ]计数器方式 因为strlen 是求字符串长度的函数&#xff0c;所以不能改变字符串本身&#xff0c;所…

用结构体写一个简单的通讯录

一个简单的通讯录 通讯录应该具备简单的一些功能 1 增添联系人 2 删除联系人 3 查找联系人 4 修改联系人 5 按名字给联系人排序 6 查看通讯录 除此之外&#xff0c;应该在实现上还应该具备一些其他的功能函数 比如 初始化通讯录 这些都是功能函数&#xff0c;而整个函数入口应…

c动态内存管理

动态内存管理 我们之前要开辟内存用的方法都是定义变量&#xff0c;比如 但是上述开辟内存的方法有两个特点 1空间开辟大小是固定的 2数组在申明的时候&#xff0c;必须指定数组的长度&#xff0c;它所需要的内存在编译时分配 malloc和free c中提供一个动态内存开辟函数 这…

右移函数(字符串,数组)

右移函数 以上是数组右移&#xff0c;将int换成char 把数组内容改成字符串就行。

c中指针简介

c中指针简介 首先我们来看一下指针的一些基本概念 ![在这里插入图片描述](https://img 而对于指针的应用&#xff0c;平常有一些形式&#xff0c;总结了一下大概有这几种用法 对于以上的几种用法&#xff0c;我依次给出详尽的解释 //这是一个普通的整型变量 1 //首先从P 处开…

判断一个字符串是否另一个字符串的右移后的

首先我们把需要判断的字符串传进来&#xff0c;开辟一块大小为两个字符串的长度总和加1的动态的空间&#xff0c;然后后字符串拷贝函数将一个字符串拷贝到开辟空降中&#xff0c;再将这个字符串再次连接到这块动态的空间中&#xff0c;等于就是将一个字符串拷贝了两遍。然后比较…

不带头结点的链表基础操作(初始化,增删改查)

链表是什么&#xff1f; **链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点&#xff08;链表中每一个元素称为结点&#xff09;组成&#xff0c;结点可以在运行时动态生成。每个结点包括…

链表面试题1:反转单链表,不带头结点。

三个指针p1,p2,p3&#xff0c;p1指向头结点的前一个结点&#xff0c;也就时指空&#xff0c;p2指向头结点&#xff0c;p3指向头结点下一个结点。 p3指向p2的下一个&#xff0c;让p2指针域指向p1&#xff0c;让p1挪到p2上&#xff0c;再让p2指向p3.

链表面试题2:编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前

我们可以&#xff0c;用两个新链表&#xff0c;一个存比基准值大的&#xff0c;另一个存比基准值小的。然后再拼接在一起。 用尾插的方法&#xff0c;首先说小的&#xff0c;创建两个指针&#xff0c;一个头&#xff0c;一个尾&#xff0c;再创建个指针跑链表&#xff0c;扫描…

栈和队列的基本操作(栈和队列的区别)

数据结构中的栈与内存中的栈的不同 一、数据结构中的堆栈 在数据结构中的堆栈&#xff0c;实际上堆栈是两种数据结构&#xff1a;堆和栈。堆和栈都是一种数据项按序排列的数据结构。 1.栈就像装数据的桶或箱子 我们先从大家比较熟悉的栈说起吧&#xff0c;它是一种具有后进先…

链表面试题3:将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成 的。

链表面试题3&#xff1a;将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成 的。 首先我们的思想是将得一个链表和第二个链表的每个结点进行比较&#xff0c;谁小谁就插入到新链表的最后。 首先我们要判段链表是否为空&#xff0c;…

双向链表的操作(创建,插入,删除)

双向链表的代码看似复杂&#xff0c;其实很简单&#xff0c;只要画图便可明白&#xff0c; 删除 假如要删除的结点叫pos. pos->prev->nextpos->next; pos->next->prevpos->prev; free(pos);

二叉树的操作(前,中,后序遍历也叫深度优先遍历,非空结点的个数)递归实现

定义一个二叉树的结点 二叉树的前序遍历&#xff0c; 先访问根结点&#xff0c;再访问左&#xff0c;再访问右。 每次访问都要先看根结点是否为空&#xff0c;然后打印根结点&#xff0c;把此时根结点的左结点作为下一次递归的根结点&#xff0c;当把左结点遍历完后&#xff0…

二叉树的相关题(叶子结点个数,最大深度,找特殊值结点(值不重复),判断两个树是否相同,判断两个数是否为镜像树,是否为子树,)

叶子结点就是没有孩子结点&#xff0c;所以当当前根结点没有孩子结点的时候&#xff0c;就返回1&#xff0c;就是找到一个叶子结点&#xff0c;然后访问完每个不为空的结点就行&#xff0c;每次访问都是把当前结点的左/右结点作为新的结点&#xff0c;来判断。 求最大深度&…

为何线程有PID?

在linux下用 top -H -p <pid> 查询某个进程的线程 按理说&#xff0c;都是某个进程下的线程&#xff0c; 应该进程id PID一样啊&#xff0c;但实际却都不一样 实际是被PID的名字给弄混了&#xff0c;线程进程都会有自己的ID&#xff0c;这个ID就叫做PID&#xff0c;P…

用c语言构建二叉树(重点)

结点创建 二叉树创建 我们以‘#’为NULL&#xff0c;我们要把输入进来的一个字符串转变为二叉树&#xff0c;所以我们要记住递归的每一步走到数组了哪个位置 所以我们要记住创建过程中用掉的前序个数&#xff0c;并返回&#xff0c;除此之外&#xff0c;还要加上当时的那个结点…

二叉树的广度优先遍历(层序遍历)

先定义一个二叉树的结点 再创建二叉树&#xff0c;这里就不写了&#xff0c;之前的有创建二叉树的博客。 层序遍历 用到栈的思想&#xff0c; 1 先让根 节点进队列&#xff0c;2 然后读队顶元素&#xff0c;3 让他出队列4 打印它的值5 让队顶元素的左右子树进栈&#xff0…