zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    js 99乘法表
    微信小程序 富文本插件 循环渲染方式
    Mysql: mysqlbinlog命令查看日志文件
    Java Mail 发送邮件(SSL加密方式,TSL加密方式)
    进程和线程的区别
    Java 制作证书(Windows 和Linux)
    Linux 常用命令标记
    Java clone克隆方法 --深拷贝--浅拷贝 --原型模型
    tomcat内存溢出:PermGen space解决方法
    Java 多线程 ---- 线程中this与 Thread.currentThread()线程的区别
  • 原文地址:https://www.cnblogs.com/quanxi/p/6079801.html
Copyright © 2011-2022 走看看