二叉树相关代码(从数组生成二叉树、中序线索化、层序遍历)

16 篇文章 0 订阅

最近,我把二叉树树的几个相关代码敲了一遍,均运行成功,在此上传博客,与大家分享。

代码主要包含:
 - 从键盘生成二叉树
 - 从数组(vector)生成二叉树
 - 二叉树的中序遍历
 - 二叉树的中序线索化
 - 线索二叉树的中序遍历
 - 二叉树的层序遍历

树图:
这里写图片描述
附上代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

typedef char TElemType;
typedef enum{ Link, Thread } PointerTag;
typedef struct BiTNode
{
    TElemType data;
    struct BiTNode* lChild;
    struct BiTNode* rChild;
    PointerTag lTag;
    PointerTag rTag;

}BiTNode, *BiTree;

unsigned int  TElemIndex = 0;   //用于从数组创建树
BiTree pre = NULL;  //用于二叉树线索化,始终指向刚刚访问过的结点


/*从stdin创建树*/
void createBiTree(BiTree *T)
{
    printf("please input NodeData: ");
    TElemType temp;
    scanf("%c", &temp);
    getchar();  //scanf() 会把回车符残留在缓冲区stdin,使用此句取出回车符(即舍弃)
    //gets(&temp);  //法2
    //std::cin>>temp;   //法3

    if (temp == '#')
    {
        *T = NULL;
    }
    else
    {
        *T = (BiTNode *)malloc(sizeof(BiTNode));
        if (!(*T))
        {
            perror("fail: create-malloc");
            return;
        }
        (*T)->data = temp;
        (*T)->lChild = NULL;
        (*T)->rChild = NULL;
        (*T)->lTag = Link;
        (*T)->rTag = Link;
        createBiTree(&(*T)->lChild);
        createBiTree(&(*T)->rChild);
    }
}

/*从数组创建树*/
void createBiTreeByArray(BiTree *T, vector<TElemType> list)
{
    if (TElemIndex + 1 <= list.size())
    {
        TElemType temp = list[TElemIndex];
        if (temp == '#')
        {
            *T = NULL;
            TElemIndex++;       /*index必须使用全局变量++,
                                 *而不能作为函数参数++(函数局部变量index在内层递归index++不会改变外层的index,退出内层递归时index会变回去)*/
        }
        else
        {
            *T = (BiTNode *)malloc(sizeof(BiTNode));
            if (!(*T))
            {
                perror("fail: create-malloc");
                return;
            }
            (*T)->data = temp;
            (*T)->lChild = NULL;
            (*T)->rChild = NULL;
            (*T)->lTag = Link;
            (*T)->rTag = Link;
            TElemIndex++;
            createBiTreeByArray(&(*T)->lChild, list);
            createBiTreeByArray(&(*T)->rChild, list);
        }
    }
}

/*中序遍历普通二叉树*/
void inOrderTraverse(BiTree T)
{
    if (T == NULL)
        return;
    inOrderTraverse(T->lChild);
    printf("%c ", T->data);
    inOrderTraverse(T->rChild);
}

/*中序线索化*/
void inThreading(BiTree T)
{
    if (T)
    {
        inThreading(T->lChild);
        //cout << T->data;
        if (!T->lChild)
        {
            T->lTag = Thread;
            T->lChild = pre;
        }
        if (!pre->rChild)
        {
            pre->rTag = Thread;
            pre->rChild = T;
        }
        pre = T;
        inThreading(T->rChild);
    }
}

/*建立头指针,使其左指针指向根结点,右指针指向遍历的最后一个结点,
   Thr表示头结点,T是根结点*/
void inThrBiTree(BiTree *Head, BiTree T)
{
    *Head = (BiTree)malloc(sizeof(BiTNode));
    (*Head)->lTag = Link;
    (*Head)->rTag = Thread;
    (*Head)->rChild = *Head;        //避免线索化时头结点的后继指向中序遍历的第一个结点

    if (!T)
        (*Head)->lChild = *Head;
    else
    {
        (*Head)->lChild = T;    //使头结点的左孩子指向根结点
        pre = *Head;    //使中序遍历的第一个结点的前驱指向头结点
        inThreading(T);
        pre->rTag = Thread;
        pre->rChild = *Head;        //使中序遍历的最后一个结点的后驱指向头结点
        (*Head)->rChild = pre;  //使头结点的后继指向中序遍历的最后一个结点
    }
}

/*中序遍历线索二叉树*/
bool inOrderTraverse_Thr(BiTree Head)
{
    BiTree T;
    T = Head->lChild;
    while (T != Head)
    {
        while (T->lTag == Link)
        {
            T = T->lChild;
        }
        cout << T->data;
        while (T->rTag == Thread && T->rChild != Head)
        {
            T = T->rChild;
            cout << T->data;
        }
        T = T->rChild;
    }
    return true;
}

/*二叉树层序遍历*/
void levelTraverse(BiTree T)
{
    queue<BiTree> q;        //定义一个队列,数据类型是二叉树结点指针,不要仅是TElemType!不然无法遍历
    if (T)
    {
        q.push(T);
    }
    while (!q.empty())
    {
        BiTree front = q.front();       //取队列最前面的结点
        cout << front->data;
        q.pop();        //删除最前面的结点

        if (front->lTag == Link && front->lChild)       //判断最前面的左结点是否为空,不是则放入队列
        {
            q.push(front->lChild);
        }
        if (front->rTag == Link && front->rChild)   //判断最前面的右结点是否为空,不是则放入队列
        {
            q.push(front->rChild);
        }
    }
}

int main()
{
    vector<TElemType> TElemList = { 'A', 'B', 'D', 'H', '#', 'K', '#', '#', '#', 'E', '#', '#', 'C', 'F', 'I', '#', '#', '#', 'G', '#', 'J', '#', '#' };
    BiTree root = NULL, head = NULL;

    //createBiTree(&root);
    createBiTreeByArray(&root, TElemList);
    cout << "create ok." << endl;

    inThrBiTree(&head, root);
    cout << "inThreading ok." << endl;

    cout << "中序遍历:";
    //inOrderTraverse(root);
    inOrderTraverse_Thr(head);
    cout << endl;

    cout << "层序遍历:";
    levelTraverse(root);
    cout << endl;

    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值