C++实现树的建立,查找,遍历输出:

#include<iostream>

#include<stack>
using namespace std;

template<class T>
class myqueue;

template<class T>
class Node
{
friend myqueue<T>;
private:
T data;
Node<T>* next;
public:
Node()
{
next=0;
}
Node(T d)
{
data=d;
next=0;
}
};
template<class T>
class myqueue
{
private:  
    Node<T> *tail;  
public:  
    myqueue()  
    {  
        tail=new Node<T>();  
//tail->next=NULL;
        tail->next=tail;  //这种表示采用的是循环队列,且队列头是一个哨兵为空,它的下一个才是队列的第一个数据
    }  
  
    bool empty()  
    {  
//return (NULL==tail->next)
        return (tail->next==tail);  
    }  
  
    void push(T d)  
    {  
        Node<T> *p=new Node<T>(d); 
//p->next=NULL;
        p->next=tail->next;  
        tail->next=p;  
        tail=p;  //始终标记出尾部的位置
    }  
  
    T front()  //取队列的第一个元素
    {  
        if(empty())  
        {  
            cout<<"queue is empty!"<<endl;  
            exit(0);  
        }  
        Node<T> *p=tail->next;  //这是一个循环链表构成的队列,尾部的链接的下一个就是队列头
        T data=p->next->data;  //队列头链接的下一个才是第一个数据
        return data;  
    }  
  
    void pop()  //队列的第一个元素出队列
    {  
        Node<T> *p=tail->next;  
        Node<T> *q=p->next;  
        p->next=q->next;  
        if(q==tail)  
            tail=p;  
        delete q;  
q=NULL;
    }  
};

class CStree;  //children sibling tree
  
class CSnode  
{  
private:  
    char data;  
    CSnode *firstchild;  //左孩子右兄弟
    CSnode *nextsibling;  
    friend CStree;  
};  
  
class CStree  
{  
public:  
    void Create_Tree(CSnode *&T)    //创建树  
    {  
        //按照从上到下,从左往右的顺序输入“双亲——孩子”的有序对,建立树的孩子兄弟存储结构  
        //输入时,以('#','#')为结束标志,根结点双亲为空,也是以'#'来表示  
        T=NULL;  
        myqueue<CSnode *> q;  //队列中存放的是树的一个节点单元
        char parent,child;  
        cout<<"输入双亲,孩子有序对,以'#','#'作为输入结束标志"<<endl;  
        for(cin>>parent>>child;child!='#';cin>>parent>>child)  
        {  
            CSnode *p=new CSnode;  
            p->data=child;  
            p->firstchild=p->nextsibling=NULL; //暂时现将它们置空  
            q.push(p);  
            if(parent=='#')  
                T=p;  //根节点,同时T也是最后链接好的那棵树
            else  
            {  
                CSnode *r;  
                CSnode *s=q.front();  //树的第一个节点单元,这个单元有parent数据、存放的孩子数据、左孩子指针、右兄弟指针
                while(s->data!=parent)     //第一次循环的时候data=a,第二次循环的时候data=b,parent=a,刚好错开了,通过parent的变化标注每次的链接
                {  
                    q.pop();  //清除的是myqueue中的data
                    s=q.front();  
                }  
                if(!s->firstchild)   //链接第一个孩子结点  
                {  
                    s->firstchild=p;  
                    r=p;  //设定r是为了方便后一步链接兄弟节点
                }  
                else    //链接兄弟结点
                {  
                    r->nextsibling=p;  
                    r=p;  
                }  
            }  
        }//end_for  
    }//end_void  
  
    void Get_Children(CSnode *T)    //找结点孩子  
    {  
        //在T的还在兄弟表示法中,求输入结点的孩子  
        cout<<"输入你要找的结点的值:";  
        char x;  
        cin>>x;  
        myqueue<CSnode *> q;  
        if(!T)  
        {  
            cout<<"这是一棵空树!"<<endl;  
            return ;  
        }  
        q.push(T);  
        CSnode *r=NULL;  
        if(T->data==x)  
            r=T;  
        else  
        {  
            do  
            {  
                CSnode *p=q.front();  
                q.pop();  
                if(p->firstchild && p->firstchild->data==x)  //纵向找
                {  
                    r=p->firstchild;  
                    break;  
                }  
                if(p->firstchild && p->firstchild->data!=x)  
                    q.push(p->firstchild);  
                if(p->nextsibling && p->nextsibling->data==x)  //横向找
                {  
                    r=p->nextsibling;  
                    break;  
                }  
                if(p->nextsibling && p->nextsibling->data!=x)  
                    q.push(p->nextsibling);  
            }while(!q.empty());  
        }  
        if(r==NULL)  
        {  
            cout<<"树T中没有结点"<<x<<endl;  
            return;  
        }  
        else  
            Print_children(r);  
    }  
  
    void Print_children(CSnode *p)  
    {  
        CSnode *q=p->firstchild;  
        if(!q)  
        {  
            cout<<"结点"<<p->data<<"没有孩子"<<endl;  
            return ;  
        }  
        cout<<"结点"<<p->data<<"的所有孩子是:";  
        while(q)  
        {  
            cout<<q->data<<"  ";  //输出左孩子
            q=q->nextsibling;  //横向输出左孩子的兄弟
        }  
        cout<<endl;  
    }  
  
    void OutPath(CSnode *T,stack<char> &s) //求路径  
    {  
        //输出树T中从根节点到所有叶子结点的路径,用栈暂存路径  
        while(T)  
        {  
            s.push(T->data); //将当前层访问的结点记入路径  s是一个堆栈
            if(!T->firstchild)  //没有左孩子
                Print_stack(s); //输出从栈底到栈顶的元素 ,同时也清空了s栈
            else  
                OutPath(T->firstchild,s); //继续遍历左孩子分支,递归操作
            s.pop();    //将当前层访问的结点从路径中删除  
            T=T->nextsibling; //继续访问兄弟分支
        }  
    }  
  
    void Print_stack(stack<char> s)  
    {  
        char temp[100];  
        int i=0;  
        while(!s.empty())  
        {  
            temp[i]=s.top();  //返回栈顶元素的值,但是不删除该元素
            s.pop();  //删除栈顶元素
            i++;  
        }  
        cout<<"从根节点到叶子结点的一条路径:";  
        for(int j=i-1;j>0;j--)  
            cout<<temp[j]<<"->";  
        cout<<temp[0]<<endl;  
    }  
  
    void PreRoot_Traverse(CSnode *T) //先根遍历  ,且是从左往右进行的  
    {  
        if(T)  
        {  
            cout<<T->data<<"  ";  
            PreRoot_Traverse(T->firstchild);   //递归,一个递归完了才能够进行另一个递归
            PreRoot_Traverse(T->nextsibling);  
        }  
    }  
  
    void PostRoot_Traverse(CSnode *T)  //后根遍历,且是从左往右进行的  
    {  
        if(T)  
        {  
            PostRoot_Traverse(T->firstchild);  
            cout<<T->data<<"  ";  
            PostRoot_Traverse(T->nextsibling);  
        }  
    }  
  
    void LevelOrder_Traverse(CSnode *T) //层次遍历  
    {  
        myqueue<CSnode *> q;  
        CSnode *t;  
        q.push(T);  
        do  
        {  
            t=q.front();  
            do  
            {  
                cout<<t->data<<"  ";  
                if(t->firstchild)  
                    q.push(t->firstchild);  
                t=t->nextsibling;  
            }while(t);  //把每一层遍历完再换到下一层
          q.pop();  
        }while(!q.empty());  
    }  
};  
int main()  
{  
    CStree tree;  
    CSnode *T;  
    tree.Create_Tree(T);  
  
    tree.Get_Children(T);  
  
    stack<char> s;  
    tree.OutPath(T,s);  
  
    cout<<"树的先根遍历为:";  
    tree.PreRoot_Traverse(T);  
    cout<<endl;  
  
    cout<<"树的后根遍历为:";  
    tree.PostRoot_Traverse(T);  
    cout<<endl;  
  
    cout<<"层次遍历树为:";  
    tree.LevelOrder_Traverse(T);  
    cout<<endl;  
      
    return 0;  
}

C++实现树的建立,查找,遍历输出相关推荐

  1. 树(二叉树层次遍历输出及二叉树前序遍历输入)

    前两篇解释了二叉树的有关逻辑概念及前中后序输出递归代码的实现,这篇将讲述二叉树层次遍历输出如何实现以及二叉树前序遍历输入的两种情况. 定义结构体 struct BiNode{char data;BiN ...

  2. C++读取XML树的建立和遍历

    2019独角兽企业重金招聘Python工程师标准>>> XML文件为嵌套结构,分析XML文件并提取关键字和数据的过程分为两个部分: 1. 字符串处理,这一部分为编译原理的一些基础知识 ...

  3. 树和森林的遍历 (树的建立和输出)

    树和森林的遍历 对于树的遍历从其结构出发有三种搜索路径:先根(次序)遍历树,先访问根结点,然后依次先根遍历根的各棵子树:后根(次序)遍历树,先依次后根遍历根的各棵子树,然后访问根结点:按层(次序)遍历 ...

  4. 二元查找树的后序遍历结果

    题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回 true ,否则返回 false . 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: ...

  5. 二叉查找(排序)树/二叉树----建树,遍历

    二叉查找(排序)树/二叉树----建树,遍历 import java.util.ArrayList; import java.util.LinkedList; import java.util.Lis ...

  6. 程序员面试题精选100题(06)-二元查找树的后序遍历结果[数据结构]

    题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: 8   ...

  7. Algorithm:C++语言实现之SimHash和倒排索引算法相关(抽屉原理、倒排索、建立查找树、处理Hash冲突、Hash查找)

    Algorithm:C++语言实现之SimHash和倒排索引算法相关(抽屉原理.倒排索.建立查找树.处理Hash冲突.Hash查找) 目录 一.SimHash算法 1.SimHash算法五个步骤 2. ...

  8. 6.二元查找树的后序遍历结果[PostOrderOfBST]

    [题目] 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: 8 ...

  9. 判断整数序列是不是二元查找树的后序遍历结果

    题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果: 8 ...

最新文章

  1. 腾讯 AI 2019这一年
  2. 机器学习——大数据与MapReduce
  3. 写给计算机的大学生!
  4. 应用场景的多样,奠定了区块链的未来
  5. 徐阿衡 | 知识抽取-实体及关系抽取(一)
  6. 中国建筑行业2020年度回顾及未来展望
  7. 畅享9能更新鸿蒙吗,Mate 9也能升级!鸿蒙系统正式发布:老用户爽了
  8. 扩展 TextBox 控件 - 依 FormViewMode 来自行设定状态
  9. ora-01031:insufficient privileges解决方法总结
  10. xtile 下载_Stata: gen 命令中的 group() 函数的潜在风险
  11. cdrx8如何批量导出jpg_Coreldraw 8插件下载|Coreldraw x8高版本文件(保存为coreldraw 8.0版)最新插件_ - 极光下载站...
  12. Python-Leetcode-剑指offer(五月上做题整理)
  13. 信息流广告如何操作?(含CPC、OCPC、CPM、eCPM、CTR等)
  14. CTS、CTS Verify、GTS测试以及GMS认证
  15. Kaggle:Home Credit Default Risk 特征工程构建及可视化(2)
  16. JavaSE基础笔记(全)
  17. panda强化练习2
  18. 松柏先生:血亏500万、倾家荡产的天猫女老板犯了这9个大忌!
  19. 看了就懂了,LCD拼接屏、LED显示屏、OLED显示屏三者的区别!
  20. thinkphp表单验证

热门文章

  1. 2021年春季学期-信号与系统-第六次作业参考答案-第六小题
  2. 聊聊那些令人惋惜的车模
  3. C语言数据段分类,13.2.1 段的分类
  4. hsf 架构_HSF 服务
  5. oracle 2日dba 11g,Oracle 11gR2 注意revoke dba 会一并回收通过”quota“分配的表空间限额...
  6. 20秋PHP作业3,北语20秋《PHP》作业3【标准答案】
  7. 如何阅读微控制器数据手册:探索硬件 ?
  8. 【 FPGA 】时钟域问题简介
  9. Android自定义组合控件
  10. python面向对象编程 Object-Oriented