二叉树的建立、插入、删除、遍历(前中后的递归及非递归遍历和层次遍历)、求树高及叶子结点等

主要难点为树的建立和,非递归遍历,尤其是后序的非递归遍历。

1.非递归遍历的主要思路:从根结点开始,沿左子树深入下去,当深入到最左端时,无法深入下去,则返回刚才深入的时遇到的结点,并遍历该结点的右子树,进行如此的深入和返回,直到最后根结点的右子树返回到跟结点为止。

2.这一过程中,返回结点的顺序和进入结点的顺序相反,即先进入后返回,正好符合堆栈因此采用堆栈这一数据结构。

在沿左子树进行深入时,进入一个结点就将其压入堆栈:

如果是先序遍历,则在入栈之前就将其访问(输出),然后当左分支深入不下去的时候则返回,并将栈中的元素输出。

如果是中序遍历,则在弹出之后,访问该结点,然后从该结点的右子树继续深入

如果是后序遍历,则将该结点二次入栈,然后从该结点的右子树继续深入,与前面相同,即进入一个结点入栈一个结点,深入不下去就返回,直到第二次从栈里弹出该结点,才访问。

完整代码如下:

/************************************************************************
*
* 文件名:3.2.1.cpp
*
* 文件描述:二叉树的建立、插入、删除、遍历(前中后的递归及非递归遍历和层次遍历)、求树高及叶子结点等
*
* 创建人:  fdk

* 时  间:  2018-08-06
*
* 版本号:1.0
*
* 修改记录:
*
************************************************************************/
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <time.h>
#include <queue>
using namespace std;

/*定义二叉树的结构*/
typedef struct Node
{
    int value; //存储结点的值为整形
    struct Node *left;  //左子树
    struct Node *right; //右子树
}*BTree,btree;

typedef struct Node1
{
    BTree bNode;
    bool isFirst;
} BTNode;

BTree bTree;

/*建立一颗树*/
void CreateTree(int x)
{
    BTree newNode;    //定义一个新的结点
    BTree currentNode; //定义一个当前结点用于比较value的值

    int flag = 0;      //判断当前是否插入新结点,当flag为1时插入结点

    /*给新结点赋值*/
    newNode = (BTree)malloc(sizeof(btree)); //分配空间
    newNode->value = x;
    newNode->left = NULL;
    newNode->right = NULL;

    /*如果当前树为空就将创建的新结点赋值当前树*/
    if (bTree == NULL)
    {
        bTree = newNode;
    }
    else
    {
        currentNode = bTree; //如果不为空就将树的根结点赋值给当前结点

        /*没有插入新结点则一直循环下去*/
        while (!flag)
        {
            /*当前结点的值大于要插入的值,且左子树为空则将新结点插入到当前结点的左子树中*/
            if (currentNode->value > x)
            {
                if (currentNode->left == NULL)
                {
                    currentNode->left = newNode;
                    flag = 1;   //新结点插入后将flag改为1
                }
                else
                {
                    currentNode = currentNode->left; //左子树不为空继续向下遍历
                }
            }
            else
            {
                /*右子树为空则将新结点插入*/
                if (currentNode->right == NULL)
                {
                    currentNode->right = newNode;
                    flag = 1;   //新结点插入后将flag改为1
                }
                else
                {
                    currentNode = currentNode->right;// 不为空则继续遍向下遍历
                }
            }
        }
    }
}

/*递归前序遍历*/
void PreorderTraversal(BTree bTree)
{
    if (bTree)
    {
     /*不为空先输出根结点上的值再递归调用左子树和右子树*/
        cout << bTree->value << " ";
        PreorderTraversal(bTree->left);
        PreorderTraversal(bTree->right);
    }
}

/*非递归前序遍历*/
void PreorderTraversals(BTree bTree)
{
    BTree b;
    stack <BTree> s;      //声明一个栈,栈内元素的类型为BTree
    b = bTree;            //从根结点开始

    /*当树不为空或者堆栈不为空,循环持续下去*/
    while (b || !s.empty())
    {
        /*一直向左并将沿途的结点压入堆栈*/
        while (b)
        {
            cout << b->value << " ";  //打印结点
            s.push(b);
            b = b->left;
        }
        b = s.top();
        s.pop();
        b = b->right;    //转向右子树
    }
}

/*递归中序遍历*/
void InorderTraversal(BTree bTree)
{
    if (bTree)
    {
        InorderTraversal(bTree->left);
        cout << bTree->value << " ";
        InorderTraversal(bTree->right);
    }
}

/*非递归中序遍历*/
void InorderTraversals(BTree bTree)
{
    BTree T;
    stack <BTree> s;
    T = bTree;         //从根结点出发
    while (T || !s.empty())
    {
        /*一直向左并将沿途结点压入堆栈*/
        while (T)
        {
            s.push(T);
            T = T->left;
        }
        T = s.top();
        cout << T->value << " "; //打印结点
        s.pop();          //弹出堆栈
        T = T->right;                //转向右子树
    }
}

/*递归后序遍历*/
void PostorderTraversal(BTree bTree)
{
    if (bTree)
    {
        PostorderTraversal(bTree->left);
        PostorderTraversal(bTree->right);
        cout << bTree->value << " ";
    }
}

/*非递归后序遍历*/
void PostorderTraversals(BTree bTree)
{
    BTree T;
    stack <BTNode*> s;
    T = bTree;        //从根结点开始
    BTNode *temp;
    while (T || !s.empty())
    {
        /*一直向左并将沿途结点压入栈中*/
        while (T)
        {
            BTNode *btn = (BTNode *)malloc(sizeof(BTNode)); //分配空间
            btn->bNode = T;
            btn->isFirst = true;
            s.push(btn);
            T = T->left;
        }
        if (!s.empty())
        {
            /*弹出栈中的元素第一次弹出则重新压入栈中*/
            temp = s.top();
            s.pop();
            if (temp->isFirst)
            {
                temp->isFirst = false;
                s.push(temp);
                T = temp->bNode->right;
            }
            /*第二次弹出则直接输出*/
            else
            {
                cout << temp->bNode->value << " ";
                T = NULL;
            }
        }
    }
}

/*层次遍历*/
void LevelorderTraversal (BTree bTree)
{
    BTree T;
    queue <BTree> q;
    T = bTree;
    if (bTree == NULL)  /*若是空树则跳出程序*/
    {
        exit(-1);
    }

    q.push(T);
    while (!q.empty())
    {
        T = q.front();

        /*输出当前结点的值,并将左右子树添加到队列中*/
        cout << T->value << " ";
        if (T->left)
        {
            q.push(T->left);
        }
        if (T->right)
        {
            q.push(T->right);
        }
        q.pop();      //从队列中删除
    }
}

/*输出二叉树中的所有叶子结点*/
void PreorderPrintLeave(BTree bTree)
{
    if (bTree)
    {
        if (!bTree->left && !bTree->right) //如果bTree结点是叶子结点
        {
            cout << bTree->value << " ";
        }
        PreorderPrintLeave(bTree->left);
        PreorderPrintLeave(bTree->right);
    }
}

/*求二叉树的高度*/
int GetHight(BTree bTree)
{
    int hl;
    int hh;   //右子树高
    int maxh; //最大高度
    if (bTree)
    {
        hl = GetHight(bTree->left);    //返回左子树高
        hh = GetHight(bTree->right);   //返回右子树高
        maxh = hl > hh ? hl : hh;      //取左右子树中较大的高度
        return (maxh + 1);             //返回树的高度
    }
    else
    {
        return 0;    //空树高度为0
    }
}
int main()
{
    int n;
    cin >> n;
    srand(time(NULL));
    int u;
    cout << "随机生成的序列为:";
    for (int i = 0; i < n; i++)
    {
        u = (double)rand() / (RAND_MAX + 1) * (100 - 1) + 1;
        cout << u << " ";
        CreateTree(u);
    }
    cout << endl;

    cout << "递归前序遍历:";
    PreorderTraversal(bTree);
    cout << "非递归前序遍历:";
    PreorderTraversals(bTree);
    cout << endl;

    cout << "递归中序遍历:";
    InorderTraversal(bTree);
    cout << "非递归中序遍历:";
    InorderTraversals(bTree);
    cout << endl;

    cout << "递归后序遍历:";
    PostorderTraversal(bTree);
    cout << "非递归后序遍历:";
    PostorderTraversals(bTree);
    cout << endl;

    cout << "层次遍历:";
    LevelorderTraversal(bTree);
    cout << endl;

    cout << "树的叶子结点为:";
    PreorderPrintLeave(bTree);
    cout << endl;

    cout << "树的高度为:";
    cout << GetHight(bTree);
    return 0;
}










猜你喜欢

转载自blog.csdn.net/fdkNeverStopLearning/article/details/81488123