数据结构(五)——二叉树

文章详细介绍了二叉树的数据结构,包括顺序结构(数组)和链式结构(节点)的存储方式,以及如何通过递归实现先序、中序、后序遍历和层次遍历。
摘要由CSDN通过智能技术生成

一、二叉树定义

二叉树是一种常用的树状数据结构,它由一组称为节点的元素组成,这些节点通过指针连接起来,形成层次结构。

在二叉树中,每个节点最多有两个子节点,分别称为左子节点和右子节点。这两个子节点可以为空,即节点没有左子节点或者右子节点



二、顺序结构存储二叉树


1.代码示例


/*===============================================
*   文件名称:seqtree.c
*   创 建 者:  
*   创建日期:2023年08月11日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#define N 1024
typedef char seqtree_data;  


// 定义二叉树结构体类型
typedef struct seq_tree
{

    seqtree_data data[N] ; // 利用顺序结构存储二叉树
    int len ; // 记录二叉树数据个数
}seqtree, *pseqtree;

//初始化二叉树存储空间
pseqtree init_seqtree()
{
    pseqtree T = (pseqtree) malloc(sizeof(seqtree));
    if( NULL == T )
    {
        return NULL ;
    }

    T->len = 0 ;  // 数据开始为0个

    return T ;

}

//插入数据创建二叉树
int create_seqtree(pseqtree T , int pos)
{
	//输入数据
    seqtree_data data ;
    scanf("%c",&data) ;
    getchar();  //处理垃圾字符
    T->len++ ; //长度加1
    
    //‘#’代表结束
    if( '#' == data )
    {
        return -1 ;
    }
    
    T->data[pos] = data; //数据给到存储空间
    
    //调用自身实现左子树创建
    create_seqtree(T , 2*pos+1 ) ;

    //右子树
    create_seqtree(T , 2*pos+2 ) ;

    return 0 ;
    
}

//循环输出二叉树
int show_seqtree(pseqtree T)
{
    for(int i = 0 ; i < T->len ; i++ )
    {
        printf("%c  ",T->data[i]);
    }
    puts("");
    return 0 ;
}

int main(int argc, char *argv[])
{ 
    pseqtree T = init_seqtree();
    if( NULL == T )
    {
        puts("init err ");
        return -1;
    }

    create_seqtree(T,0);

    if( 0 != show_seqtree(T))
    {
        puts("show err");
        return -1;
    }
    return 0;
} 

2.结果


在这里插入图片描述

三、链式存储二叉树


1.头文件


/*===============================================
*   文件名称:linktree.h
*   创 建 者:
*   创建日期:2023年08月10日
*   描    述:
================================================*/
#ifndef _LINKTREE_H
#define _LINKTREE_H
//数据类型取别名
typedef char linktree_char;

//定义节点类型
typedef struct link_tree
{
    linktree_char data;
    struct link_tree * rchild ;
    struct link_tree * lchild ;
}linktree , *plinktree;

//创建树
plinktree init_linktree();

//先序遍历
int precedence_linktree( plinktree T );

//中序遍历
int inorder_linktree( plinktree T);

//后续遍历
int epilogue_linktree( plinktree T);

//层次遍历
int level_linktree( plinktree T);



#endif

2.功能代码


/*===============================================
*   文件名称:linktree.c
*   创 建 者: 
*   创建日期:2023年08月10日
*   描    述:
================================================*/
#include <stdio.h>
#include <stdlib.h>
#include "linktree.h"
#include "seqqueue.h"
//创建树
plinktree init_linktree()
{
    
    //输入树的节点的数据
    linktree_char c ;
    scanf("%c",&c);
    getchar();
    if( '#' == c )//
        return NULL  ;
    
    plinktree T = (plinktree) malloc(sizeof(linktree));
    if( NULL == T )
    return NULL;

    T->data = c;  

    //左子树
    T->lchild = init_linktree();

    //右子树
    T->rchild = init_linktree();

    return T;

}


//先序遍历
int precedence_linktree( plinktree T )
{
    if( NULL == T )
        return -1;

    //根
    printf("%c ",T->data);

    //左
    precedence_linktree( T->lchild );

    //右
    precedence_linktree( T->rchild );
    
    return 0;
}

//中序遍历
int inorder_linktree( plinktree T)
{
    if( NULL == T )
        return -1;


    //左
    inorder_linktree( T->lchild );

    //根
    printf("%c ",T->data);

    //右
    inorder_linktree( T->rchild );

    return 0;
}

//后续遍历
int epilogue_linktree( plinktree T)
{
    if( NULL == T )
        return -1;


    //左
    epilogue_linktree( T->lchild );
    
    //右
    epilogue_linktree( T->rchild );

    //根
    printf("%c ",T->data);

    return 0;
}

//层次遍历
int level_linktree( plinktree T)
{
    if( NULL == T )
        return -1;
    
    psqueue Q =  init_seqqueue();//创建一个队列
    if( NULL == Q )
    {
        printf("init seq err");
        return -1;
    }
    
    //将数根入队
    if( 0 != input_seqqueue(Q,T))
    {
        return -2;
        puts("input err ");
    }
    
    //循环入队和出队
    while( 0 != empty_seqqueue(Q)) //队列为空则结束循环
    {
    
    	//出队
        plinktree p = out_seqqueue(Q);
        if( NULL == p )
        {
            puts(" out err");
            return -1;
        }

        printf("%c ",p->data);

	//左节点不为空,入队
        if( NULL != p->lchild)
        if( 0 != input_seqqueue(Q,p->lchild))
        {
            puts("l input err ");
            return -2;

        }
        
        //右节点不为空,入队
        if( NULL != p->rchild)
        if( 0 != input_seqqueue(Q,p->rchild))
        {
            puts("r input err ");
           return -2;
        }
    }

    return 0;
}



3.测试代码


/*===============================================
*   文件名称:main.c
*   创 建 者:    
*   创建日期:2023年08月10日
*   描    述:
================================================*/
#include <stdio.h>
#include "linktree.h"

int main(int argc, char *argv[])
{ 

    //创建树
    plinktree T = init_linktree();
    if( NULL == T )
    {
        puts("init err");
        return -1;
    }

    //先序遍历
    puts("先序遍历");
    if( 0 != precedence_linktree(T))
    {
        puts(" pre err ");
        return -1;
    }
    puts("");

    //中序遍历
    puts("中序遍历");
    if( 0 != inorder_linktree(T))
    {
        puts(" ino err");
        return -1;
    }
    puts("");

    //后序遍历
    puts("后序遍历");
    if( 0 != epilogue_linktree(T))
    {
        puts("epi err");
        return -1;
    }
    puts("");

    //层次遍历
    puts("层次遍历");
    int i = level_linktree(T);
    if( 0 != i)
    {
        printf("%d\n",i);
        puts("lev err");
        return -1;
    }
    puts("");


    return 0;
} 

4.运行结果


在这里插入图片描述

使用队列的代码

/*===============================================
*   文件名称:seqqueue.c
*   创 建 者: 
*   创建日期:2023年08月09日
*   描    述:
================================================*/
#include <stdio.h>
#include "seqqueue.h"
#include <stdlib.h>
//创建
psqueue init_seqqueue()
{
    psqueue Q = (psqueue ) malloc(sizeof(squeue));
    if( NULL == Q )
        return NULL;
    Q->r = 0; //队尾
    Q->f = 0;//队首
    return Q;
}

//入队
int input_seqqueue(psqueue Q , queue_data value)
{
    if( NULL == Q )
        return -1;
    if( 0 == full_seqqueue(Q))
        return -2;

    Q->data[Q->r] = value ;// 从队尾插入
    Q->r = (Q->r+1)%N; //队尾移动一位
    return 0;

}

//出队
queue_data out_seqqueue(psqueue Q)
{

    //
    if( NULL == Q )
        return NULL;
    if( 0 == empty_seqqueue(Q))
        return NULL;

    queue_data t = Q->data[Q->f];//从队头出队
    Q->f = (Q->f+1)%N; //队头移动一位
    return t;
}

//判空
int empty_seqqueue(psqueue Q)
{
    if( NULL == Q )
        return -1;
    if( Q->r == Q->f )  // 如果出队与入队标识重合,则为空队列
        return 0 ;
    else
        return 1;

}

//判满
int full_seqqueue(psqueue Q )
{

    if( NULL == Q )
        return -1;
    if( Q->f == (Q->r+1)%N ) // 人为定义,在队尾离队头有一个位置时为满队列,用一个数组元素空间来判断队列是否满
        return 0;
    else 
        return 1;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值