C++ Exercises(十六)--二叉树的简单实现

简介:
#include "stdafx.h"
#include <iostream>
#include <stack>
#include "BinSTree.h"
#include <queue>
using namespace std;

class CTreeNode
{//树节点类
public:
    CTreeNode(const int& item,CTreeNode* lptr = NULL,CTreeNode* rptr = NULL):data(item),left(lptr),right(rptr)
    {
    }
    CTreeNode* Left(void)
    {
        return left;
    }
    CTreeNode* Right(void)
    {
        return right;
    }
    friend class CBinSTree;
public:
    int data;
private:
    CTreeNode* left;
    CTreeNode* right;

};

typedef enum{LEFT,RIGHT} TagType;//伪节点类型
struct ProTreeNode
{//用于后序遍历的伪节点
    CTreeNode* node;
    TagType type;
};
CTreeNode* GetTreeNode(const int& item,CTreeNode* lptr=NULL,CTreeNode* rptr=NULL)
{
    CTreeNode* p;
    p = new CTreeNode(item,lptr,rptr);
    if(p==NULL)
    {
        cerr<<"分配内存失败!"<<endl;
        exit(1);
    }
    return p;
}

void FreeTreeNode(CTreeNode* p)
{
    delete p;
    p = NULL;
}

void InOrder(CTreeNode* t)
{//中序遍历
    stack<CTreeNode*> s;
    CTreeNode* p=t;
    while (p!=NULL || !s.empty())
    {
        while (p!=NULL)             //遍历左子树
        {
            s.push(p);
            p=p->Left();
        }//endwhile
        
        if (!s.empty())
        {
            p=s.top();
            s.pop();
            cout<<p->data<<endl;        //访问根结点
            p=p->Right();            //通过下一次循环实现右子树遍历
        }//endif   
   
    }//endwhile
}

void PreOrder(CTreeNode* t)
{//前序遍历
    stack<CTreeNode*> s;
    CTreeNode* p=t;
    while (p!=NULL || !s.empty())
    {
        while (p!=NULL)             //遍历左子树
        {
            cout<<p->data<<endl;
            s.push(p);
            p=p->Left();
        }//endwhile
        
        if (!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->Right();            //通过下一次循环实现右子树遍历
        }//endif   
   
    }//endwhile
}

void PostOrder(CTreeNode* t)
{//后序遍历
    stack<ProTreeNode> s;
    CTreeNode* p=t;
    ProTreeNode x;
    do
    {
        while (p!=NULL)        //遍历左子树
        {
            x.node = p;
            x.type = LEFT;         //标记为左子树
            s.push(x);
            p=p->Left();
        }
   
        while (!s.empty() && s.top().type==RIGHT)  
        {
            x = s.top();
            s.pop();
            p = x.node;
            cout<<p->data<<endl;   //type为RIGHT,表示右子树访问完毕,故访问根结点    
        }
        
        if (!s.empty())
        {
            s.top().type = RIGHT;     //遍历右子树
            p=s.top().node->Right();        
        }   
    }while (!s.empty());
}
CTreeNode* MakeSampleTree()
{
    CTreeNode *root,*node2,*node3,*node4,*node5;
    node4 = GetTreeNode(4);
    node2 = GetTreeNode(2,NULL,node4);
    node5 = GetTreeNode(5);
    node3 = GetTreeNode(3,node5);
    root = GetTreeNode(1,node2,node3);
    return root;
}

void DeleteTree(CTreeNode* t)
{
    if(t!=NULL)
    {
        DeleteTree(t->Left());
        DeleteTree(t->Right());
        FreeTreeNode(t);
    }
}

void ClearSampleTree(CTreeNode *t)
{
    DeleteTree(t);
    t = NULL;
}


void CountLeaf(CTreeNode* t,int& count)
{
    if(t!=NULL)
    {
        CountLeaf(t->Left(),count);
        CountLeaf(t->Right(),count);
        if(t->Left()==NULL&&t->Right()==NULL)
            count++;
    }
}

int Depth(CTreeNode* t)
{
    int depLeft,depRight,depRtv;
    if(t==NULL)
        depRtv = 0;
    else
    {
        depLeft = Depth(t->Left());
        depRight = Depth(t->Right());
        depRtv = max(depLeft,depRight)+1;
    }
    return depRtv;

}

void IndentBlanks(int num)
{
    for(int i=0;i<num;++i)
        cout<<" ";
}
const int INDENTBLANKS = 6;
void PrintTree(CTreeNode* t,int level)
{//逆时针旋转'打印树
    if(t!=NULL)
    {
        PrintTree(t->Right(),level+1);
        IndentBlanks(level*INDENTBLANKS);
        cout<<t->data<<endl;
        PrintTree(t->Left(),level+1);
    }
}

CTreeNode* CopyTree(CTreeNode* t)
{
    CTreeNode *newnode,*newlptr,*newrptr;
    if(t==NULL)
        return NULL;
    if(t->Left()!=NULL)
        newlptr = CopyTree(t->Left());
    else
        newlptr = NULL;
    if(t->Right()!=NULL)
        newrptr = CopyTree(t->Right());
    else
        newrptr = NULL;
    newnode = GetTreeNode(t->data,newlptr,newrptr);
    return newnode;
}

void LevelTravel(CTreeNode* t)
{
    queue<CTreeNode*> q1;
    CTreeNode *p;
    q1.push(t);
    while(!q1.empty())
    {
        p = q1.front();
        q1.pop();
        cout<<p->data<<endl;
        if(p->Left()!=NULL)
            q1.push(p->Left());
        if(p->Right()!=NULL)
            q1.push(p->Right());

    }
}
int main()
{
    CTreeNode *root = NULL;
    root = MakeSampleTree();
    CTreeNode *root1 = CopyTree(root);
    PostOrder(root);
    int leafCount=0;
    CountLeaf(root,leafCount);
    cout<<"叶子数: "<<leafCount<<" 深度:"<<Depth(root)<<endl;
    PrintTree(root,0);
    cout<<"拷贝后: "<<endl;
    PrintTree(root1,0);
    cout<<"层序遍历: "<<endl;
    LevelTravel(root);
    ClearSampleTree(root);
    system("pause");
    return 0;
}


复制代码



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/07/20/1247018.html,如需转载请自行联系原作者

目录
相关文章
二叉树进阶面试题(精华总结)【C++版本】
二叉树进阶面试题(精华总结)【C++版本】
107 1
|
存储 编译器 数据库
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
328 0
|
算法 C++ 开发者
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
263 0
|
8月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
178 12
|
8月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
160 10
|
8月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
249 3
|
存储 C++
【C++】二叉树进阶之二叉搜索树(下)
【C++】二叉树进阶之二叉搜索树(下)
79 4
|
Java 编译器 C++
【C++】二叉树进阶之二叉搜索树(上)
【C++】二叉树进阶之二叉搜索树(上)
71 3
|
算法 C++
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
88 2
|
存储 算法 数据管理
C++中利用随机策略优化二叉树操作效率的实现方法
C++中利用随机策略优化二叉树操作效率的实现方法
168 1