数据结构--二叉树

来源:互联网 发布:python 马科维兹模型 编辑:程序博客网 时间:2024/05/23 01:21

类定义:

/*
 *FileName: BinaryTree
 *Creator:  QianChenglong
 *Date:     2011/10/30
 *Comments: 因为BinaryTree把根节点指针作为数据成员,所以在后面的递归算法的实现上,都需要先处理下根节点,在设计辅助函数去实现递归处理;之所以这样是因为递归入口不一样,且需要初始化,在建立过程中就需要先给流输入数据,还要是根节点指针指向根节点,而在子部分中就不需要这些处理,所以应该分开来写;
 */

#ifndef BINARYTREE_H
#define BINARYTREE_H

#include<string>
#include<vector>


template<typename T>
class BinaryTree{
private:
    struct Node; /* 嵌套类定义,用来辅助实现*/
    Node* rootNode;//指向树的根节点;

    //辅助函数;
    Node* _find(Node* node,const T& value) const;//返回value的指针
    int _getHeight(Node* node) const;//求树的高度;
    int _getLeaves(Node* node) const;//返回叶子节点数

    void _preOrderOut(Node* node);//前序遍历二叉树;
    void _infixOrderOut(Node* node);
    void _postOrderOut(Node* node);

    Node* _creat(std::istringstream& in);//利用string对象创建二叉树;
    Node* _creat();

public:
        BinaryTree():rootNode(0){}//二叉树的初始化;
        ~BinaryTree(){destroy();}
        
    //建立
    Node* creat();//利用前序来创建二叉树,返回树的根节点;
    Node* creat(std::string& str);//利用前序序列的字符串创建二叉树,返回树的根节点;

    //销毁
    void destroy();//销毁二叉树;

    //遍历
    void preOrderOut();//前序递归遍历
    void infixOrderOut();//中序递归遍历
    void postOrderOut();//后序递归遍历
    void levelTraversing() const;//按层次遍历;
    void preOut();//前序非递归遍历
    void infixOut();//中序非递归遍历
    void postOut();//后序非递归遍历

    //访问操作
    bool getLeftNodeValue(Node* node,T& gotValue) const;//用gotValue返回node的左孩子的值,成功返回1,失败返回0;
    bool getRightNodeValue(Node* node,T& gotValue) const;//用gotValue返回node的右孩子的值,成功返回1,失败返回0;
    int getHeight() const;//返回树的高度;
    int getWidth() const;//返回树的宽度;
    int getNodeCount() const;//返回节点数;
    int getLeaves() const;//返回叶子节点数;
    Node* getRoot() const;//返回二叉树的根节点指针;
    Node* find(const T& value) const;//返回value的指针;

    //判断操作
    bool isEmpty() const;//判断是否为空树;
    bool isComplete() const;//判断是否是完全二叉树;
    bool isSemmetrical() const;//判断一棵树是否是对称的;

};
//定义树的节点;
template<typename T>
struct BinaryTree<T>::Node{
    T data;
    Node* leftNode;//指向该节点的左子树;
    Node* rightNode;//指向该节点的右子树;
    Node();/* 默认构造函数 */
    Node(T& _data);
};

#include "BinaryTree.cpp"

#endif

类实现:

/*=============================================================================
#     FileName: BinaryTree.cpp
#         Desc:   实现二叉树
#       Author: QianChenglong
#        Email: qian_cheng_long@163.com
#     HomePage: waiting...
#      Version: 0.0.1
#   LastChange: 2011-11-29 19:09:41
#      History:
=============================================================================*/
#ifndef BINARYTRR_CPP
#define BINARYTRR_CPP

#include "BinaryTree.h"
#include "SeqQueue.h"
#include<iostream>
#include<sstream>
#include "SeqStack.h"

///////////////////////////////////////////////////////////////////////
template<typename T>
BinaryTree<T>::Node::Node()
    :leftNode(0),rightNode(0)
{

}

/////////////////////////////////////////////////////////////////////////
template<typename T>
BinaryTree<T>::Node::Node(T& _data)
:data(_data),leftNode(0),rightNode(0)
{

}


///////////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::creat(){//采用前序遍历一个满二叉树建立,虚节点采用'*'标识,结束标记为'#';
    T nullNode;//用来吸收虚节点;
    if(std::cin.peek()=='*'){//当第一个就为虚节点标识时,则为空树;
        std::cin>>nullNode;
        rootNode=0;
        return rootNode;
    }
    T data_;//用来存储节点值;
    std::cin>>data_;
    rootNode=new Node(data_);
    rootNode->leftNode=_creat();
    rootNode->rightNode=_creat();
    return rootNode;
}
//////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::_creat(){//采用前序遍历一个满二叉树建立,虚节点采用'*'标识,结束标记为'#';
T data_;
//处理虚节点和结束符;
char nullNode;
if(std::cin.peek()=='*'){ //将下一字节作为int值返回,但不移除它;
    std::cin.get(nullNode);
    return 0;
}
std::cin>>data_;
Node* newNode=new Node(data_);
newNode->leftNode=_creat();
newNode->rightNode=_creat();
return newNode;
}

///////////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::_creat(std::istringstream& in){//采用前序遍历一个满二叉树建立,虚节点采用'*'标识
//处理虚节点和结束符;
char nullNode;
if(in.peek()=='*'){ //将下一字节作为int值返回,但不移除它;
    in.get(nullNode);
    return 0;
}
T data_;
in>>data_;
Node* newNode=new Node(data_);
newNode->leftNode=_creat(in);
newNode->rightNode=_creat(in);
return newNode;
}

////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::creat(std::string& str){
std::istringstream in(str);//用str初始化istringstream流;
if(in.peek()=='*'){ //若第一个节点就为虚节点,则为空树;
    rootNode=0;
    return rootNode;
}
T data_;
in>>data_;
rootNode=new Node(data_);
rootNode->leftNode=_creat(in);
rootNode->rightNode=_creat(in);
return rootNode;
}
template<typename T>//销毁树;
void BinaryTree<T>::destroy(){//层次遍历二叉树,挨个delete
if(rootNode==0)
    return;
SeqQueue<Node*> qu;
qu.push(rootNode);
Node* work=0;
if(!qu.isEmpty()){
    work=qu.pop();
    if(work->leftNode!=0)
        qu.push(work->leftNode);
    if(work->rightNode!=0)
        qu.push(work->rightNode);
    delete work;
    work=0;
}
}

/////////////////////////////////////////////////////////////////////////////////
template<typename T>//前序输出二叉树;
void BinaryTree<T>::_preOrderOut(Node* node){
if(node!=0){
    std::cout<<node->data<<' ';
    _preOrderOut(node->leftNode);
    _preOrderOut(node->rightNode);
}
}
////////////////////////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::preOrderOut(){
_preOrderOut(rootNode);
std::cout<<std::endl;
}
//////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::getRoot() const{//返回根节点的指针;
return rootNode;
}
////////////////////////////////////////////////////////////////////
template<typename T>
bool BinaryTree<T>::isEmpty() const{//判断是否为空树;
return rootNode==0;
}
//////////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::find(const T& value) const{
return _find(rootNode,value);
}
////////////////////////////////////////////////////////////////////////
template<typename T>
typename BinaryTree<T>::Node* BinaryTree<T>::_find(Node* node,const T& value) const{
if(node==0)
    return 0;
if(node->data==value)
    return node;
else{
    Node* p=0;
    p=_find(node->leftNode,value);
    if(p!=0) return p;
    p=_find(node->rightNode,value);
    return p;
}
}
//////////////////////////////////////////////////////////////////////
template<typename T>//用gotValue返回node的左孩子的值,成功返回1,失败返回0;
bool BinaryTree<T>::getLeftNodeValue(Node* node,T& gotValue) const{
if(node->leftNode==0)
    return 0;
gotValue=node->leftNode->data;
return 1;
}
/////////////////////////////////////////////////////////////////////
template<typename T>//用gotValue返回node的右孩子的值,成功返回1,失败返回0;
bool BinaryTree<T>::getRightNodeValue(Node* node,T& gotValue)const{
if(node->rightNode==0)
    return 0;
gotValue=node->rightNode->data;
return 1;
}
/////////////////////////////////////////////////////////////////////////
template<typename T>//返回树的高度;
int BinaryTree<T>::getHeight() const{
return _getHeight(rootNode);
}
//////////////////////////////////////////////////////////////////////////
template<typename T>//返回树的高度;
int BinaryTree<T>::_getHeight(Node* node) const{
if(node==0)
    return 0;
int leftHeight=_getHeight(node->leftNode);
int rightHeight=_getHeight(node->rightNode);
if(leftHeight>rightHeight)
    return leftHeight+1;
else
    return rightHeight+1;
}
////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::getNodeCount() const{
SeqQueue<Node*> qu;
qu.push(rootNode);
Node* work=0;
int count=0;
while(!qu.isEmpty()){
    work=qu.pop();
    ++count;
    if(work->leftNode!=0)
        qu.push(work->leftNode);
    if(work->rightNode!=0)
        qu.push(work->rightNode);
}
return count;
}
/////////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::getWidth() const{//返回树的宽度;
Node* work;
SeqStack<Node*> stack1,stack2;
stack1.push(rootNode);
int width=0;
while(!(stack1.isEmpty()&&stack2.isEmpty()))  /* 当两个栈 !都为空的时候*/
{
    while(!stack1.isEmpty()) /* 当stack1不为空时*/
    {
        work=stack1.pop(); /* 出栈一个元素*/
        if( work->leftNode ) /* 判断当前出栈元素的左孩子是否存在*/
        {
            stack2.push(work->leftNode); /* 若存在则把它压入stack2*/
        }
        if( work->rightNode ) /* 判断当前出栈元素的右孩子是否存在*/
        {
            stack2.push(work->rightNode); /* 若存在则把他压入stack2*/
        }
    } /* 这样所有stack1的孩子节点就进入了stack2*/
    if( width < stack2.length() ) /* 若当前宽度值小于某一层的节点数*/
    {
        width = stack2.length(); /* 则该层的节点数就为当前宽度*/
    }
    while(!stack2.isEmpty()) /* 当stack2不为空时*/
    {
        work=stack2.pop(); /* 出栈一个元素*/
        if( work->leftNode ) /* 判断当前出栈元素的左孩子是否存在*/
        {
            stack1.push(work->leftNode); /* 若存在则把它压入stack1*/
        }
        if( work->rightNode ) /* 判断当前出栈元素的右孩子是否存在*/
        {
            stack1.push(work->rightNode); /* 若存在则把他压入stack1*/
        }
    } /* 这样所有stack2的孩子节点就进入了stack1*/
    if( width < stack1.length() ) /* 若当前宽度值小于某一层的节点数*/
    {
        width = stack1.length(); /* 则该层的节点数就为当前宽度*/
    }
}
return width;  /* 返回宽度*/
}
//////////////////////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::getLeaves() const{//返回叶子节点数;
return _getLeaves(rootNode);
}
/////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
int BinaryTree<T>::_getLeaves(Node* node) const{
if(node==0)
    return 0;
if(node->leftNode==0&&node->rightNode==0)
    return 1;
return _getLeaves(node->leftNode)+_getLeaves(node->rightNode);
}
/////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::levelTraversing() const{//按层次遍历;
SeqQueue<Node*> qu;//定义一个存储节点指针的队列;
Node* work=0;//工作指针;
if(rootNode==0) return;//若为空树,则结束遍历
qu.push(rootNode);//根节点入队;
while(qu.isEmpty()==0){//队列是否为空;
    work=qu.pop();//出队;
    std::cout<<work->data<<' ';//访问出队节点的数据;
    if(work->leftNode!=0)//若出队节点的左孩子不为空;
        qu.push(work->leftNode);//左孩子入队;
    if(work->rightNode!=0)//若出队节点的右孩子不为空:
        qu.push(work->rightNode);//右孩子入队;
}
std::cout<<std::endl;
}
///////////////////////////////////////////////////////////////////////////
template<typename T>
bool BinaryTree<T>::isComplete() const{//采用层次遍历,判断每一个节点前面是否有空位,若有,则不是完全二叉树;
SeqQueue<Node*> qu;
if(rootNode==0) return 1;
qu.push(rootNode);
Node* work=0;
int flag=0;//标记位,0表示前面一个为数据,1表示前面上个空位;
while(qu.isEmpty()==0){
    work=qu.pop();//出队一个节点;
    if(work!=0){//若出队节点不为空;
        if(flag==1)//若标记位为1;
            return 0;//则说明不是完全二叉树;
        qu.push(work->leftNode);//出队节点的左右孩子入队,空节点也入队;
        qu.push(work->rightNode);
    }
    else//说明为空节点;
        flag=1;//标记位置为1;
}
return 1;
}
///////////////////////////////////////////////////////////////////////////
template<typename T>//中序遍历
void BinaryTree<T>::infixOrderOut(){
_infixOrderOut(rootNode);
std::cout<<std::endl;
}
/////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::_infixOrderOut(Node* node){
if(node!=0){
    _infixOrderOut(node->leftNode);
    std::cout<<node->data<<' ';
    _infixOrderOut(node->rightNode);
}
}
//////////////////////////////////////////////////////////
template<typename T>//后序遍历
void BinaryTree<T>::postOrderOut(){
_postOrderOut(rootNode);
std::cout<<std::endl;
}
///////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::_postOrderOut(Node* node){
if(node!=0){//若节点为空,则不访问,返回上一级,若节点不为空,则后序遍历该树
    _postOrderOut(node->leftNode);
    _postOrderOut(node->rightNode);
    std::cout<<node->data<<' ';
}
}
////////////////////////////////////////////////////////////
template<typename T>//前序非递归遍历
void BinaryTree<T>::preOut(){
SeqStack<Node*> sk;
if(rootNode==0)
    return;
sk.push(rootNode);
Node *work=0;
while(!sk.isEmpty()){
    work=sk.pop();
    std::cout<<work->data<<' ';//访问节点
    if(work->rightNode!=0)
        sk.push(work->rightNode);
    if(work->leftNode!=0)
        sk.push(work->leftNode);
}
std::cout<<std::endl;
}
//////////////////////////////////////////////
template<typename T>//中序非递归遍历
void BinaryTree<T>::infixOut(){
SeqStack<Node*> sk;
if(rootNode==0) return;
Node* work=rootNode;
while(work!=0||!sk.isEmpty()){
    while(work!=0){//将work的左子树,当左节点不为空,则进栈
        sk.push(work);//当处理的是根节点是,就是将所有的左子树依次进栈
        work=work->leftNode;
    }
    if(!sk.isEmpty()){
        work=sk.pop();
        std::cout<<work->data<<' ';//访问左节点后
        work=work->rightNode;//处理右子树
    }
}
std::cout<<std::endl;
}
///////////////////////////////////////////////////////////
template<typename T>//后序非递归遍历
void BinaryTree<T>::postOut(){
int flag;
SeqStack<Node*> sk;
Node* work=rootNode;
Node* pre;
    if(work!=0){
        do{
            while(work!=0){//将work所有的左节点依次进栈
                sk.push(work);
                work=work->leftNode;
            }
            pre=0;//pre指向栈顶节点的前一个已访问过的节点
            flag=1;//1表示*work的左孩子已访问或为空
            while(!sk.isEmpty()&&flag==1){
                work=sk.getTop();
                if(work->rightNode==pre){
                    std::cout<<work->data<<' ';
                    pre=work;
                    sk.pop();
                }else{
                    work=work->rightNode;
                    flag=0;//
                }
            }
        }while(!sk.isEmpty());
    }
    std::cout<<std::endl;
}
#endif

功能测试:

/*=============================================================================
#     FileName: main.cpp
#         Desc:  
#       Author: QianChenglong
#        Email: qian_cheng_long@163.com
#     HomePage: waiting...
#      Version: 0.0.1
#   LastChange: 2011-11-29 19:06:57
#      History:
=============================================================================*/

#include<iostream>
#include "BinaryTree.h"

int main(){
    BinaryTree<char> Tree;
    std::cout<<"请按前序输入二叉树:\n";
    std::string str("ABD*G***CE**F**");
    //std::string str("ABc*****");
    //std::string str("AB**C**");
    Tree.creat(str);
    std::cout<<"二叉树创建成功!\n";
    std::cout<<Tree.getWidth()<<std::endl;
    Tree.preOut();
    Tree.infixOut();
    Tree.postOut();
    /*
    Tree.preOrderOut();
    
    Tree.infixOrderOut();
    Tree.postOrderOut();
    /*
    Tree.levelTraversing();
    if(Tree.isComplete()==1)
    std::cout<<"是完全二叉树\n";
    else
        std::cout<<"不是完全二叉树\n";
    /*
    Tree.preOrderOut();
    std::cout<<std::endl;
    Node<char>* p=Tree.find('A');
    char gotValue;
    if(p!=0){
        Tree.getLeftNodeValue(p,gotValue);
        std::cout<<gotValue;
        Tree.getRightNodeValue(p,gotValue);
        std::cout<<gotValue;
    }
    
    std::cout<<Tree.getHeight()<<std::endl
        <<Tree.getNodeCount()
        <<Tree.getWidth()
        <<Tree.getLeaves();

    return 0;
    */
}



原创粉丝点击