数据结构学习第5篇 - 二叉树的建立与遍历

二叉树的建立与遍历

如下图所示,通过输入该完全二叉树的顺序存储结构,程序自动建立该完全二叉树的链式存储结构,并利用链式存储结构实现对该二叉树的先序遍历、中序遍历、后序遍历和层次遍历。

注意:1.程序启动时,由用户输入结点数量,并按顺序输入结点的值

      2.先序、中序遍历必须包含非递归实现

 


# include <stdio.h>
# include <malloc.h>
# include <stdlib.h>
# define MAXNODE 40
# define MAXSIZE 40

typedef int elemtype;

//定义二叉树结点
typedef struct BiTNode
{
    elemtype data;
    struct BiTNode * lchild,* rchild;
    int index;
}BiTNode,* BiTree;

//定义查看函数
void Visite(elemtype data)
{
    printf("\t%d\n",data);
}

typedef BiTree datatype;

//定义顺序存放结点数据的栈
typedef struct
{
    datatype data[MAXSIZE];
    int top;
    int flag;
}SeqStack;

//定义栈初始化函数
SeqStack * Init_SeqStack()
{
    SeqStack * s =(SeqStack *)malloc(sizeof(SeqStack));
    s->top=-1;
    s->flag=0;
    return s;
}

//定义判断栈是否为空的函数
int Empty_SeqStack(SeqStack * s)
{
    if(s->top==-1)
        return 1;
    else
        return 0;
}

//定义入栈函数
int Push_SeqStack(SeqStack * s,datatype x)
{
    if(s->top==MAXSIZE-1)
        return 0;
    else
    {
        s->top++;
        s->data[s->top]=x;
        s->flag=1;
        return 1;
    }
}

//定义出栈函数
int Pop_SeqStack(SeqStack * s,datatype * x)
{
    if(Empty_SeqStack(s)==1)
        return 0;
    else
    {
        *x=s->data[s->top];
        s->top--;
        return 1;
    }
}

//定义取栈顶元素函数
datatype Top_SeqStack(SeqStack * s)
{
    if(Empty_SeqStack(s)==1)
        return 0;
    else
        return(s->data[s->top]);
}

//定义初始化二叉树函数
//参数bt:根结点的指针变量
//返回值:0--动态内存分配失败  1--初始化成功
int initnate(BiTree *bt,elemtype x)
{
    /*初始化建立二叉树bt的头结点*/
    if((*bt = (BiTNode *)malloc(sizeof(BiTNode))) == NULL)//判断动态内存是否分配
    {
        printf("动态内存没有分配!\n");
        return 0;
    }
    (*bt)->data = x;
    (*bt)->lchild= NULL;
    (*bt)->rchild= NULL;
    (*bt)->index = 1;
    return 1;
}

//定义一个二叉树左子树插入函数
//参数:bt--根结点指针  x--插入结点的数据  parent--插入位置的指点  index--索引
//返回值:NULL--动态内存没有分配,插入失败  bt--根结点指针
BiTree InsertL(BiTree bt,elemtype x,BiTree parent,int index)
{

    /*在二叉树bt的结点parent的左子树插入数据元素x*/
    BiTree p;
    if(parent == NULL)
    {
        printf("\n插入出错!\n");
        return NULL;
    }
    //p = (BiTree)malloc(sizeof(BiTNode));
    if((p = (BiTree)malloc(sizeof(BiTNode))) == NULL)//判断动态内存是否分配成功
        return NULL;
    p->data = x;
    p->index = index;
    p->lchild = NULL;
    p->rchild = NULL;
    if(parent->lchild == NULL)
    {
        
        parent->lchild = p;
    }
    else
    {
        p->lchild = parent->lchild;//在parent节点与它的左子树插入一个新的节点
        parent->lchild = p;
    }
    return bt;
}

//定义一个二叉树右子树插入函数
//参数:bt--根结点指针  x--插入结点的数据  parent--插入位置的指点
//返回值:NULL--动态内存没有分配,插入失败  bt--根结点指针
BiTree InsertR(BiTree bt,elemtype x,BiTree parent,int index)
{
    /*在二叉树bt的结点parent的右子树插入数据元素x*/
    //printf("right\n");
    BiTree p;
    if(parent == NULL)
    {
        printf("插入出错!\n");
        return NULL;
    }
    if((p = (BiTree)malloc(sizeof(BiTNode)))== NULL)//判断动态内存是否分配成功
        return NULL;
    p->data = x;
    p->index = index;
    p->lchild = NULL;
    p->rchild = NULL;
    if(parent->rchild == NULL)
    {
        parent->rchild = p;
    }
    else
    {
        p->rchild = parent->rchild;//在parent节点与它的右子树插入一个新的节点
        parent->rchild = p;
    }
    return bt;
}

//定义一个二叉树左子树删除函数
//参数:bt--根结点指针  parent--所要删除结点的指针
//返回值:NULL--删除错误  bt--删除成功,返回根结点指针
int DeleteL(BiTree bt,BiTree parent)
{
    /*在二叉树删除结点parent的左子树*/
    BiTree p;
    if(parent == NULL)//判断所要删除的结点时否为空,或它的左子树是否为空
    {    
        printf("删除错误!\n");
        return 0;
    }    
    p = parent->lchild;
    parent->lchild = NULL;
    free(p);/*当p为非叶子结点时,这样删除仅释放了所删子树根结点的空间*/
            /*若要删除子树分支中的结点,需要后面介绍的遍历操作来实现*/
    p=NULL;
    return 1;
}

//定义一个二叉树右子树删除函数
//参数:bt--根结点指针  parent--所要删除结点的指针
//返回值:NULL--删除错误  bt--删除成功,返回根结点指针
int DeleteR(BiTree bt,BiTree parent)
{
    /*在二叉树删除结点parent的右子树*/
    BiTree p;
    if(parent == NULL||parent->rchild==NULL)//判断所要删除的结点时否为空,或它的左子树是否为空
    {    
        printf("删除错误!\n");
        return 0;
    }    
    p = parent->rchild;
    parent->rchild = NULL;
    free(p);/*当p为非叶子结点时,这样删除仅释放了所删子树根结点的空间*/
            /*若要删除子树分支中的结点,需要后面介绍的遍历操作来实现*/
    return 1;
}
 
//定义先序遍历二叉树函数
//参数bt:根结点指针
void NRPreOrder(BiTree bt)
{
    /*非递归先序遍历二叉树*/
    int i=0;
    SeqStack * stack_1=Init_SeqStack();
    BiTree p=NULL;
    if(bt==NULL)
        return;
    p=bt;
    stack_1->top=0;
    while(p!=NULL||stack_1->top!=0)
    {
        while(p!=NULL)
        {
            Visite(p->data);//访问结点的数据域
            
            if(Push_SeqStack(stack_1, p)==0)
            {
                printf("栈溢出!\n");
                free(stack_1);
                p=NULL;
                stack_1=NULL;
                return;
            }
            
            if(stack_1->top==0)
                return;
            p = p->lchild;//指针指向p的左子树
        }
        if(Empty_SeqStack(stack_1)==1)//栈空时结束
        {
            free(stack_1);
            stack_1=NULL;
            p=NULL;
            return;
        }
        else
        {
        
            Pop_SeqStack(stack_1,&p);
            
            p=p->rchild;//指针指向p的右子树结点
        }
    }
    free(stack_1);
    stack_1=NULL;
    p=NULL;
    return;
}

//定义中序遍历二叉树函数
//参数bt:根结点指针
void NRMidOrder(BiTree bt)
{
    /*非递归先序遍历二叉树*/
    SeqStack * stack_1=Init_SeqStack();
    BiTree p=NULL;
    if(bt==NULL)
        return;
    p=bt;
    stack_1->top=0;
    while(p!=NULL||stack_1->top!=0)
    {
        while(p!=NULL)
        {
            if(Push_SeqStack(stack_1, p)==0)
            {
                printf("栈溢出!\n");
                free(stack_1);
                p=NULL;
                stack_1=NULL;
                return;
            }
            
            if(stack_1->top==0)
                return;
            p = p->lchild;//指针指向p的左子树
        }
        if(Empty_SeqStack(stack_1)==1)//栈空时结束
        {
            free(stack_1);
            stack_1=NULL;
            p=NULL;
            return;
        }
        else
        {
        
            Pop_SeqStack(stack_1,&p);
            Visite(p->data);//访问结点的数据域
            p=p->rchild;//指针指向p的右子树结点
        }
    }
    free(stack_1);
    stack_1=NULL;
    p=NULL;
    return;
}

typedef struct
{
    BiTree link;
    int flag;
}stacktype;

//定义二叉树后序遍历函数
//参数:bt--根结点   
void PostOrder(BiTree bt)
{
    if(bt==NULL)
        return;
    PostOrder(bt->lchild);
    PostOrder(bt->rchild);
    Visite(bt->data);
}

//定义二叉树查找函数
//参数:bt--根结点指针  x--要查找的结点的数据域
//返回值: NULL--搜索失败  p--要搜索结点的指针
BiTree Search(BiTree bt,int index)
{
    int i,memory[MAXNODE];
    int top=-1;
    BiTree p=NULL;
    if(bt==NULL)
    {
        printf("该二叉树为空!\n");
        return NULL;
    }
    while(index!=1)
    {
        index=index/2;
        top++;
        if(top<MAXNODE)
        {
            memory[top] = index;    
        }
    }
    for(i=top;i>=0;i--)
    {
        if(memory[i]==1)
        {
            p=bt;
        }
        if(memory[i]%2==0&&memory[i]>1)
        {
            p=p->lchild;
        }
        if(memory[i]%2==1&&memory[i]>1)
        {
            p=p->rchild;
        }
    }
    
    return p;
}

//定义删除函数
//参数:bt--根结点指针  n--结点个数
void DeleteBiTree(BiTree bt,int n)
{
    int i,index;
    BiTree p;
    for(i=n;i>=1;i--)
    {
        index=i;
        if(index==1)
        {
            Visite(bt->data);
            free(bt);
            bt=NULL;
        }
        if(index%2==0&&index>1)
        {
            p=Search(bt , index);
            DeleteL(bt, p);
        }
        if(index%2==1&&index>1)
        {
            p=Search(bt , index);
            DeleteR(bt, p);
        }
        
    }
    return;
}

//功能菜单
void Menu(void)
{
    printf("-----------------------------------------------\n");
    printf("\t二叉树的建立与遍历\n");
    printf("功能菜单:\n");
    printf("\t1.创建二叉树\n");
    printf("\t2.各种遍历\n");
    printf("\t3.注销并退出功能菜单\n");
    printf("-----------------------------------------------\n\n");
}

//递归后序遍历
//参数bt:根结点指针
void PreOrder(BiTree bt)
{
    if(bt==NULL)
    {
        return;
    }
    Visite(bt->data);
    PreOrder(bt->lchild);
    PreOrder(bt->rchild);
}

//定义层次遍历参数
//参数:bt--根结点指针 n--二叉树的结点数
void LevelTraver(BiTree bt,int n)
{
    int i;
    int index;
    BiTree p=bt;
    for(i=1;i<=n;i++)
    {
        index=i;
        if(index==1)
        {
            Visite(bt->data);
        }
        if(index%2==0&&index>1)
        {
            p=Search(bt , index);
            printf("\t%d\n",p->lchild->data);
        }
        if(index%2==1&&index>1)
        {
            p=Search(bt , index);
            printf("\t%d\n",p->rchild->data);
        }
        
    }
    return;
}
 
//定义创建二叉树函数
//参数:val--指向顺序存储数据的指针,n--二叉树的结点数
//返回值:NULL--创建二叉树失败  bt--二叉树的根结点指针
BiTree CreateBiTree(elemtype * val,int n)
{
    int i;

    BiTree bt=NULL;
    BiTree p=NULL;
    int index;
    for(i=0;i<n;i++)
    {
        
        index=i+1;

        if(index==1)
        {
            if(initnate(&bt,val[i])==0)
            {
                printf("动态内存分配失败!\n");
                return NULL;
            }
            p=bt;
        }
        if(index%2==0&&index>1)
        {
            p=Search(bt , index);
            InsertL(bt , val[i] , p , index);
        }
        if(index%2==1&&index>1)
        {
            p=Search(bt , index);
            InsertR(bt , val[i] , p , index);
        }
    }
        
    return bt;
}

int main()
{
    int i,n,op;
    BiTree parent=NULL;
    BiTree bt=NULL;
    while(1)
    {
        Menu();
        printf("请输入你的选择:");
        scanf("%d",&op);
        switch(op)
        {
            case 1:
            {
                printf("请输入你要创建二叉树的结点树:");
                scanf("%d",&n);
                elemtype * val=(elemtype *)malloc(sizeof(elemtype) * n);
                for(i=0;i<n;i++)
                {
                    printf("请输入第%d个结点的数据:",i+1);
                    scanf("%d",&val[i]);
                }
                bt=CreateBiTree(val,n);
                break;
            }
            case 2:
                printf("层次遍历:\n");
                LevelTraver(bt,n);
                printf("后序遍历:\n");
                PostOrder(bt);
                printf("先序遍历:\n");
                NRPreOrder(bt);
                printf("中序遍历:\n");
                NRMidOrder(bt);
                break;    
            case 3:
                DeleteBiTree(bt, n);
                printf("菜单已关闭!\n");
                return 0;
            default:
                printf("输入错误!\n");
                break;
        }    
    }
}

猜你喜欢

转载自blog.csdn.net/guanshanyue96/article/details/89006262