二叉树的深度优先和广度优先遍历

http://steven-hong.javaeye.com/blog/493665

图的深度优先搜索法是树的先根遍历的推广,它的基本思想是:从图G的某个顶点v0出发,访问v0,然后选择一个与v0相邻且没被访问过的顶点vi访问,再 从vi出发选择一个与vi相邻且未被访问的顶点vj进行访问,依次继续。如果当前被访问过的顶点的所有邻接顶点都已被访问,则退回到已被访问的顶点序列中 最后一个拥有未被访问的相邻顶点的顶点w,从w出发按同样的方法向前遍历,直到图中所有顶点都被访问。

图的广度优先搜索是树的按层次遍历的推广,它的基本思想是:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点 vi1,vi2, …, vi t,并均标记已访问过,然后再按照vi1,vi2, …, vi t的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止。

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

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

 

源码:

/*************************** 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;

                     }

              }

       }

}

转载于:https://www.cnblogs.com/sunnytracy/archive/2009/10/27/1590876.html

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

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

相关文章

面试官问:你做过什么Java线程池实践,我写了一篇博客给他看~

线程池大家都## 标题很熟悉&#xff0c;无论是平时的业务开发还是框架中间件都会用到&#xff0c;大部分都是基于JDK线程池ThreadPoolExecutor做的封装&#xff0c; 都会牵涉到这几个核心参数的设置&#xff1a;核心线程数&#xff0c;等待(任务)队列&#xff0c;最大线程数&am…

《硝烟中的Scrum和XP》书摘(1)

Nokia的Scrum标准&#xff1a;迭代要有固定的时长&#xff08;TimeBox&#xff09;&#xff0c;不能超过六个星期。每一次迭代的结尾&#xff0c;代码必须经过QA的测试。Scrum团队必须有产品负责人&#xff0c;而且团队都清楚这个人是谁。产品负责人必须有产品的Backlog&#x…

【Blog.Idp开源】支持在线密码找回

&#xff08;一个做认证平台&#xff0c;必须会遇到的一个问题&#xff09;BCVP框架&#xff0c;是基于:ASP.NETCore5.0VUE.jsIdentityServer4等核心技术&#xff0c;实现的前后端分离与动态认证鉴权一体化平台。01密码找回认证中心绕不开的话题Architecture Design.无论你是自…

我的狗丢了,所以我能加你微信吗? | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源网络&#xff0c;侵权删&#xff09;

Yahoo网站性能最佳体验的34条黄金守则

Yahoo!的Exceptional Performance团队为改善Web性能带来最佳实践。他们为此进行了一系列的实验、开发了各种工具、写了大量的文章和博客并在各种会议上参与探讨。最佳实践的核心就是旨在提高网站性能。 Excetional Performance团队总结出了一系列可以提高网站速度的方法。可以分…

hdu 4597 + uva 10891(一类区间dp)

题目链接&#xff1a;http://vjudge.net/problem/viewProblem.action?id19461 思路&#xff1a;一类经典的博弈类区间dp,我们令dp[l][r]表示玩家A从区间[l, r]得到的最大值&#xff0c;于是就有dp[l][r] sum[l][r] - min(dp[l i][r], dp[l][r - i]) (i > 1 && i …

将VC++6.0的代码迁移到VS2005常见问题总结(Window核心编程第五版以前代码在VS2005无法编译的解决方案)...

额喜新厌旧是男人的通病吧&#xff0c;可是呢VS2005的界面看着的确比VC6.0看着舒服&#xff0c;而且也算用习惯了吧。可是网上现在大部分C/C的代码还是用VC6.0的。这为我们这些菜鸟的学习之路增添了不少障碍&#xff0c;可能有很多朋友在这一步就放弃了吧或者抹黑走下去&#x…

被问到了!为什么一定要使用分布式,内行啊

一、为什么要使用分布式 如果需求要测试 4000 虚拟用户数&#xff0c;而本机只能支持1000 虚拟用户&#xff0c;如果测试结果有可能是电脑的问题&#xff0c;而不是服务器的问题&#xff0c;所以需要把其他虚拟用户分配到多台电脑上 把虚拟用户数分配到其他电脑上面去执行&am…

设计模式之享元

享元模式介绍享元模式主要在于共享通用对象&#xff0c;减少内存的使用&#xff0c;提升系统的访问效率。而这部分共享对象通常比较耗费内存或者需要查询大量接口或者使用数据库资源&#xff0c;因此统一抽离作为共享对象使用。在使用此模式过程中&#xff0c;需要使用享元工厂…

真正拉开人与人之间的差距是什么?

全世界只有3.14 % 的人关注了青少年数学之旅身边总有些人看上去很轻松&#xff0c;不仅在工作中游刃有余&#xff0c;还知识渊博&#xff0c;对各种事情有自己的思考。这样的人一定是天生的学霸吧。其实学习不一定要在教室里从一本书的第一页开始看&#xff0c;学习可以很轻松。…

ORACLE备份中的压缩

默认的情况下&#xff0c;如果没有配置压缩备份&#xff0c;或者备份的时候没有发出compressed 命令&#xff0c;那么ORACLE会采用NULL数据块的压缩方法来备份数据库&#xff0c;采用这种方法备份&#xff0c;ORACLE就不会备份从未使用过的数据块。另外一种备份就是采用compres…

[导入]【翻译】WF从入门到精通(第八章):调用外部方法及工作流

摘要: 学习完本章&#xff0c;你将掌握&#xff1a; 1.创建并调用你的工作流外部的本地数据服务 2.理解怎样使用接口来为宿主进程和你的工作流之间进行通信。 3.使用设计的外部方法在你的工作流和宿主应用程序之间传输数据。 4.在一个正执行的工作流中调用其它工作流 阅读全文…

(译)Windsor入门教程---第三部分 编写第一个Installer

原文&#xff1a;http://docs.castleproject.org/Windsor.Windsor-tutorial-ASP-NET-MVC-3-application-To-be-Seen.ashx 简介 在第二部分我们创建了控制器工厂。现在我们要把我们的控制器交给Windsor来管理。 Installer Windsor有一个专门的类installer.cs&#xff0c;用来向容…

在 ASP.NET Core 中使用 Serilog 使用 Fluentd 将日志写入 Elasticsearch

在 ASP.NET Core 中使用 Serilog 使用 Fluentd 将日志写入 Elasticsearch原文来自&#xff1a;https://andrewlock.net/writing-logs-to-elasticsearch-with-fluentd-using-serilog-in-asp-net-core/对于在 Kubernetes 中运行的应用程序&#xff0c;将日志消息存储在一个中心位…

2021年度最全面JVM虚拟机,类加载过程与类加载器

前言 类装载器子系统是JVM中非常重要的部分&#xff0c;是学习JVM绕不开的一关。 一般来说&#xff0c;Java 类的虚拟机使用 Java 方式如下&#xff1a; Java 源程序&#xff08;.java 文件&#xff09;在经过 Java 编译器编译之后就被转换成 Java 字节代码&#xff08;.class …

做生意最重要的诚信呢??? | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源网络&#xff0c;侵权删&#xff09;

从笑话中看到产品创意

西贝在公司的洗手间中看到了2则笑话&#xff0c;体会出来笑话的另一个含义&#xff0c;其实它和产品有很多相似之处的。第一则&#xff1a;某学校的小师妹看上了校中的师兄帅哥&#xff0c;决定主动追求。小师妹遇上之后主动搭讪“师兄&#xff0c;有女朋友吗&#xff1f;”帅哥…

快速配置Ehcache

1. 编写ehcache.xml文件&#xff0c;将该文件放置于classpath路径下。代码如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?><ehcache> <!-- 缓存文件生成之后所放置的路径 --> <diskStore path"D:/Develop/tomcat-6…

.NET 6 预览版 7 发布--(最后一个预览版)

原文&#xff1a;bit.ly/2VJxjxQ作者&#xff1a;Richard翻译&#xff1a;精致码农-王亮说明&#xff1a;文中有大量的超链接&#xff0c;这些链接在公众号文章中被自动剔除&#xff0c;一部分包含超链接列表的小段落被我删减了&#xff0c;如果你对此感兴趣&#xff0c;请参考…

面试避坑手册之 Java字节流和字符流总结IO流!

从接收输入值说起 在日常的开发应用中&#xff0c;有时候需要直接接收外部设备如键盘等的输入值&#xff0c;而对于这种数据的接收方式&#xff0c;我们一般有三种方法&#xff1a;字节流读取&#xff0c;字符流读取&#xff0c;Scanner 工具类读取。 字节流读取 直接看一个…