当前位置:首页 » 操作系统 » 树广度遍历算法

树广度遍历算法

发布时间: 2022-11-05 07:12:07

㈠ 二叉树广度优先遍历

#include<queue>
void bfs(Node*root)
{

queue<Node*> q;
Node* p;

if(root!=NULL)
{
q.push(root);
}
else return;
while(!q.empty())
{
p=q.front();

if(p->LT) q.push(p->LT);
if(p->RT) q.push(p->RT);
cout<<p->data<<endl;
q.pop();

}

}

㈡ 什么是树的遍历java

树遍历方法:有先序遍历、中序遍历、后序遍历以及广度优先遍历四种遍历树的方法

Demo:


publicclassThreeLinkBinTree<E>{

publicstaticclassTreeNode{

Objectdata;
TreeNodeleft;
TreeNoderight;
TreeNodeparent;

publicTreeNode(){

}

publicTreeNode(Objectdata){
this.data=data;
}

publicTreeNode(Objectdata,TreeNodeleft,TreeNoderight,TreeNodeparent){
this.data=data;
this.left=left;
this.right=right;
this.parent=parent;
}

}

privateTreeNoderoot;

//以默认的构造器创建二叉树
publicThreeLinkBinTree(){
this.root=newTreeNode();
}

//以指定根元素创建二叉树
publicThreeLinkBinTree(Edata){
this.root=newTreeNode(data);
}

/**
*为指定节点添加子节点
*
*@paramparent需要添加子节点的父节点的索引
*@paramdata新子节点的数据
*@paramisLeft是否为左节点
*@return新增的节点
*/
publicTreeNodeaddNode(TreeNodeparent,Edata,booleanisLeft){

if(parent==null){
thrownewRuntimeException(parent+"节点为null,无法添加子节点");
}
if(isLeft&&parent.left!=null){
thrownewRuntimeException(parent+"节点已有左子节点,无法添加左子节点");
}
if(!isLeft&&parent.right!=null){
thrownewRuntimeException(parent+"节点已有右子节点,无法添加右子节点");
}

TreeNodenewNode=newTreeNode(data);
if(isLeft){
//让父节点的left引用指向新节点
parent.left=newNode;
}else{
//让父节点的left引用指向新节点
parent.right=newNode;
}
//让新节点的parent引用到parent节点
newNode.parent=parent;
returnnewNode;
}

//判断二叉树是否为空
publicbooleanempty(){
//根据元素判断二叉树是否为空
returnroot.data==null;
}

//返回根节点
publicTreeNoderoot(){
if(empty()){
thrownewRuntimeException("树为空,无法访问根节点");
}
returnroot;
}

//返回指定节点(非根节点)的父节点
publicEparent(TreeNodenode){
if(node==null){
thrownewRuntimeException("节点为null,无法访问其父节点");
}
return(E)node.parent.data;
}

//返回指定节点(非叶子)的左子节点,当左子节点不存在时返回null
publicEleftChild(TreeNodeparent){
if(parent==null){
thrownewRuntimeException(parent+"节点为null,无法添加子节点");
}
returnparent.left==null?null:(E)parent.left.data;
}

//返回指定节点(非叶子)的右子节点,当右子节点不存在时返回null
publicErightChild(TreeNodeparent){
if(parent==null){
thrownewRuntimeException(parent+"节点为null,无法添加子节点");
}
returnparent.right==null?null:(E)parent.right.data;
}

//返回该二叉树的深度
publicintdeep(){
//获取该树的深度
returndeep(root);
}

//这是一个递归方法:每一棵子树的深度为其所有子树的最大深度+1
privateintdeep(TreeNodenode){
if(node==null){
return0;
}
//没有子树
if(node.left==null&&node.right==null){
return1;
}else{
intleftDeep=deep(node.left);
intrightDeep=deep(node.right);
//记录其所有左、右子树中较大的深度
intmax=leftDeep>rightDeep?leftDeep:rightDeep;
//返回其左右子树中较大的深度+1
returnmax+1;
}
}

//实现先序遍历
//1、访问根节点
//2、递归遍历左子树
//3、递归遍历右子树
publicList<TreeNode>preIterator(){
returnpreIterator(root);
}

privateList<TreeNode>preIterator(TreeNodenode){

List<TreeNode>list=newArrayList<TreeNode>();
//处理根节点
list.add(node);

//递归处理左子树
if(node.left!=null){
list.addAll(preIterator(node.left));
}

//递归处理右子树
if(node.right!=null){
list.addAll(preIterator(node.right));
}

returnlist;

}

//实现中序遍历
//1、递归遍历左子树
//2、访问根节点
//3、递归遍历右子树
publicList<TreeNode>inIterator(){
returninIterator(root);
}

privateList<TreeNode>inIterator(TreeNodenode){

List<TreeNode>list=newArrayList<TreeNode>();

//递归处理左子树
if(node.left!=null){
list.addAll(inIterator(node.left));
}

//处理根节点
list.add(node);

//递归处理右子树
if(node.right!=null){
list.addAll(inIterator(node.right));
}

returnlist;

}

//实现后序遍历
//1、递归遍历左子树
//2、递归遍历右子树
//3、访问根节点
publicList<TreeNode>postIterator(){
returnpostIterator(root);
}

privateList<TreeNode>postIterator(TreeNodenode){

List<TreeNode>list=newArrayList<TreeNode>();

//递归处理左子树
if(node.left!=null){
list.addAll(postIterator(node.left));
}

//递归处理右子树
if(node.right!=null){
list.addAll(postIterator(node.right));
}

//处理根节点
list.add(node);

returnlist;

}

//实现广度优先遍历
//广度优先遍历又称为按层遍历,整个遍历算法先遍历二叉树的第一层(根节点),再遍历根节点的两个子节点(第二层),以此类推
publicList<TreeNode>breadthFirst(){

Queue<TreeNode>queue=newArrayDeque<TreeNode>();
List<TreeNode>list=newArrayList<TreeNode>();
if(root!=null){
//将根元素加入“队列”
queue.offer(root);
}
while(!queue.isEmpty()){
//将该队列的“队尾”的元素添加到List中
list.add(queue.peek());
TreeNodep=queue.poll();
//如果左子节点不为null,将它加入“队列”
if(p.left!=null){
queue.offer(p.left);
}
//如果右子节点不为null,将它加入“队列”
if(p.right!=null){
queue.offer(p.right);
}
}
returnlist;
}

}

㈢ 图的矩阵深度和广度遍历算法

图的遍历是指从图中任一给定顶点出发,依次访问图中的其余顶点。如果给定的图是连通图,则从图中的任意一点出发,按照一个指定的顺序就可以访问到图中的所有顶点,且每个顶点只访问一次。这个过程称为图的遍历。
图的遍历比树的遍历复杂的多。树是一种特殊类型的图,即无圈(无回路)连通图。树中的任意两个顶点间都有唯一的路径相通。在一个顶点被访问过之后,不可能又沿着另外一条路径访问到已被访问过的结点。而图中的顶点可能有边与其他任意顶点相连
。因此在访问了某个顶点之后,可能沿着另一条边访问已被访问过的顶点。例如图(a)中的G1,在访问了V1,V2和V3之后,有可能沿着边(V3,V1)访问到V1。为了避免一顶点被多次访问,可以设立一个集合Visited,用来记录已被访问过的顶点。它的初值为空
集。一旦V1被访问过,即把V1加到集合Visited中。图的遍厉通常有两种:图的深度优先
搜索和图的广度优先搜索。
1)图的深度优先搜索
从图G=(V,E)的一个顶点V0出发,在访问了任意一个与V0相邻且未被访问过的顶点W1之后,再从W1出发,访问和W1相邻且未被访问过的顶点W2,然后再从W2出发进行如上所述访问,直到找到一个它相邻的结点,都被访问过的结点为止。然后退回到尚有相
邻结点未被访问过的顶点,再从该顶点出发,重复上述搜索过程,直到所有被访问过的顶点的邻接点都被访问过为止。图的这种遍历过程就称为图的深度优先搜索。例如从顶点V1出发对图3.3.5进行深度优先搜索,遍历的顺序为 V1,V2,V5,V10,V6,V7,V3,V12,V1
1,V8,V4,V9。(与邻接表中的邻接点排列顺序有关,即p->next.vertex=v2 or v3对遍历
顺序有影响 )
例25.(p194.c)图的深度优先搜索。从图G的顶点V0
发进行深度优先搜索,打印出各个顶点的遍历顺序。
解:图的深度优先搜索法为:
(1)首先访问V0并把V0加到集合visited中;
(2)找到与V0相邻的顶点W,若W未进入
visited中,则以深度优先方法从W开始搜索。
(3)重复过程(2)直到所有于V0相邻的顶点
都被访问过为止。

下面是对用邻接表表示的图G进行深度优先搜索的程序
int rear=0; /*Visit和rear都为全局变量*/
int visit[500];
depth_first_search(g,v0) /*从V0开始对图G进行深度
优先搜索*/
graphptr g[ ]; /*指针数组,为邻接表表头顶点指针
g[vi]...g[vn]*/
int v0; /*这里V0和W都是顶点标号,如V0=0或1*/
{ /*g[v0]是顶点V0的表头指针*/
int w;
graphptr p; /*链表的结点指针*/
visit [++rear]=v0;
printf("%d\n",v0);
p=g[v0];/*指定一个顶点,通过邻接表表头指针
,访问v0的邻接顶点*/
while (p!=NULL)
{
w=p->vertex ;/*这里W是与V0相邻的一个顶点*/
if (!visited(w))/*当V0的相邻结点,W未被访问时,从W开始遍厉*/
depth_first_search(g,w);
p=p->next;/*接着访问另一个相邻顶点*/
}
}
int visited(w) /*检查顶点w是否进入visited(w)*/
int w ;
{
int i;
for (i=1;i<=rear;i++)
if (visit [ i ] == w) return(1);/*W在visit[]中,说明被访问过*/
return(0); /*W不在visit[]中,说明未被访问过,返回0*/
}
2)图的广度优先搜索
从图G的一个顶点V0出发,依次访问V0的邻接点K1,K2...Kn。然后再顺序访问K1,K2...Kn的所有尚未被访问过的邻接点。如此重复,直到图中的顶点都被访问过为止。图的这种搜索称为图的广度优先搜索。例如:从V1出发按广度优先搜索方法遍历图3.3.5,顶
点的访问顺序为V1,V2,V3,V4,V5,V6,V7,V8,V9,V10,V11,V12。
图的广度优先搜索类似树的按层次遍历,需要有一个队列来存放还没
有来得及处理的顶点。图的广度优先搜索算法为:
(1)首先把V0放入队列;
(2)若队列为空则结束,否则取出队列的头V;
(3)访问V并把所有与V相邻且未被访问的顶点插入队列;
(4)重复(2)-(3)直到队列为空。
上述算法中所有已被访问过的顶点都放在队列中,因此只要检查某个顶点是否在队列中就可以判断出该顶点是否已被访问过。
广度搜索法的程序如下:
broad_first_search(g,v0) /*从V0开始对图g进行广度优先搜索*/
graphptr g[ ]; /*为邻接表,表头顶点指针*/
int v0;
{
int queue[500],front =1, tail=1,v;
graphptr p;
queue [tail]=v0; /*把V0插入队列queue*/
while (front <=tail)/*当队列不为空*/
{
v=queue[front++]; /*取出队列中的顶点*/
printf("%d\n",v); /*访问该顶点*/
p=g[v]; /*从顶点V的链表来考虑与V相邻的顶点*/
while (p!=NULL)
{
v=p->vertex; /*从第一个结点(即边)中找出相邻的顶点*/
if (!visited(queue,tail,v))/*判断顶点是否进入队列,如进入队列
说明已被访问或将要访问*/
queue[++tail]=v;/*如果该顶点未被访问过,将此相邻顶点插入队列*/
p=p-->next;/*再考虑该结点的下一个相邻顶点*/
}
}
}
visited (q,tail,v)/*判断顶点是否被访问过,访问过时,返回1,否则返回0*/
int q[ ],tail,v;/*进入队列的顶点,在front之前的顶点已被访问过打印输出,
在front和tail之间的顶点是即将要访问顶点*/
{
int i;
for(i=1;i<=tail;i++)/*扫描队列,确定v是否在队列中,在队列中返回1,否则返回0*
/
if (q[i]==v)return(1);/*队列中的顶点都认为已被访问过*/
return(0);
}

深度优先的非递归算法

/*设当前图(或图的某个连通分枝)的起始访问点为p*/
NodeType stackMain,stackSec
visit(p)
p->mark=true;
do
{
for(all v isTheConnectNode of (G,p))//将当前点的邻接点中的所有结点压入副栈中
if(v.marked==false)
statckSec.push(v)
//将副栈中的点依次弹出,压入主栈中,这与非递归算法中使用队列的意图类似
while(!stackSec.isEmpty())
stackMain.push(statckSec.pop());
do//找出下一个未访问的结点或者没找到,直到栈为空
{
if(!stackMain.isEmpty())

{
p=stackMain.pop();

}
}while(p.marked==true&&!stackMain.isEmpty())
if(p.marked==false)//访问未访问结点.

{

visit(p);

p.marked=true;

}

}while(!stackMain.isEmpty())

㈣ 试分别画出自顶点1出发进行遍历所得的深度优先生成树和广度优先生成树。

从1开始,1连接7,7连接3,3连接4,4连接5,5连接6,6连接2(1已经连过了)(2连接了3,7,但是3和7都已经连过,所以回到上一级6,6的连接是1,2都已经连过,所以再回到上一级5)5连接10 。

(10连接1,6都已经连过了,所以回到上一级5,但是5的所有连接点都连过了,所以回到上一级4)4连接9,(9连接5,10都已经连过了,所以回到上一级4,4也已经练完了,所以再回到上一级3)3连接8,至此连完。

广度遍历:从1开始,连接7和9,下一个是7,连接3和10 ,下一个是9,连接5,下一个是3,连接4和8,下一个是10 连接6,下一个是5,没有什么连接的,下一个是4,没有什么连接的,下一个是8,没有什么连接的,下一个是6,连接2,至此连完。

(4)树广度遍历算法扩展阅读:

通用定义:

若从图的某顶点出发,可以系统地访问到图中所有顶点,则遍历时经过的边和图的所有顶点所构成的子图,称作该图的生成树。

(1)若G是强连通的有向图,则从其中任一顶点v出发,都可以访问遍G中的所有顶点,从而得到以v为根的生成树。

(2)若G是有根的有向图,设根为v,则从根v出发可以完成对G的遍历,得到G的以v为根的生成树。

(3)若G是非连通的无向图,则要若干次从外部调用DFS(或BFS)算法,才能完成对G的遍历。每一次外部调用,只能访问到G的一个连通分量的顶点集,这些顶点和遍历时所经过的边构成了该连通分量的一棵DFS(或BPS)生成树。

G的各个连通分量的DFS(或BFS)生成树组成了G的DFS(或BFS)生成森林。

(4)若G是非强连通的有向图,且源点又不是有向图的根,则遍历时一般也只能得到该有向图的生成森林。

㈤ 名词解释 深度遍历 广度遍历 完全二叉树

深度遍历就是从根开始,逐个往下找,知道找不到了,就退回来,继续往下找。结束的标志是全部都找了一遍。
广度遍历,从根开始,遍历一下和根相连的所有节点,遍历完毕之后,再遍历其中一个节点的所有邻居节点。就像是画波浪一样,一层层的。
完全二叉树,除叶子节点之外每一个中间节点又两个儿子。

㈥ 关于数据结构的深度优先遍历和广度优先遍历以及最小生成树 第四大题的第一题

首先看一下深度优先和广度优先怎么遍历:
深度优先遍历从某个顶点出发,首先访问这个顶点,然后找出刚访问这个结点的第一个未被访问的邻结点,然后再以此邻结点为顶点,继续找它的下一个新的顶点进行访问,重复此步骤,直到所有结点都被访问完为止。
广度优先遍历从某个顶点出发,首先访问这个顶点,然后找出这个结点的所有未被访问的邻接点,访问完后再访问这些结点中第一个邻接点的所有结点,重复此方法,直到所有结点都被访问完为止。
在看题目,其要求按顺时针方向:
深度优先序列:V1 V2 V3 V5 V4
广度优先序列:V1 V2 V4 V3 V5
最小生成树,有两种方法,prim和kruskal算法。
这题最小生成树如下:
[(V4,V5),(V1,V4),(V2,V4),(V5,V3)],其中(V4,V5)表示V4和V5点之间连线。如下图类似(这里简单表示一下)。
V1 V2 V3
\ / /
V4----V5

㈦ 求设计一个程序,实现树的深度优先与广度优先遍历。急急急!!

二叉树的深度优先遍历的非递归的通用做法是采用栈,广度优先遍历的非递归的通用做法是采用队列。

为了方便程序验证,首先构造一个如图所示的二叉树。

源码

/*************************** bintree.h文件 *****************************/

#ifndef _BINTREE_H

#define _BINTREE_H

template <class T>

class CBintree

{

public:

CBintree();

bool Depth_RF();//先根深度遍历

bool Depth_RM();//中根深度遍历

bool WidthFS(); //层次遍历

protected:

private:

struct TreeNode

{

T va;

TreeNode *plchild;

TreeNode *prchild;

};

TreeNode *m_pBintree;

};

#endif

template <class T>

CBintree<T>::CBintree()

{

m_pBintree = new TreeNode;

TreeNode *pNode2 = new TreeNode;

TreeNode *pNode3 = new TreeNode;

TreeNode *pNode4 = new TreeNode;

TreeNode *pNode5 = new TreeNode;

TreeNode *pNode6 = new TreeNode;

TreeNode *pNode7 = new TreeNode;

m_pBintree->va = (T)1;

m_pBintree->plchild = pNode2;

m_pBintree->prchild = pNode3;

pNode2->va = (T)2;

pNode2->plchild = pNode4;

pNode2->prchild = pNode5;

pNode3->va = (T)3;

pNode3->plchild = NULL;

pNode3->prchild = pNode6;

pNode4->va = (T)4;

pNode4->plchild = NULL;

pNode4->prchild = NULL;

pNode5->va = (T)5;

pNode5->plchild = pNode7;

pNode5->prchild = NULL;

pNode6->va = (T)6;

pNode6->plchild = NULL;

pNode6->prchild = NULL;

pNode7->va = (T)7;

pNode7->plchild = NULL;

pNode7->prchild = NULL;

}

template <class T>

bool CBintree<T>::Depth_RF() //先根深度遍历

{

cout << "先根遍历序列:\n";

stack <TreeNode> s;

s.push(*m_pBintree);

while (!s.empty())

{

TreeNode node_s = s.top();

cout << node_s.va << "\n";

s.pop();

if (node_s.prchild != NULL)

{

s.push(*node_s.prchild);

}

if (node_s.plchild != NULL)

{

s.push(*node_s.plchild);

}

}

return true;

}

template <class T>

bool CBintree<T>::Depth_RM() //中根深度遍历

{

cout << "中根遍历序列:\n";

stack <TreeNode> s;

TreeNode *pNode = m_pBintree;

while (pNode != NULL || !s.empty())

{

while (pNode != NULL)

{

s.push(*pNode);

pNode = pNode->plchild;

}

if (!s.empty())

{

TreeNode node_s = s.top();

cout << node_s.va << "\n";

s.pop();

pNode = node_s.prchild;

}

}

return true;

}

template <class T>

bool CBintree<T>::WidthFS() //层次遍历

{

cout << "层次遍历序列:\n";

queue <TreeNode> q;

q.push(*m_pBintree);

while (!q.empty())

{

TreeNode *pNode = &q.front();

cout << pNode->va << "\n";

if (pNode->plchild != NULL)

{

q.push(*pNode->plchild);

}

if (pNode->prchild != NULL)

{

q.push(*pNode->prchild);

}

q.pop();

}

return true;

}

/************************ main.cpp 文件 ****************************/

#include <iostream>

#include <stack>

#include <queue>

using namespace std;

#include "bintree.h"

int main()

{

CBintree <int> bt;

bt.Depth_RF();

bt.Depth_RM();

bt.WidthFS();

return 0;

}

/***************** 教科书标准算法及优化算法(转)*******************/
1.先序遍历非递归算法
void PreOrderUnrec(Bitree *t)
{
Stack s;
StackInit(s);
Bitree *p=t;

while (p!=NULL || !StackEmpty(s))
{
while (p!=NULL) //遍历左子树
{
visite(p->data);
push(s,p);
p=p->lchild;
}

if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子树遍历
{
p=pop(s);
p=p->rchild;
}//endif

}//endwhile
}

2.中序遍历非递归算法
void InOrderUnrec(Bitree *t)
{
Stack s;
StackInit(s);
Bitree *p=t;

while (p!=NULL || !StackEmpty(s))
{
while (p!=NULL) //遍历左子树
{
push(s,p);
p=p->lchild;
}

if (!StackEmpty(s))
{
p=pop(s);
visite(p->data); //访问根结点
p=p->rchild; //通过下一次循环实现右子树遍历
}//endif

}//endwhile
}

3.后序遍历非递归算法
typedef enum{L,R} tagtype;
typedef struct
{
Bitree ptr;
tagtype tag;
}stacknode;

typedef struct
{
stacknode Elem[maxsize];
int top;
}SqStack;

void PostOrderUnrec(Bitree t)
{
SqStack s;
stacknode x;
StackInit(s);
p=t;

do
{
while (p!=null) //遍历左子树
{
x.ptr = p;
x.tag = L; //标记为左子树
push(s,x);
p=p->lchild;
}

while (!StackEmpty(s) && s.Elem[s.top].tag==R)
{
x = pop(s);
p = x.ptr;
visite(p->data); //tag为R,表示右子树访问完毕,故访问根结点
}

if (!StackEmpty(s))
{
s.Elem[s.top].tag =R; //遍历右子树
p=s.Elem[s.top].ptr->rchild;
}
}while (!StackEmpty(s));
}//PostOrderUnrec

4.前序最简洁非递归算法

void PreOrderUnrec(Bitree *t)

{

Bitree *p;

Stack s;

s.push(t);

while (!s.IsEmpty())

{

s.pop(p);

visit(p->data);

if (p->rchild != NULL) s.push(p->rchild);

if (p->lchild != NULL) s.push(p->lchild);

}

}

5.后序算法之二

void BT_PostOrderNoRec(pTreeT root)

{

stack<treeT *> s;

pTreeT pre=NULL;

while ((NULL != root) || !s.empty())

{

if (NULL != root)

{

s.push(root);

root = root->left;

}

else

{

root = s.top();

if (root->right!=NULL && pre!=root->right){

root=root->right;

}

else{

root=pre=s.top();

visit(root);

s.pop();

root=NULL;

}

}

}

}

㈧ JS树结构数据的遍历

title: JS树结构数据的遍历
date: 2022-04-14
description: 针对项目中出现树形结构数据的时候,我们怎样去操作他

项目中我们会经常出现对树形结构的遍历、查找和转换的场景,比如说DOM树、族谱、社会机构、组织架构、权限、菜单、省市区、路由、标签等等。那针对这些场景和数据,我们又如何去遍历和操作,有什么方式或者技巧可以简化我们的实现思路。下面我们将针对常规出现的场景去总结一下我们的遍历方式

树的特点
1、每个节点都只有有限个子节点或无子节点;
2、没有父节点的节点称为根节点;
3、每一个非根节点有且只有一个父节点;
4、除了根节点外,每个子节点可以分为多个不相交的子树;
5、树里面没有环路

下面的图片表示一颗树

在下面的JS中我们由多棵树组成我们的数据

在这数据中我们如何评判数据是否为叶节点(也就是最后一级),我们每个节点都会存在children属性,如果不存在children属性或者children不是一个数组或者children为数组且长度为0我们则认为他是一个叶节点

我们针对树结构的操作离不开遍历,遍历的话又分为广度优先遍历、深度优先遍历。其中深度优先遍历可以通过递归和循环的方式实现,而广度优先遍历的话是非递归的

从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止。即访问树结构的第n+1层前必须先访问完第n层。

简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。

所以我们的实现思路是,维护一个队列,队列的初始值为树结构根节点组成的列表,重复执行以下步骤直到队列为空:
取出队列中的第一个元素,进行访问相关操作,然后将其后代元素(如果有)全部追加到队列最后。

深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。这个算法会尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止

1、先序遍历
访问子树的时候,先访问根再访问根的子树

2、后序遍历
访问子树的时候,先访问子树再访问根

1、先序遍历
先序遍历与广度优先循环实现类似,要维护一个队列,不同的是子节点不追加到队列最后,而是加到队列最前面

2、后序遍历
后序遍历就略微复杂一点,我们需要不断将子树扩展到根节点前面去,执行列表遍历,并且通过一个临时对象维护一个id列表,当遍历到某个节点如果它没有子节点或者它本身已经存在于我们的临时id列表,则执行访问操作,否则继续扩展子节点到当前节点前面

对于树结构的遍历操作,其实递归是最基础,也是最容易理解的。递归本身就是循环的思想,所以可以用循环来改写递归,以上的方式在项目中已经廊括了大部分的场景了,我们在日常开发中可以根据场景或者需要去选择我们的遍历方式,或者基于此对他进行调整和优化,至于每种方式的空间复杂度和时间复杂度我们在这个地方就不去尝试了,各位感兴趣可以自己去验证。

广度优先搜索

树的遍历

深度优先搜索

图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)

二叉树遍历(前序,后序,中序,层次)递归与迭代实现JavaScript

JS树结构操作:查找、遍历、筛选、树和列表相互转换

㈨ js广度遍历生成树,树的定义

先序,后序,中序针对二叉树。
深度、广度针对普通树。深度遍历:从树根开始扫描,顶层扫描完了,从一层最左(也可以右)面的结点往下层扫描,直到下层已无结点,这时所有靠最左(右)的结点全部扫描完毕,从树梢往上退一层,看这层旁有无兄弟结点,有的话还是一样从最左(右)边开始扫描,这是个递归概念,利用这一方法来遍历整棵树。广度遍历:从树根开始扫描,顶层扫描完了,扫描一层的所有结点,扫描二层的所有结点,,扫描最底层的结点。

热点内容
落叶片拍摄脚本 发布:2025-05-14 20:40:49 浏览:797
安卓为什么不能用cmwap 发布:2025-05-14 20:40:43 浏览:656
jquery获取上传文件 发布:2025-05-14 20:27:57 浏览:43
云web服务器搭建 发布:2025-05-14 20:25:36 浏览:525
汽修汽配源码 发布:2025-05-14 20:08:53 浏览:742
蜜蜂编程官网 发布:2025-05-14 19:59:28 浏览:57
优酷怎么给视频加密 发布:2025-05-14 19:31:34 浏览:635
梦三国2副本脚本 发布:2025-05-14 19:29:58 浏览:860
phpxmlhttp 发布:2025-05-14 19:29:58 浏览:434
Pua脚本 发布:2025-05-14 19:24:56 浏览:449