二叉树操作(C语言)含注释

(一) 实现功能:

1:初始化 2:显示(Map.txt) 3:先序遍历(递归法) 4中序遍历(递归法) 5:后序遍历 (递归法) 6:统计叶子结点数目 7:二叉树深度 8:左右子树交换 9:生成二叉排序树 a:查找排序树中的结点 b:删除排序树中的结点 c:先序遍历(非递归法) d:层次遍历 e:凹入法表示二叉树 f:广义表表示二叉树

(二) 二叉树操作

1、创建。

2、用递归方法分别先序、中序、后序遍历以Tree为根指针的二叉树。

3、编写递归算法,计算二叉树中叶子结点的数目。

4、编写递归算法,计算二叉树的深度。

5、编写递归算法,将二叉树中所有结点的左、右子树相互交换。

6、使用数组elem中的随机数序列(以0表示结束,不包括0),生成以Tree为根指针的二叉排序树。

7、在以Tree为根指针的二叉排序树中查找结点。

8、从以Tree为根指针的二叉排序树中删除结点(适用各种位置的结点)。

9、用非递归算法,先序遍历以Tree为根指针的二叉树。

提示:用数组 BiTNode *stack[max] 构成堆栈,利用这个堆栈实现功能。

10、对以Tree为根指针的二叉树,从根结点开始,逐层从左到右输出各结点的数据。

提示:用数组 BiTNode *queue[max] 构成队列,利用这个队列实现功能

11、用凹入表示法的表示以Tree为根指针的二叉树,例如:

// 324

// 123

// 746

// 690

// 567

12、用广义表表示以Tree为根指针的二叉树,例如

//(324(123(746,690),567))

提高题:

13*、根据Huffman编码原理,使用数组elem中的随机数序列(以0表示结束,不包括0)作为结点的权重,生成赫夫曼树,以及赫夫曼编码,计算平均带权径长度。

14*、(1)随机生成二叉树。(2)生成并保存先(后)序、中序输出序列。(3)按照保存的一对输出序列恢复出二叉树。(4)生成先(后)序输出序列。

二叉树操作菜单如下:

Tips:

  1. 程序缺陷:赫夫曼树功能未实现

  1. 凹入表示法可以同叶子节点一起输出

  1. 功能2只能在32位电脑正常显示,64位可能会有偏差,可使用word查看

一些个人感想:

在写二叉树时,对树林转换成哈夫曼树时,返回树结点的地址时会刷新整棵树的地址,导致错误,思考后认为可以加一个父节点,解决地址混乱问题,但由于时间有限,未来得及实现。在编写删除二叉排序树的结点时,原想采用调用函数重新生成一颗排序树,但发现在某些条件下,左右子树会发生偏移,思考良久,决定按照书上思想,用寻找右子树的最小元素进行代替的策略,完成此函数功能。

程序所包含文件格式 (注意包含文件所在位置,以免报错!)

#include"BinT.h"//读取BinT.h文件

BinT.h文件完整如下:

//屏幕提示后,从键盘输入个数和随机数种子,在数组elem中生成指定个数的数据,供其他程序使用,0表示数据结束
void init0(int list[])
{
    int i, n;
    while (1)
    {
        cout << "输入数据个数(0-" << max - 1 << "):" << flush;
        cin >> n;
        if (n >= 0 && n <= max - 1)
            break;
        cout << endl;
    }
    while (1)
    {
        cout << "输入随机数种子(0-32767):" << flush;
        cin >> i;
        if (i >= 0 && i <= 32767)
            break;
        cout << endl;
    }
    srand(i); //指定随机数种子,相同的种子将产生相同的数据序列
    rand();

    for (i = 0; i < n; i++)
    {
        list[i] = rand() % 999 + 1;
    }
    list[n] = 0;
}

void getWidth(BiTNode *Tree, int depth, int shift, char map[max * 2][max * 2])
{
    int i;

    if (Tree->left != NULL)
    {
        getWidth(Tree->left, depth + 1, shift, map);
        Tree->tem1 = Tree->left->tem1 + Tree->left->tem2 + 1;
        for (i = (Tree->left->tem1 + shift) * 2; i < shift * 2; i = i + 2)
        {
            map[depth * 2 + 1][i] = '-';
            map[depth * 2 + 1][i + 1] = '-';
        }
    }
    else
        Tree->tem1 = 0;
    if (Tree->right != NULL)
    {
        getWidth(Tree->right, depth + 1, shift + Tree->tem1 + 1, map);
        Tree->tem2 = Tree->right->tem1 + Tree->right->tem2 + 1;
    }
    else
        Tree->tem2 = 0;

    for (i = shift * 2; i < (Tree->tem1 + shift) * 2; i++)
        map[depth * 2][i] = ' ';

    map[depth * 2][(Tree->tem1 + shift) * 2] = (char)(Tree->data / 1000 + 48);
    map[depth * 2][(Tree->tem1 + shift) * 2 + 1] = (char)(Tree->data / 100 % 10 + 48);
    map[depth * 2][(Tree->tem1 + shift) * 2 + 2] = (char)(Tree->data / 10 % 10 + 48);
    map[depth * 2][(Tree->tem1 + shift) * 2 + 3] = (char)(Tree->data % 10 + 48);
    if (Tree->data < 1000)
    {
        map[depth * 2][(Tree->tem1 + shift) * 2] = ' ';
        if (Tree->data < 100)
        {
            map[depth * 2][(Tree->tem1 + shift) * 2 + 1] = map[depth * 2][(Tree->tem1 + shift) * 2 + 2];
            map[depth * 2][(Tree->tem1 + shift) * 2 + 2] = map[depth * 2][(Tree->tem1 + shift) * 2 + 3];
            map[depth * 2][(Tree->tem1 + shift) * 2 + 3] = ' ';
            if (Tree->data < 10)
                map[depth * 2][(Tree->tem1 + shift) * 2 + 1] = ' ';
        }
    }

    if (Tree->left != NULL)
    {
        map[depth * 2 + 1][(Tree->left->tem1 + shift) * 2 + 1] = (char)0xa9;
        map[depth * 2 + 1][(Tree->left->tem1 + shift) * 2 + 2] = (char)0xb0;
        map[depth * 2 + 1][(Tree->tem1 + shift) * 2 + 1] = (char)0xa9;
        map[depth * 2 + 1][(Tree->tem1 + shift) * 2 + 2] = (char)0xbc;
        for (i = (Tree->left->tem1 + shift) * 2 + 3; i < (Tree->tem1 + shift) * 2; i = i + 2)
        {
            map[depth * 2 + 1][i] = (char)0xa9;
            map[depth * 2 + 1][i + 1] = (char)0xa4;
        }
    }
    if (Tree->right != NULL)
    {
        map[depth * 2 + 1][(Tree->tem1 + shift) * 2 + 1] = (char)0xa9;
        map[depth * 2 + 1][(Tree->tem1 + shift) * 2 + 2] = (char)0xb8;
        map[depth * 2 + 1][(Tree->tem1 + Tree->right->tem1 + shift) * 2 + 3] = (char)0xa9;
        map[depth * 2 + 1][(Tree->tem1 + Tree->right->tem1 + shift) * 2 + 4] = (char)0xb4;
        for (i = (Tree->tem1 + shift) * 2 + 3; i < (Tree->tem1 + Tree->right->tem1 + shift) * 2 + 2; i = i + 2)
        {
            map[depth * 2 + 1][i] = (char)0xa9;
            map[depth * 2 + 1][i + 1] = (char)0xa4;
        }
    }
    if (Tree->left != NULL && Tree->right != NULL)
    {
        map[depth * 2 + 1][(Tree->tem1 + shift) * 2 + 1] = (char)0xa9;
        map[depth * 2 + 1][(Tree->tem1 + shift) * 2 + 2] = (char)0xd8;
    }
}

//生成文件Map.txt,显示以Tree为根指针的二叉树
void showBinTree(BiTNode *Tree)
{
    char map[max * 2][max * 2];
    FILE *f;
    int i, j, k;

    f = fopen("Map.txt", "w");
    if (Tree == NULL)
    {
        fprintf(f, "空树");
        fclose(f);
        return;
    }
    for (i = 0; i < max * 2; i++)
        for (j = 0; j < max * 2; j++)
            map[i][j] = ' ';
    getWidth(Tree, 0, 0, map);
    for (i = 0; i < max * 2; i++)
    {
        k = max * 2 - 1;
        while (k >= 0 && map[i][k] == ' ')
            k--;

        for (j = 0; j <= k; j++)
            fprintf(f, "%c", map[i][j]);
        fprintf(f, "\n");
        //        if (k<0)
        //            break;
    }
    fclose(f);
}

//供init1O调用的释放函数
void release(BiTNode *Tree)
{
    if (Tree == NULL)
        return;
    release(Tree->left);
    release(Tree->right);
    free(Tree);
}

//供init1调用的生成函数
BiTNode *Generate(int n)
{
    int nl;
    if (n == 0)
        return NULL;

    BiTNode *P = new BiTNode;
    P->data = rand() % 999 + 1;
    nl = rand() % (n);
    P->left = Generate(nl);
    P->right = Generate(n - 1 - nl);
    return P;
}

//屏幕提示后,从键盘输入个数和随机数种子,以Tree为根指针,生成指定结点个数的二叉树,供其他程序使用,同时生成文件Map.txt,显示这课二叉树
BiTNode *init1()
{
    int i, n;

    while (1)
    {
        cout << "输入数据个数(0-" << max - 1 << "):" << flush;
        cin >> n;
        if (n >= 0 && n <= max - 1)
            break;
        cout << endl;
    }
    while (1)
    {
        cout << "输入随机数种子(0-32767):" << flush;
        cin >> i;
        if (i >= 0 && i <= 32767)
            break;
        cout << endl;
    }
    srand(i); //指定随机数种子,相同的种子将产生相同的数据序列
    rand();

    //    release(Tree);
    return Generate(n);
}

//公用的等待函数
void wait()
{
    cout << "\n\n请按任意键继续" << flush;
    getch();
}

//选择排序
void simpleSort(int list[])
{
    int i,j,k,temp;
    for(i=0;list[i]!=0;i++)
    {
        k=i;
        for(j=i+1;list[j]!=0;j++)
            if(list[j]<list[k])
                k=j;
        if(k!=i)
        {
            temp=list[i];
            list[i]=list[j];
            list[j]=temp;
        }
    }
}

//插入指定结点
BiTNode *insertChild(BiTNode *Tree,int child)
{
    if(Tree==NULL)
    {
        BiTNode *Tree=new BiTNode;
        Tree->data=child;
        Tree->left=NULL;
        Tree->right=NULL;
        return Tree;
    }
    else if(child>Tree->data)
        Tree->right=insertChild(Tree->right,child);
    else
        Tree->left=insertChild(Tree->left,child);
    return Tree;
}

//查找指定结点
BiTNode *search(BiTNode *Tree,int elem)
{
    if(Tree==NULL)
        return NULL;
    if(elem==Tree->data)
        return Tree;
    else if(elem>Tree->data)
            return search(Tree->right,elem);
        else 
            return search(Tree->left,elem);
}


//删除最小结点
BiTNode *FindMin(BiTNode *Tree)
{
    if(!Tree)
        return NULL;
    else if(!Tree->left)
        return Tree;
    else
        return FindMin(Tree->left);
}
//删除指定结点
BiTNode *Delete(BiTNode *Tree,int delElem)
{
    BiTNode *temp;
    if(!Tree)
        return NULL;
    else
    {
        if(delElem<Tree->data)
            Tree->left=Delete(Tree->left,delElem);
        else if(delElem>Tree->data)
            Tree->right=Delete(Tree->right,delElem);
        else
        {
            if(Tree->left&&Tree->right)
            {
                temp=FindMin(Tree->right);
                Tree->data=temp->data;
                Tree->right=Delete(Tree->right,Tree->data);
            }
            else
            {
                temp=Tree;
                if(!Tree->left)
                    Tree=Tree->right;
                else
                    Tree=Tree->left;
                free(temp);
            }
        }
    }
    return Tree;
}

BiTNode *minElem(BiTNode *Elem[],int length)
{
    BiTNode *min=new BiTNode;
    min=Elem[0];
    for(int i=0;i<length;i++)
    {
        if(Elem[i]->data<min->data)
            min=Elem[i];
    }
    return min;
}

void deleteMin(int length,int minElem)
{
    for(int i=0;i<length;i++)
    {
        if(minElem==Elem[i]->data)
        {
            for(int j=i;j<length-1;j++)
                elem[j]=elem[j+1];
            return;
        }
    }
}

//根据中序和后序数组中的n个结点建树
BiTNode *buildTree(int in[],int post[],int n)
{
    BiTNode *tree;
    int i;
    if(!n)
        return NULL;//空树
    tree=new BiTNode;
    tree->data=post[n-1];    //根结点是后序最后一个
    tree->left=tree->right=NULL;
    for(i=0;i<n;i++)        //在中序里找根结点
    {
        if(in[i]==post[n-1])
            break;
    }
    tree->left=buildTree(in,post,i);
    tree->right=buildTree(in+i+1,post+i,n-i-1);
    return tree;
}


//先序-文件
void PreOrderTraversePrintf(BiTNode *Tree,FILE *&f)
{
    if(Tree==NULL)
        return;
    fprintf(f, "%-5d ", Tree->data);
    PreOrderTraversePrintf(Tree->left,f);
    PreOrderTraversePrintf(Tree->right,f);
}
//中序-文件
void InOrderTraversePrintf(BiTNode *Tree,FILE *&f)
{
    if(Tree==NULL)
        return;
    InOrderTraversePrintf(Tree->left,f);
    fprintf(f,"%-5d ",Tree->data);
    InOrderTraversePrintf(Tree->right,f);
}
//后序-文件
void PostOrderTraversePrintf(BiTNode *Tree,FILE *&f)
{
    if(Tree==NULL)
        return;
    PostOrderTraversePrintf(Tree->left,f);
    PostOrderTraversePrintf(Tree->right,f);
    fprintf(f,"%-5d ",Tree->data);
}


void GetWidth(BiTNode *Tree, int depth, int shift, char map[max*2][max*2])
{
    int i;
 
    if (Tree->left != NULL)
    {
        GetWidth(Tree->left, depth+1, shift, map);
        Tree->tem1 = Tree->left->tem1 + Tree->left->tem2 + 1;
        for (i=(Tree->left->tem1+shift)*2; i<shift*2; i=i+2)
        {
            map[depth*2+1][i]='-';
            map[depth*2+1][i+1]='-';
        }
    }
    else Tree->tem1 = 0;
    if (Tree->right != NULL)
    {
        GetWidth(Tree->right, depth+1, shift+Tree->tem1+1, map);
        Tree->tem2 = Tree->right->tem1 + Tree->right->tem2 + 1;
    }
    else Tree->tem2 = 0;
 
    for (i=shift*2; i<(Tree->tem1+shift)*2; i++)
        map[depth*2][i]=' ';
    
    map[depth*2][(Tree->tem1+shift)*2]=(char)(Tree->data / 1000 +48);
    map[depth*2][(Tree->tem1+shift)*2+1]=(char)(Tree->data / 100 % 10 +48);
    map[depth*2][(Tree->tem1+shift)*2+2]=(char)(Tree->data / 10 % 10 +48);
    map[depth*2][(Tree->tem1+shift)*2+3]=(char)(Tree->data %10 +48);
    if (Tree->data<1000)
    {
        map[depth*2][(Tree->tem1+shift)*2]=' ';
        if (Tree->data<100)
        {
            map[depth*2][(Tree->tem1+shift)*2+1]=map[depth*2][(Tree->tem1+shift)*2+2];
            map[depth*2][(Tree->tem1+shift)*2+2]=map[depth*2][(Tree->tem1+shift)*2+3];
            map[depth*2][(Tree->tem1+shift)*2+3]=' ';
            if (Tree->data<10)
                map[depth*2][(Tree->tem1+shift)*2+1]=' ';
        }
    }
 
    if (Tree->left != NULL)
    {
        map[depth*2+1][(Tree->left->tem1+shift)*2+1]=(char)0xa9;
        map[depth*2+1][(Tree->left->tem1+shift)*2+2]=(char)0xb0;
        map[depth*2+1][(Tree->tem1+shift)*2+1]=(char)0xa9;
        map[depth*2+1][(Tree->tem1+shift)*2+2]=(char)0xbc;
        for (i=(Tree->left->tem1+shift)*2+3; i<(Tree->tem1+shift)*2; i=i+2)
        {
            map[depth*2+1][i]=(char)0xa9;
            map[depth*2+1][i+1]=(char)0xa4;
        }
    }
    if (Tree->right != NULL)
    {
        map[depth*2+1][(Tree->tem1+shift)*2+1]=(char)0xa9;
        map[depth*2+1][(Tree->tem1+shift)*2+2]=(char)0xb8;
        map[depth*2+1][(Tree->tem1+Tree->right->tem1+shift)*2+3]=(char)0xa9;
        map[depth*2+1][(Tree->tem1+Tree->right->tem1+shift)*2+4]=(char)0xb4;
        for (i=(Tree->tem1+shift)*2+3; i<(Tree->tem1+Tree->right->tem1+shift)*2+2; i=i+2)
        {
            map[depth*2+1][i]=(char)0xa9;
            map[depth*2+1][i+1]=(char)0xa4;
        }
    }
    if (Tree->left != NULL && Tree->right != NULL)
    {
        map[depth*2+1][(Tree->tem1+shift)*2+1]=(char)0xa9;
        map[depth*2+1][(Tree->tem1+shift)*2+2]=(char)0xd8;
    }
 
}

void ShowBinTree(BiTNode *Tree)
{
    char map[max * 2][max * 2];
    FILE *f;
    int i, j, k;

    //f = fopen("Map.txt", "w");
    if (Tree == NULL)
    {
        printf("空树");
        //fclose(f);
        return;
    }
    for (i = 0; i < max * 2; i++)
        for (j = 0; j < max * 2; j++)
            map[i][j] = ' ';
    GetWidth(Tree, 0, 0, map);
    for (i = 0; i < max * 2; i++)
    {
        k = max * 2 - 1;
        while (k >= 0 && map[i][k] == ' ')
            k--;

        for (j = 0; j <= k; j++)
            printf("%c", map[i][j]);
        printf("\n");
        //        if (k<0)
        //            break;
    }
    //fclose(f);
}

二叉树完整代码如下:

/*
    源文件名:P5.cpp
    功能:二叉树操作
*/
#include <iostream>
#include <iomanip>
#include <conio.h>
#include <stdio.h>
#include <process.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <Windows.h>
#include <math.h>
using namespace std;


struct BiTNode        //二叉树结点类型
{
    int data;         //数据
    int tem1,tem2;    //辅助数据(实习题不用)
    BiTNode *left;    //左子树指针
    BiTNode *right;   //右子树指针
};

BiTNode *Tree;      //本程序操作的二叉树根指针

#define  max 100
int elem[max];        //存放原始数据
int leafSum=0;//叶子节点数
BiTNode *Elem[max];
int length;//数组长度
int pre[max],in[max],post[max];//先、中、后遍历生成数组

#include"BinT.h"//读取BinT.h文件


//从键盘输入个数和随机数种子,在数组elem中生成指定个数的数据,供其他程序使用,0表示数据结束
void init0(int list[]);

//在本程序所在的位置生成文本文件Map.txt,其中显示以Tree为根指针的二叉树      
void showBinTree(BiTNode *Tree);

//从键盘输入个数和随机数种子,以Tree为根指针,生成指定结点个数的二叉树,供其他程序使用。同时生成文件Map.txt,显示这课二叉树
BiTNode *init1();   

//公用的等待函数
void wait();

//选择排序
void simpleSort(int list[]);

//插入指定结点
BiTNode *insertChild(BiTNode *Tree,int child);

//查找指定结点
BiTNode *search(BiTNode *Tree,int elem);

//删除指定结点
BiTNode *Delete(BiTNode *Tree,int delElem);

//删除最小结点
BiTNode *FindMin(BiTNode *Tree);
//展示函数
void ShowBinTree(BiTNode *Tree);

//先序-文件
void PreOrderTraversePrintf(BiTNode *Tree,FILE *&f);

//中序-文件
void InOrderTraversePrintf(BiTNode *Tree,FILE *&f);

//后序-文件
void PostOrderTraversePrintf(BiTNode *Tree,FILE *&f);

//根据中序和后序数组中的n个结点建树
BiTNode *buildTree(int in[],int post[],int n);



void PreOrderTraverse(BiTNode *Tree);//先序
void InOrderTraverse(BiTNode *Tree);//中序
void PostOrderTraverse(BiTNode *Tree);//后序
void leafCount(BiTNode *Tree);//叶子节点
int treeDeep(BiTNode *Tree);//深度
void changeTree(BiTNode *tree);//左右子树交换 
void createBinaryTree();//生成二叉排序树
void searchElem(BiTNode *Tree);//在以Tree为根指针的二叉排序树中查找结点
void deleteNode();//从以Tree为根指针的二叉排序树中删除结点(适用各种位置的结点)
void PreOrderTraverse2(BiTNode *Tree,int flag);//先序-非递归
void InOrderTraverse2(BiTNode *Tree,int flag);//中序-非递归
void PostOrderTraverse2(BiTNode *Tree,int flag);//后序-非递归
void levelOrderTraverse(BiTNode *Tree);//层次遍历
void showTreeByTab(BiTNode *Tree,int count);//用缩入格式的多行文本表示以Tree为根指针的二叉树
void showTreeBylist(BiTNode *Tree);//用广义表表示以Tree为根指针的二叉树
void Huffman();//哈夫曼树
void binaryTree();//生成随机二叉树,保存到文件,再恢复

//主函数,显示功能菜单(包括生成二叉树、显示二叉树),键盘选择后执行对应功能
int main()
{
    char choice;
    while (1)
    {
        system("cls");
        printf("\n\n\n\n");
        printf("\t\t             二叉树的操作            \n");
        printf("\t\t======================================");
        printf("\n\n");
        printf("\t\t             1:初始化              \n");
        printf("\t\t             2:显示(Map.txt)     \n");
        printf("\t\t             3:先序遍历(递归法)   \n");
        printf("\t\t             4:中序遍历(递归法)   \n");
        printf("\t\t             5:后序遍历(递归法)   \n");
        printf("\t\t             6:统计叶子节点数目     \n");
        printf("\t\t             7:二叉树深度           \n");
        printf("\t\t             8:左右子树交换         \n");
        printf("\n");
        printf("\t\t             9:生成二叉排序树      \n");
        printf("\t\t             a:查找排序树中的结点   \n");
        printf("\t\t             b:删除排序树中的结点   \n");
        printf("\n");
        printf("\t\t             c:先序遍历(非递归法)及中后非递归遍历 \n");
        printf("\t\t             d:层次遍历            \n");
        printf("\t\t             e:凹入法表示二叉树     \n");
        printf("\t\t             f:广义表表示二叉树     \n");
        printf("\t\t             g:程序内显示二叉树     \n");
        printf("\t\t             h:(未完成)使用数组elem中的随机数序列生成赫夫曼树,以及赫夫曼编码,计算平均带权径长度\n");
        printf("\t\t             i:生成随机二叉树,保存到文件,再恢复\n");
        printf("\n");
        printf("\t\t             0:退出                \n");
        printf("\n");
        printf("\n");
        printf("\t\t请选择:");
        choice = getch();
        system("cls");

        switch(choice)
        {
            case '1':
                Tree=init1();
                wait();
                break;
            case '2':
                showBinTree(Tree);
                printf("保存成功!\n");
                wait();
                break;
            case '3':
                printf("先序遍历结果:\n\t\t");
                PreOrderTraverse(Tree);
                wait();
                break;
            case '4':
                printf("中序遍历结果:\n\t\t");
                InOrderTraverse(Tree);
                wait();
                break;
            case '5':
                printf("后序遍历结果:\n\t\t");
                PostOrderTraverse(Tree);
                wait();
                break;
            case '6':
                leafCount(Tree);
                printf("叶子节点数目为:%d\n",leafSum);
                leafSum=0;
                wait();
                break;
            case '7':
                printf("二叉树的深度为:%d\n",treeDeep(Tree));
                wait();
                break;
            case '8':
                changeTree(Tree);
                printf("交换成功!\n");
                wait();
                break;
            case '9':
                createBinaryTree();
                wait();
                break;
            case 'a':
                searchElem(Tree);
                wait();
                break;
            case 'b':
                deleteNode();
                wait();
                break;
            case 'c':
                printf("先序遍历结果(非递归):\n\t\t");
                PreOrderTraverse2(Tree,1);
                printf("\n中序遍历结果(非递归):\n\t\t");
                InOrderTraverse2(Tree,1);
                printf("\n后序遍历结果(非递归):\n\t\t");
                PostOrderTraverse2(Tree,1);
                wait();
                break;
            case 'd':
                printf("层次遍历结果:\n\t\t");
                levelOrderTraverse(Tree);
                wait();
                break;
            case 'e':
                showTreeByTab(Tree,0);
                wait();
                break;
            case 'f':
                showTreeBylist(Tree);
                wait();
                break;
            case 'g':
                ShowBinTree(Tree);
                wait();
                break;
            case 'h':
                Huffman();
                wait();
                break;
            case 'i':
                binaryTree();
                wait();
                break;
            case '0':
                exit(0);
        }
    }
    return 0;
}


//先序、中序、后序遍历以Tree为根指针的二叉树  递归法
//先序
void PreOrderTraverse(BiTNode *Tree)
{
    if(Tree==NULL)
        return;
    printf("%-5d ",Tree->data);
    PreOrderTraverse(Tree->left);
    PreOrderTraverse(Tree->right);
}
//中序
void InOrderTraverse(BiTNode *Tree)
{
    if(Tree==NULL)
        return;
    InOrderTraverse(Tree->left);
    printf("%-5d",Tree->data);
    InOrderTraverse(Tree->right);
}
//后序
void PostOrderTraverse(BiTNode *Tree)
{
    if(Tree==NULL)
        return;
    PostOrderTraverse(Tree->left);
    PostOrderTraverse(Tree->right);
    printf("%-5d",Tree->data);
}

//统计叶子节点数目
void leafCount(BiTNode *Tree)//先序

    {if (Tree == NULL)
        return;
    if (Tree->left == NULL && Tree->right == NULL)
    {
        leafSum++;
        return;
    }
    leafCount(Tree->left);
    leafCount(Tree->right);
} 

//二叉树深度 
int treeDeep(BiTNode *Tree)
{
    int leftDeep,rightDeep;
    if(Tree==NULL)
        return 0;
    leftDeep=treeDeep(Tree->left);
    rightDeep=treeDeep(Tree->right);
    if(leftDeep<rightDeep)
        return rightDeep+1;
    else
        return leftDeep+1;
}

//左右子树交换 
void changeTree(BiTNode *Tree)
{
    BiTNode *temp;
    if(Tree!=NULL)
    {
        temp=Tree->left;
        Tree->left=Tree->right;
        Tree->right=temp;
        changeTree(Tree->left);
        changeTree(Tree->right);
    }
}

//使用数组elem中的随机数序列(以0表示结束,不包括0),生成以Tree为根指针的二叉排序树
/*
二叉排序树:
若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树分别为二叉排序树。
*/
void createBinaryTree()//生成二叉排序树
{
    init0(elem);
    Tree=NULL;
    for(int i=0;elem[i]!=0;i++)
        Tree=insertChild(Tree,elem[i]);
}

//在以Tree为根指针的二叉排序树中查找结点
void searchElem(BiTNode *Tree)
{
    int elem;
    BiTNode *tree;
    printf("请输入要查找结点:");
    scanf("%-5d",&elem);
    if(Tree==NULL)
    {
        printf("查找失败,此树为空!");
    }
    else
        tree=search(Tree,elem);
    if(tree==NULL)
    {
        printf("查找失败,无此元素!");
        return;
    }
    printf("此树为\n");
    InOrderTraverse(Tree);
    printf("\n查找成功!\n");
    printf("元素为:%d\n",elem);

}

//从以Tree为根指针的二叉排序树中删除结点(适用各种位置的结点)
void deleteNode()
{
    if(Tree==NULL)
    {
        printf("查找失败,此树为空!");
        return;
    }
    int elem;
    BiTNode *tree;
    printf("请输入要删除结点:");
    scanf("%d",&elem);
    tree=search(Tree,elem);
    if(tree==NULL)
    {
        printf("查找失败,无此元素!");
        return;
    }
    else
    {
        printf("删除前:\n");
        InOrderTraverse(Tree);
        Tree=Delete(Tree,elem);
        printf("\n删除结点成功!\n");
        printf("删除后:\n");
        InOrderTraverse(Tree);
    }
}

//https://www.cnblogs.com/greedyco/p/7182555.html
//用非递归算法,先序遍历以Tree为根指针的二叉树。
//提示:用数组 BiTNode *stack[max] 构成堆栈,利用这个堆栈实现功能。
//后进先出
void PreOrderTraverse2(BiTNode *Tree,int flag) //flag=1:打印 flag=2:进数组
{
    BiTNode *stack[max];
    int top=-1;
    BiTNode *p;
    if(flag==2)
        length=-1;
    if(Tree!=NULL)
    {
        top++;
        stack[top]=Tree;//先将根结点压栈
        while(top>-1)   //栈不为空时循环
        {
            p=stack[top];  // 栈顶元素出栈
            top--;
            if(flag==1)
                printf("%-5d",p->data);    // 访问栈顶元素
            else
            {
                length++;
                pre[length]=p->data;//数组记录
            }
            if(p->right!=NULL)    // 如果右孩子不为空,则进栈
            {
                top++;
                stack[top]=p->right;
            }
            if(p->left!=NULL)    // 如果左孩子不为空,则进栈
            {
                top++;
                stack[top]=p->left;
            }
        }
    }
    else 
        printf("此树为空!\n");
}

//中序-非递归(左根右)
void InOrderTraverse2(BiTNode *Tree,int flag) //flag=1:打印 flag=2:进数组
{
    if(flag==2)
        length=-1;
    BiTNode *stack[max];
    BiTNode *p;
    int top = -1;
    if (Tree != NULL)
    {
        p = Tree;
        while (top > -1 || p != NULL)
        {
            while (p != NULL) // while循环将根结点的最左结点全部压栈
            {
                top++;
                stack[top] = p;
                p = p->left;
            }
            if (top > -1) // 当结点p没有最左结点时出栈
            {
                p = stack[top];
                if(flag==1)
                    printf("%-5d", p->data); // 访问结点p
                else
                {
                    length++;
                    in[length]=p->data;//数组记录
                }
                top--;
                p = p->right; // 转向处理右孩子结点
            }
        }
    }
}

//后序-非递归(左右根)
void PostOrderTraverse2(BiTNode *Tree,int flag) //flag=1:打印 flag=2:进数组
{
    if(flag==2)
        length=-1;
    BiTNode *stack[max];
    BiTNode *p;
    int top = -1;
    bool visited = false;
    BiTNode *pre = NULL;
    if (Tree != NULL)
    {

        // 1)初始化,根入栈
        stack[++top] = Tree;

        // 2)循环执行,直至栈空
        while (top != -1)
        {
            //读取栈顶结点,不出栈
            p = stack[top];

            if (p->left == NULL || visited)
            {
                visited = false;
                //栈顶结点有右子树 且 右子树未被访问:右子树入栈
                if (p->right != NULL && p->right != pre)
                {
                    stack[++top] = p->right;
                    //栈顶结点无右子树、栈顶结点有右子树 且 右子树已被访问:
                    //该结点出栈并访问之
                }
                else if (p->right == NULL || (p->right != NULL && p->right == pre))
                {
                    //出栈栈顶元素,并访问
                    top--;
                    if(flag==1)
                        printf("%-5d", p->data);
                    else
                    {
                        length++;
                        post[length]=p->data;//数组记录
                    }
                    //更新pre
                    pre = p;
                    visited = true;
                }
            }
            else
            { //有左孩子,左孩子入栈
                stack[++top] = p->left;
            }
        }
    }
}


//对以Tree为根指针的二叉树,从根结点开始,逐层从左到右输出各结点的数据。
//提示:用数组 BiTNode *queue[max] 构成队列,利用这个队列实现功能。
//先进先出
void levelOrderTraverse(BiTNode *Tree)
{
    BiTNode *queue[max];
    BiTNode *p;
    int front=0,rear=0;//front和rear表示队首和队尾的指针
    if(Tree!=NULL)    //若树为空
    {
        rear++;
        queue[rear]=Tree;
        while(front!=rear)    //当队列非空
        {
            front++;
            p=queue[front];//队首元素出队列,并访问这个节点
            printf("%-5d",p->data);
            if(p->left!=NULL)     //若左子树非空,则入队列
            {
                rear++;
                queue[rear]=p->left;    
            }
            if(p->right!=NULL)     //若右子树非空,则入队列
            {
                rear++;
                queue[rear]=p->right;
            }
        }
    }
    else 
        printf("此树为空!\n");
}

//*用缩入格式的多行文本表示以Tree为根指针的二叉树,例如:
//  324
//     123
//      746
//      690
//     567
void showTreeByTab(BiTNode *Tree,int count)
{
    for(int j=0;j<count;j++)
        printf("\t");
    if(Tree==NULL)
    {
        printf("空\n");
        return;
    }
    printf("%d\n",Tree->data);
    if(Tree->right==NULL&&Tree->left==NULL)//叶子节点
        return;
    //左
    showTreeByTab(Tree->left,count+1);
    //右
    showTreeByTab(Tree->right,count+1);

}

//用广义表表示以Tree为根指针的二叉树,例如
// (324(123(746,690),567))
//*用广义表表示以Tree为根指针的二叉树,例如
// (324(123(746()())(690()()))(567()()))
void showTreeBylist(BiTNode *Tree)
{
    if(Tree!=NULL)
    {
        printf("%d",Tree->data);
        if(Tree->left!=NULL||Tree->right!=NULL)
        {
            printf("(");
            showTreeBylist(Tree->left);
            printf(",");
            showTreeBylist(Tree->right);
            printf(")");
        }
    }
}


/*
根据Huffman编码原理,使用数组elem中的随机数序列(以0表示结束,不包括0)
作为结点的权重,生成赫夫曼树,以及赫夫曼编码,计算平均带权径长度。
*/
void Huffman()
{
    // BiTNode 
    // //int i;
    // for(i=0;elem[i]!=0;i++)
    // {

    // }
    printf("Now Programming. . .\n");
}

/*
1、随机生成二叉树。 
2、生成并保存先(后)序、中序输出序列。 
3、按照保存的一对输出序列恢复出二叉树。 
4、生成先(后)序、中序输出序列。 
5、比较两对输出序列。
*/
void binaryTree()
{
    Tree=NULL;
    Tree=init1();
    FILE *f=NULL;
    f = fopen("Tree.txt", "w");
    fprintf(f, "先序:");
    PreOrderTraversePrintf(Tree,f);
    fprintf(f, "\n中序:");
    InOrderTraversePrintf(Tree,f);
    fprintf(f, "\n后序:");
    PostOrderTraversePrintf(Tree,f);

    fprintf(f, "\n______________________________________________________________________\n");
    
    InOrderTraverse2(Tree,2);
    PostOrderTraverse2(Tree,2);
    int n=length+1;
    Tree=buildTree(in,post,n);
    fprintf(f, "新树:");
    fprintf(f, "\n中序:");
    InOrderTraversePrintf(Tree,f);
    fprintf(f, "\n后序:");
    PostOrderTraversePrintf(Tree,f);
    fclose(f);
    printf("\n保存成功!已按中序和后序生成新二叉树,生成文件为:Tree.txt。\n");
}

猜你喜欢

转载自blog.csdn.net/m0_62925086/article/details/129160258