C/C++树结构

目录

1. 二叉树

1.0 C语言实现

1.1 C++类封装

2. 二叉排序树

3. 线索二叉树


普通二叉树、满二叉树和完全二叉树三者的形态。

C/C++树结构_第1张图片

 C/C++树结构_第2张图片

C/C++树结构_第3张图片

常用的一个公式n0 = n2 + 1,即度为0的叶子结点等于度为2的结点加1.

1. 二叉树

1.0 C语言实现

 1.0.1 #号法创建二叉树

 二叉树最基本的数据结构:

typedef struct BitNode
{
    char data;
    struct BitNode * lchild, *rchild;
}BitNode;

“#号法”含义:让树的每个结点都变成度为2的树,度不为2的树就用#号补齐。如此,先序遍历一遍就可唯一确定一颗二叉树。具体代码如下:

//#井号法创建二叉树
BitNode * createBitNode()
{
    BitNode * pTmp = NULL;
    char ch;
    scanf("%c", &ch);
    if (ch == '#')
    {
        pTmp = NULL;
        return pTmp;
    }
    else
    {
        pTmp = (BitNode *)malloc(sizeof(BitNode));
        pTmp->data = ch;
        pTmp->lchild = pTmp->rchild = NULL;
        pTmp->lchild = createBitNode();
        pTmp->rchild = createBitNode();
        return pTmp;
    }
}

例如要创建如下的二叉树

C/C++树结构_第4张图片

通过#号法补齐后的形态如下:

C/C++树结构_第5张图片

运行程序时在终端输入

DFE###B##

即可创建上述二叉树。

1.0.2 二叉树的先序、中序和后序遍历

//先序遍历
void preOrder(BitNode * T)
{
    if (T == NULL)
        return;
    printf("%c", T->data);
    if (T->lchild != NULL)
        preOrder(T->lchild);
    if (T->rchild != NULL)
        preOrder(T->rchild);
}

//中序遍历
void inOrder(BitNode * T)
{
    if (T == NULL)
        return;
    if (T->lchild != NULL)
        preOrder(T->lchild);
    printf("%c", T->data);
    if (T->rchild != NULL)
        preOrder(T->rchild);
}

//后序遍历
void lastOrder(BitNode * T)
{
    if (T == NULL)
        return;
    if (T->lchild != NULL)
        preOrder(T->lchild);
    if (T->rchild != NULL)
        preOrder(T->rchild);
    printf("%c", T->data);
}

1.0.3 计算二叉树的深度

//求二叉树深度
int bitreeDepth(BitNode * T)
{
    int depth = 0;
    int ldepth = 0, rdepth = 0;
    if (T != NULL)
    {
        ldepth = bitreeDepth(T->lchild);
        rdepth = bitreeDepth(T->rchild);
        depth = ldepth > rdepth ? ldepth : rdepth;
        return 1 + depth;
    }
    else
        return 0;

1.0.4 计算二叉树的叶子个数

//求二叉树叶子结点个数
int getLeafNum(BitNode * T)
{
    int left_leaves_count;
    int right_leaves_count;
    if (T == NULL)
        return 0;
    else if (T->lchild == NULL && T->rchild == NULL)
        return 1;
    else
    {
        left_leaves_count = getLeafNum(T->lchild);
        right_leaves_count = getLeafNum(T->rchild);
        return left_leaves_count + right_leaves_count;
    }

1.1 C++类封装

#pragma once
#include
using namespace std;

template
class BinaryTree
{
private:
    struct Node
    {
        T data;
        Node *  left, *right;
    };
    Node * _root;
    //#号法创建
    Node * _createBinaryTree()
    {
        T ch;
        Node * t = NULL;
        scanf("%c", &ch);
        if (ch == '#')
        {
            t = NULL;
            return t;
        }
        else
        {
            t = new Node;
            t->data = ch;
            t->left = t->right = NULL;
            t->left = _createBinaryTree();
            t->right = _createBinaryTree();
            return t;
        }
    }
    void _preOrder(Node * t) const;
    void _inOrder(Node * t) const;
    void _lastOrder(Node * t) const;

    void _Clear(Node * t);
    int _getHight(Node * t);
    int _getLeavesNum(Node * t);
    int _getSize(Node * t);
public:
    BinaryTree() : _root(NULL) {}
    ~BinaryTree() { _Clear(_root); }
    void createBinaryTree() { _root = _createBinaryTree(); }
    void preOrder() const { if (_root) _preOrder(_root); }
    void inOrder() const { if (_root) _inOrder(_root); }
    void lastOrder() const { if (_root) _lastOrder(_root); }

    void Clear() { if (_root) _Clear(_root);_root = NULL; }
    int getHight() { return _getHight(_root); }
    int getLeavesNum()  { if (_root) return _getLeavesNum(_root); }
    int getSize() { if (_root) return _getSize(_root); }

};

template
inline void BinaryTree::_preOrder(Node * t) const
{
    if (t)
    {
        cout << t->data << " ";
        _preOrder(t->left);
        _preOrder(t->right);
    }
}

template
inline void BinaryTree::_inOrder(Node * t) const
{
    if (t)
    {
        
        _preOrder(t->left);
        cout << t->data << " ";
        _preOrder(t->right);
    }
}

template
inline void BinaryTree::_lastOrder(Node * t) const
{
    if (t)
    {
        
        _preOrder(t->left);
        _preOrder(t->right);
        cout << t->data << " ";
    }
}

template
inline void BinaryTree::_Clear(Node * t)
{
    if (t->left) _Clear(t->left);
    if (t->right) _Clear(t->right);
    delete t;
}

template
inline int BinaryTree::_getHight(Node * t)
{
    if (t == NULL) return 0;
    else
    {
        int lh = _getHight(t->left);
        int rh = _getHight(t->right);
        return 1 + (lh > rh ? lh : rh);
    }
}

template
inline int BinaryTree::_getLeavesNum(Node * t)
{
    if (t == NULL) return 0;
    else
    {
        if (t->left == NULL && t->right == NULL)
            return 1;
        else
            return _getLeavesNum(t->left) + _getLeavesNum(t->right);
    }
}

template
inline int BinaryTree::_getSize(Node * t)
{
    if (t == NULL) return 0;
    else
    {
        return 1 + _getSize(t->left) + _getSize(t->right);
    }
}

测试主函数

int main()
{
    BinaryTree tree;
    cout << "#号法创建二叉树" << endl;
    tree.createBinaryTree();
    cout << "\n先序遍历" << endl;
    tree.preOrder();

    int ret = tree.getHight();
    cout << "\n求高度 : " << ret << endl;

    ret = tree.getSize();
    cout << "\n求结点总数 : " << ret << endl;

    ret = tree.getLeavesNum();
    cout << "\n求叶结点总数:" << ret << endl;


    cout << "\n清空" << endl;
    tree.Clear();
}

2. 二叉排序树

二叉排序树具有下列性质:

1)若它的左子树不为空,则左子树上的值均小于根结点上的值。

2)若它的右子树不为空,则右子树上的所有结点的值均大于根结点的值。

3)二叉排序树的左右子树也都是排序树。

给定一个关键字key,在二叉排序树T中查找该关键字的算法如下:

BiTree * SearchBST(BiTree * T,dataType key)

{

     if (T == NULL) return NULL;

    if (T->data == key) retrun T;

    if (key < T->data)

         return SearchBST(T->lchild,key);

    else

        return SearchBST(T->rchild,key);

}

3. 线索二叉树

若结点有左子树,则其left指向其左孩子,否则令left域指示其在某种遍历下的前驱;若结点有右子树,则其right指向其右孩子,否则令right域指示其在某种遍历下的后继。为了区分一个结点的指针域是指向其孩子还是指向其前驱或后继,需要增加两个标志域lTag和rTag,结点结构如下

struct BiNode

{

int data;

BiNode * lchild, * rchild;

int lTag, rTag;

}

其中lTag = false,表示left指向结点的左孩子,lTag= true,表示left指向结点的前驱。rTag用法含义相同。

线索:二叉链表中指向前驱和后继的指针,称为线索。

你可能感兴趣的:(C/C++)