Tree

//Header.h

#ifndef _HEAD_
#define _HEAD_

#include <queue>
#include <iostream>
using namespace std;

typedef char TElemType;
typedef int Status;
#define OK 0
#define ERROR -2
#define OverFlow -1

//普通二叉树
typedef struct BiTNode
{
    TElemType data;
    struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;

//线索二叉树
typedef enum {Link, Thread} PointerTag;

typedef struct BiThrNode
{
    TElemType data;
    struct BiThrNode *lchild, *rchild;
    PointerTag LTag, RTag;
} BiThrNode, *BiThrTree;

//仅为普通二叉树
void CreateBiTree(BiTree &T);
void PreOrderTraverse(BiTree T);
void LevelTraverse(BiTree T);

//线索二叉树
void CreateBiThrTree(BiThrTree &T);
Status InOrderThread_Head(BiThrTree &head, BiThrTree &T);
Status InOrderTraverse_Thr(BiThrTree T);

#endif

//Functions.cpp

#include "Header.h"

//因为BiTree是一个结构体,所以这里必须用“引用&”,否则将会新建一个空的BiTree,导致在创建二叉树时,创建失败(我们指定的BiTree为空);
//进而导致后面的遍历直接退出(因为传进去的BiTree不管是否为“引用&”都为空);
//另外只要创建的树正确,那么在遍历的时候不论是否“引用&”都可以得到正确的遍历顺序

//创建二叉树:过程理解为先序
void CreateBiTree(BiTree &T)
{
    TElemType ch;
    cin >> ch;
    if (ch == '#')
        T = NULL;
    else
    {
        T = (BiTree)malloc(sizeof(BiTNode));
        if (T == NULL)
        {
            cout << "Create BinaryTree failed!";
            exit(OverFlow);
        }
        T->data = ch;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
}

//先序遍历
void PreOrderTraverse(BiTree T)
{
    if (T == NULL)
        return;
    cout << T->data;
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);
}

//深度优先遍历

//广度优先遍历

//层次遍历
void LevelTraverse(BiTree T)
{
    BiTree temp;
    queue<BiTree>q;
    q.push(T);
    do
    {
        temp = q.front();
        cout << temp->data;
        q.pop();
        if (temp->lchild != NULL)
        {
            q.push(temp->lchild);
        }
        if (temp->rchild != NULL)
        {
            q.push(temp->rchild);
        }
    } while (!q.empty());
}

//前面是二叉树,下面是线索二叉树
BiThrTree pre;

void CreateBiThrTree(BiThrTree &T)
{
    TElemType ch;
    cin >> ch;
    if (ch == '#')
        T = NULL;
    else
    {
        T = (BiThrTree)malloc(sizeof(BiThrNode));
        if (T == NULL)
        {
            cout << "Create BinaryTree failed!";
            exit(OverFlow);
        }
        T->data = ch;
        CreateBiThrTree(T->lchild);
        CreateBiThrTree(T->rchild);
    }
}

void SetPointerTag(BiThrTree &p)    //实际上只需要设置初始值就行
{
    if (p)
    {
        p->LTag = Link;
        p->RTag = Link;
        SetPointerTag(p->lchild);
        SetPointerTag(p->rchild);
    }
}
void InThreading(BiThrTree &p)    //p:present
{
    if (p)
    {
        InThreading(p->lchild);
        //两个if都是线索结点
        if (p->lchild == NULL)        //这里千万不要写错,要看清楚:这里是没有左孩子,而不是有左孩子
        {
            p->LTag = Thread;
            p->lchild = pre;
        }
        if (pre->rchild == NULL)    //前驱没有右孩子
        {
            pre->RTag = Thread;
            pre->rchild = p;
        }
        pre = p;
        InThreading(p->rchild);
    }
}

//建立头结点,中序线索二叉树本来的其余结点
Status InOrderThread_Head(BiThrTree &head, BiThrTree &T)
{
    if (head == NULL)
    {
        return ERROR;
    }

    head->rchild = head;
    head->RTag = Link;

    if (T == NULL)      //如果为NULL
    {
        head->lchild = head;
        head->LTag = Link;
    }
    else
    {
        pre = head;
        head->lchild = T;        //第一步
        head->LTag = Link;
        SetPointerTag(T);
        InThreading(T);         //找到最后一个结点
        pre->rchild = head;        //第四步
        pre->RTag = Thread;
        head->rchild = pre;      //第二步
    }
    return OK;
}

Status InOrderTraverse_Thr(BiThrTree T)
{
    BiThrTree p;
    p = T->lchild;
    while (p != T)
    {
        while (p->LTag == Link)
            p = p->lchild;
        cout << p->data;
        while (p->RTag == Thread && p->rchild != T)
        {
            p = p->rchild;
            cout << p->data;
        }
        p = p->rchild;
    }
    return OK;
}

//Main.cpp

#include "Header.h"

int main()
{
    int choice;
    cout << "1:普通二叉树" << endl << "2:线索二叉树" << endl;
    cin >> choice;
    switch (choice)
    {
    case 1:
        BiTree binaryTree;
        CreateBiTree(binaryTree);
        PreOrderTraverse(binaryTree);
        cout << endl;
        LevelTraverse(binaryTree);
        cout << endl;
        break;
    case 2:
        //必须用一个新的函数,新建一个树,因为数据结构已被改变——>然后建立头节点(就像链表),
        //并随即线索化——>像链表一样遍历(相对于普通树的遍历,减少了递归的堆栈导致的返回次数)
        BiThrTree threadBinaryTree;
        CreateBiThrTree(threadBinaryTree);
        BiThrTree head = (BiThrTree)malloc(sizeof(BiThrNode));
        InOrderThread_Head(head, threadBinaryTree);
        InOrderTraverse_Thr(head);
        cout << endl;
        break;
    }
    return 0;
}
posted @ 2016-11-19 07:25  不抛弃,不放弃  阅读(562)  评论(0编辑  收藏  举报