首页 > 代码库 > 数据结构-二叉树 C和C++实现

数据结构-二叉树 C和C++实现

二叉树,指针域具有两个下一节点的特殊链表结构。

先来看看它的结构

(此处补图)

 

来看程序中需要使用到的概念:

树根:二叉树的第一个节点

子树:对于某一个节点指针域指向的节点,左指针指向的节点为左子节点,右指针指向的节点为右子节点

树高:树的层数

树宽:树在最多节点一层的节点数

叶子:不具有子树的节点

 

C语言版本

(此处补程序)

 

C++版本

包含三部分

(此处补图)

 

BiTreeNode.h:

技术分享
#ifndef _BITREENODE_H
#define _BITREENODE_H
#include<iostream>
using namespace std;


template <typename T>
class BiTreeNode
{
public:
    BiTreeNode(int index,T data);
    virtual ~BiTreeNode();
    //get data
    int getIndex();
    T getData();
    BiTreeNode *getParent();
    BiTreeNode *getLChild();
    BiTreeNode *getRChild();
    //set data
    void setIndex(int index);
    void setData(T data);
    void setParenet(BiTreeNode *Node);
    void setLChild(BiTreeNode *Node);
    void setRChild(BiTreeNode *Node);
    //else
    BiTreeNode *NodeSearch(int index);                    //通过索引搜索节点(以本节点作为根寻找树的某个节点)
    int NodeLeavesStatistics(int leaves = 0);            //统计叶子数
    int NodeChildrenNodeHeigh();                        //统计子节点的最大高度(包含本节点)/(以本节点作为根求树的高度)
    int NodeChildrenStatistics();                        //统计子节点数(包含本节点)
    int NodeDelete();                                    //删除节点
    //traversal
    void NodePreorderTraversal();
    void NodeInorderTraversal();
    void NodeSubsequentTraversal();
private:
    int m_iIndex;
    T m_tData;
    BiTreeNode *m_pParent;
    BiTreeNode *m_pLeftChild;
    BiTreeNode *m_pRightChild;

    //struct NodeWidth<T> stNodeWidth;
};

template <typename T>
BiTreeNode<T>::BiTreeNode(int index,T data)
{
    m_iIndex = index;
    m_tData = data;
    m_pParent = NULL;
    m_pLeftChild = NULL;
    m_pRightChild = NULL;
}

template <typename T>
BiTreeNode<T>::~BiTreeNode()
{
    if(m_pLeftChild != NULL)
    {
        m_pLeftChild->NodeDelete();
        m_pLeftChild = NULL;
    }
    if(m_pRightChild != NULL)
    {
        m_pRightChild->NodeDelete();
        m_pRightChild = NULL;
    }
    m_pParent = NULL;
}
/*-----------------------getdata------------------------*/
template <typename T>
int BiTreeNode<T>::getIndex()
{
    return m_iIndex;
}


template <typename T>
T BiTreeNode<T>::getData()
{
    return m_tData;
}

template <typename T>
BiTreeNode<T> *BiTreeNode<T>::getParent()
{
    return m_pParent;
}

template <typename T>
BiTreeNode<T> *BiTreeNode<T>::getLChild()
{
    return m_pLeftChild;
}

template <typename T>
BiTreeNode<T> *BiTreeNode<T>::getRChild()
{
    return m_pRightChild;
}

/*-----------------------setdata------------------------*/
template <typename T>
void setIndex(int index)
{
    m_iIndex = index;
}
template <typename T>
void setData(T data)
{
    m_tData = data;
}
template <typename T>
void BiTreeNode<T>::setParenet(BiTreeNode *Node)
{
    m_pParent = Node;
}

template <typename T>
void BiTreeNode<T>::setLChild(BiTreeNode *Node)
{
    m_pLeftChild = Node;
}

template <typename T>
void BiTreeNode<T>::setRChild(BiTreeNode *Node)
{
    m_pRightChild = Node;
}

/*-----------------------else------------------------*/
template <typename T>
BiTreeNode<T> *BiTreeNode<T>::NodeSearch(int index)
{
    BiTreeNode<T> *tempNode = NULL;
    if(m_iIndex == index)
    {
        return this;
    }
    if(m_pLeftChild != NULL)
    {
        tempNode = m_pLeftChild->NodeSearch(index);
        if(tempNode != NULL)//match
        {
            return tempNode;
        }
    }

    if(m_pRightChild !=NULL)
    {
        tempNode = m_pRightChild->NodeSearch(index);
        if(tempNode != NULL)// match
        {
            return tempNode;
        }
    }


    return NULL;
}

/*statistcal children node heigh(includding me)*/
template <typename T>
int BiTreeNode<T>::NodeChildrenNodeHeigh()
{
    int heightLeft =0 ;
    int heightRight =0; 
    if(m_pLeftChild != NULL)
    {
        heightLeft += m_pLeftChild->NodeChildrenNodeHeigh();    
    }
    if(m_pRightChild != NULL)
    {
        heightRight += m_pRightChild->NodeChildrenNodeHeigh();
    }
    if(heightRight > heightLeft)
    {
        return ++heightRight;
    }
    else
    {
        return ++heightLeft;
    }
}

/*statistcal leaves node(includding me)*/
template <typename T>
int BiTreeNode<T>::NodeLeavesStatistics(int leaves)
{
    if(this->m_pLeftChild != NULL)
    {
        leaves = this->m_pLeftChild->NodeLeavesStatistics(leaves);
    }
    if(this->m_pRightChild != NULL)
    {
        leaves = this->m_pRightChild->NodeLeavesStatistics(leaves);
    }
    if(this->getLChild() == NULL && this->getRChild() == NULL)
    {
        leaves ++;
    }
    return leaves;    
}
/*statistcal children node(includding me)*/
template <typename T>
int BiTreeNode<T>::NodeChildrenStatistics()
{
    int iCnt=0;
    if(this->m_pLeftChild != NULL)
    {
        iCnt+=this->m_pLeftChild->NodeChildrenStatistics();
    }
    if(this->m_pRightChild!= NULL)
    {
        iCnt+=this->m_pRightChild->NodeChildrenStatistics();
    }
    iCnt++;
    return iCnt;
}

template <typename T>
int  BiTreeNode<T>::NodeDelete()
{
    int Times=0;
    if(this->m_pLeftChild != NULL)
    {
         //delete this->getLChild();
        Times+=this->m_pLeftChild->NodeDelete();
        this->m_pLeftChild =NULL;
    }
    if(this->m_pRightChild!= NULL)
    {
        //delete this->getRChild();
        Times+=this->m_pRightChild->NodeDelete();
        this->m_pRightChild =NULL;
    }
    Times++;
    delete this;
    return Times;
}
/*-----------------------traversal------------------------*/
template <typename T>
void BiTreeNode<T>::NodePreorderTraversal()
{
    cout<<"Index:"<<this->getIndex()<<";Data:"<<this->getData()<<endl;

    if(this->getLChild() != NULL)
    {
        this->getLChild()->NodePreorderTraversal();
    }

    if(this->getRChild() != NULL)
    {
        this->getRChild()->NodePreorderTraversal();
    }
}

template <typename T>
void BiTreeNode<T>::NodeInorderTraversal()
{
    if(this->getLChild() != NULL)
    {
        this->getLChild()->NodePreorderTraversal();
    }

    cout<<"Index:"<<this->getIndex()<<";Data:"<<this->getData()<<endl;

    if(this->getRChild() != NULL)
    {
        this->getRChild()->NodePreorderTraversal();
    }
}

template <typename T>
void BiTreeNode<T>::NodeSubsequentTraversal()
{
    if(this->getLChild() != NULL)
    {
        this->getLChild()->NodePreorderTraversal();
    }

    if(this->getRChild() != NULL)
    {
        this->getRChild()->NodePreorderTraversal();
    }

    cout<<"Index:"<<this->getIndex()<<";Data:"<<this->getData()<<endl;
}

#endif
View Code

 

BinaryTree.h

技术分享
#ifndef _BINARYTREE_H
#define _BINARYTREE_H

#include <iostream>

#include "BiTreeNode.h"
using namespace std;

template <typename T>
class BinaryTree
{
public:
    BinaryTree(int size);
    virtual ~BinaryTree();                                            
    bool IsTreeFull();                                                //树的容量是否已满
    //search    
    BiTreeNode<T> getNodeByIndex(int index);                        //通过索引搜索节点
    int getLeaves();                                                //获取树的叶子数
    int getHeight();                                                //获取树的高度(包含根节点)
    int getWidth();                                                    //获取树的宽度(包含根节点)
    int getNowSize();                                                //获取树现在的节点数(包含根节点)
    int getMaxSize();                                                //获取树的最大节点数
    //add/delete
    bool addLeftNodeByIndex(int newIndex,T data,int searchIndex);    //添加左子树(使用索引)
    bool addRightNodeByIndex(int newIndex,T data,int searchIndex);  //添加右子树(使用索引)
    bool addLeftNodeByNode(int index,T data,BiTreeNode<T> *pNode);  //添加左子树(使用节点地址)
    bool addRightNodeByNode(int index,T data,BiTreeNode<T> *pNode); //添加右子树(使用节点地址)
    bool deleteNodeByIndex(int index);                                //删除节点(使用索引)
    bool deleteNodeByNode(BiTreeNode<T> *pNode);                    //删除节点(使用地址)

    //traversal
    void PreorderTraversal();                                        //先序遍历
    void InorderTraversal();                                        //中序遍历
    void SubsequentTraversal();                                        //后序遍历

private:
    BiTreeNode<T> *m_pRoot;                                            //tree root
    int m_iSize;                                                    //Tree now nodes size (without root)
    int m_iMaxSize;                                                    //Tree max nodes size (without root) 
};


template <typename T>
BinaryTree<T>::BinaryTree(int size)
{
    m_pRoot = new BiTreeNode<T>(1,0);
    m_pRoot->setLChild(NULL);
    m_pRoot->setRChild(NULL);
    m_pRoot->setParenet(NULL);
    m_iSize = 0;
    m_iMaxSize = size;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
    delete m_pRoot;
    m_pRoot=NULL;
}
template <typename T>
bool BinaryTree<T>::IsTreeFull()
{
    if(m_iSize >= m_iMaxSize)
        return true;
    return false;
}
//search
template <typename T>
BiTreeNode<T> BinaryTree<T>::getNodeByIndex(int index)
{
    return m_pRoot->NodeSearch(index);
}
template <typename T>
int BinaryTree<T>::getLeaves()
{    
    return m_pRoot->NodeLeavesStatistics();
}

template <typename T>
int BinaryTree<T>::getWidth()
{
    int maxWidth=1;                //save max width
    int parentWidth=0;            //save this width
    int childrenWidth=0;        //save next width
    queue<BiTreeNode<T>*> stdQueue;
    BiTreeNode<T> *tempNode = m_pRoot;
    if(tempNode -> getLChild() != NULL)
    {
        stdQueue.push(tempNode -> getLChild());
        parentWidth ++;
    }
    if(tempNode -> getRChild() != NULL)
    {
        stdQueue.push(tempNode ->getRChild());
        parentWidth ++;
    }

    while(!stdQueue.empty())
    {
        while(parentWidth>0)
        {
            tempNode = stdQueue.front();
            stdQueue.pop();
            if(tempNode -> getLChild() != NULL)
            {
                stdQueue.push(tempNode -> getLChild());
                childrenWidth ++;
            }
            if(tempNode -> getRChild() != NULL)
            {
                stdQueue.push(tempNode ->getRChild());
                childrenWidth ++;
            }
            parentWidth --;
        }
        parentWidth = childrenWidth;
        if(parentWidth > maxWidth)
        {
            maxWidth = parentWidth;
        }
        childrenWidth =0;
    }

//    result =  m_pRoot->NodeChildrenNodeWidth(&child);
    return maxWidth;
}


template <typename T>
int BinaryTree<T>::getHeight()
{
    return m_pRoot->NodeChildrenNodeHeigh();//include root 
}

template <typename T>
int BinaryTree<T>::getNowSize()
{
    //return m_iSize;//quickly get Size
    return m_pRoot ->NodeChildrenStatistics();//except root
}

template <typename T>
int BinaryTree<T>::getMaxSize()
{
    return m_iMaxSize ;
}

//add/delete
template <typename T>
bool BinaryTree<T>::addLeftNodeByIndex(int newIndex,T data,int searchIndex)
{
    BiTreeNode<T> *tempNode;
    tempNode = m_pRoot->NodeSearch(searchIndex);//find the Node witch is index = searchIndex
    if(tempNode!=NULL)
    {
        return addLeftNodeByNode(newIndex,data,tempNode);
    }
    return false;
}
template <typename T>
bool BinaryTree<T>::addRightNodeByIndex(int newIndex,T data,int searchIndex)
{
    BiTreeNode<T> *tempNode ;
    tempNode = m_pRoot->NodeSearch(searchIndex);
    if(tempNode!=NULL)
    {
        return addRightNodeByNode(newIndex,data,tempNode);
    }
    return false;
}
template <typename T>
bool BinaryTree<T>::addLeftNodeByNode(int index,T data,BiTreeNode<T> *pNode)
{
    BiTreeNode<T> *pNodeCopy = pNode;//make a copy of pNode to protect the pNode being changed by accidentally
    if(IsTreeFull())
    {
        return false ;
    }
    if(pNodeCopy -> getLChild() == NULL)
    {
        BiTreeNode<T> *newNode = new BiTreeNode<T>(index,data);
        pNodeCopy->setLChild(newNode);
        newNode->setParenet(pNodeCopy);
    }
    else 
    {
        return false ;
    }

    m_iSize++;
    return true;
}

template <typename T>
bool BinaryTree<T>::addRightNodeByNode(int index,T data,BiTreeNode<T> *pNode)
{
    BiTreeNode<T> *pNodeCopy = pNode;//make a copy of pNode to protect the pNode being changed by accidentally
    if(IsTreeFull())
    {
        return false ;
    }
    if(pNodeCopy -> getRChild() == NULL)
    {
        BiTreeNode<T> *newNode = new BiTreeNode<T>(index,data);
        pNodeCopy->setRChild(newNode);
        newNode->setParenet(pNodeCopy);
    }
    else 
    {
        return false ;
    }

    m_iSize++;
    return true;
}

template <typename T>
bool BinaryTree<T>::deleteNodeByIndex(int index)
{
    BiTreeNode<T> *deleteNode = m_pRoot->NodeSearch(index);
    if(deleteNode != NULL)
    {
        if(deleteNode == m_pRoot)
        {
            cout<<"BinaryTree<T>::deleteNodeByIndex():"<<index<<"是根节点不能删除"<<endl;
            return false;
        }
        return deleteNodeByNode(deleteNode);
    }
    return false;
}
template <typename T>
bool BinaryTree<T>::deleteNodeByNode(BiTreeNode<T> *pNode)
{
    if(pNode!=NULL)
    {
        /*clear parent Node L/RChild*/ 
        BiTreeNode<T> *parentNode = pNode->getParent();
        if(parentNode != NULL)
        {
            if(parentNode->getLChild() == pNode)
            {
                parentNode->setLChild(NULL);
            }
            else
            {
                parentNode->setRChild(NULL);
            }
        }
        /*delete node*/
        int SizeDec;//use to caculate how much Node was delete
        SizeDec = pNode->NodeDelete();
        m_iSize-=SizeDec;
        return true;
    }
    return false;
}

//traversal
template <typename T>
void BinaryTree<T>::PreorderTraversal()
{
    cout<<"PerorderTraversal:"<<endl;
    m_pRoot ->NodePreorderTraversal();
}
template <typename T>
void BinaryTree<T>::InorderTraversal()
{
    cout<<"InorderTraversal:"<<endl;
    m_pRoot ->NodeInorderTraversal();
}
template <typename T>
void BinaryTree<T>::SubsequentTraversal()
{
    cout<<"SubsequentTraversal:"<<endl;
    m_pRoot ->NodeSubsequentTraversal();
}

#endif 
View Code

 

main.c(本部分用于测试)

技术分享
#include <iostream>
#include "BinaryTree.h"

using namespace std;


int main()
{
    //float Ldatas[11] = {0.0f,1.1f,2.2f,3.3f,4.4f,5.5f,6.6f,7.7f,8.8f,9.9f,10.1f};
    //float Rdatas[5] = {30.0f,31.1f,32.2f,33.3f,34.4f};
    int Ldatas[11] = {0,1,2,3,4,5,6,7,8,9,10};
    int Rdatas[5] = {30,31,32,33,34};
    BinaryTree<int> *tree = new BinaryTree<int>(20);

    //addLeftNodeByIndex()/addRightNodeByIndex check
    for(int i=1;i<5;i++)
    {
        tree->addLeftNodeByIndex(i+1,Ldatas[i],i);
    }
    for(int i=1;i<5;i++)
    {
        tree->addRightNodeByIndex(i+5,Rdatas[i],i);
    }
    for(int i=1;i<5;i++)
    {
        tree->addLeftNodeByIndex(i+9,Rdatas[i],i+5);
    }
    tree->PreorderTraversal();
    cout<<"tree size(except root):"<<tree->getNowSize()<<endl;

    //getLeaves() check;
    cout<<"tree leaves:"<<tree->getLeaves()<<endl;

    //getHeight() check;
    cout<<"getHeight():"<<tree->getHeight()<<endl;

    //getWidth() check;
    cout<<"getWidth():"<<tree->getWidth()<<endl;

    //preorderTraversal()/InorderTraversal()/SubsequentTraversal() check
//    tree->PreorderTraversal();
//    tree->InorderTraversal();
//    tree->SubsequentTraversal();

    //deleteNodeByIndex() check
    tree->deleteNodeByIndex(2);
    tree->PreorderTraversal();

    //getNowSize() check
    cout<<"tree size(except root):"<<tree->getNowSize()<<endl;
    delete tree;
    tree = NULL;
    system("pause");
    return 0;
}
View Code

 

测试结果:

 

数据结构-二叉树 C和C++实现