二叉树的代码实现——C语言

一、顺序存储

二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系。
对于完全二叉树
在这里插入图片描述

将这二款二叉树存入数组中,相应的下标对应其相同的位置,如图所示:
在这里插入图片描述
对于一般二叉树:
在这里插入图片描述

在这里插入图片描述
由此可以看出,对于一般二叉树而言。采用顺序存储结构,会造成大量的空间浪费。所以顺序存储结构一般适用于满二叉树或者完全二叉树。
下面是具体代码:

#include<stdio.h>
#include<stdlib.h>

#define MaxSize 25
typedef char Tree[MaxSize];

// 创建顺序二叉树
void CreateTree(Tree T, int i){
    char ch;
    scanf(" %c", &ch);
    if(ch == '#'){
        T[i] = '0';
        getchar(); // 正确处理换行符
        return;
    }
    T[i] = ch;
    printf("请输入%c结点的左孩子:", T[i]);
    CreateTree(T, 2*i+1);
    printf("请输入%c结点的右孩子:", T[i]);
    CreateTree(T, 2*i+2);
}

// 获取树的根节点元素
char getRoot(Tree T){
    return T[0];
}

// 获取树的结点个数
int getNodeNum(Tree T){
    int num=0;
    for(int i=0; i<MaxSize; i++){
        if(T[i] != '0'){
            num++;
        }
    }
    return num;
}

// 打印二叉树
void printTree(Tree T, int level, int i){
    if(i < MaxSize && T[i] != '0'){
        // 打印当前节点
        printf("%c ", T[i]);
        // 打印左子树
        printTree(T, level + 1, 2*i+1);
        // 打印右子树
        printTree(T, level + 1, 2*i+2);
    }
}


int main(){
    Tree T;
    CreateTree(T, 0);

    printf("树的根节点元素为:%c\n", getRoot(T));
    printTree(T, 0, 0); // 打印二叉树,从根节点开始,level为0
    printf("\n");

    return 0;
}

二、链式存储

二叉树每个结点多有有两个孩子,所以为它设计一个数据域和两个指针域,我们称这样的链表为二叉链表

链式二叉树结点结构

typedef struct BiTNode  /* 结点结构 */
{
   TElemType data;		/* 结点数据 */
   struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
}BiTNode,*BiTree;

构造空二叉树

/* 构造空二叉树T */
void InitBiTree(BiTree *T){ 
	*T=NULL;
}

构造二叉树链表

/* 按前序输入二叉树中结点的值(一个字符) */
/* #表示空树,构造二叉链表表示二叉树T。 */
void CreateBiTree(BiTree *T){ 
	TElemType ch;
	
	scanf("%c",&ch);
    fflush(stdin);

	if(ch=='#'){
        *T=NULL;
    }
	else{
		*T=(BiTree)malloc(sizeof(BiTNode));
		if( !*T ){
            exit(0);
        }

		(*T)->data=ch; /* 生成根结点 */
        printf("输入%c的左孩子:", ch);
		CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        printf("输入%c的右孩子:", ch);
		CreateBiTree(&(*T)->rchild); /* 构造右子树 */
	}
}

销毁二叉树

/* 初始条件: 二叉树T存在。操作结果: 销毁二叉树T */
void DestroyBiTree(BiTree *T)
{ 
	if(*T) 
	{
		if((*T)->lchild) /* 有左孩子 */
			DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */
		if((*T)->rchild) /* 有右孩子 */
			DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */
		free(*T); /* 释放根结点 */
		*T=NULL; /* 空指针赋0 */
	}
}

判断二叉树是否为空

/* 初始条件: 二叉树T存在 */
/* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
int BiTreeEmpty(BiTree T)
{ 
	if(T)
		return 0;
	else
		return 1;
}

获取二叉树T的深度:Depth

/* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
int BiTreeDepth(BiTree T)
{
	int i,j;
	if(!T)
		return 0;
	if(T->lchild)
		i=BiTreeDepth(T->lchild);
	else
		i=0;
	if(T->rchild)
		j=BiTreeDepth(T->rchild);
	else
		j=0;
	return i>j?i+1:j+1;
}

返回二叉树T的根

/* 初始条件: 二叉树T存在。操作结果: 返回T的根 */
TElemType Root(BiTree T)
{ 
	if(BiTreeEmpty(T))
		return ' ';
	else
		return T->data;
}

前序遍历二叉树

/* 初始条件: 二叉树T存在 */
/* 操作结果: 前序递归遍历T */
void PreOrderTraverse(BiTree T)
{ 
	if(T==NULL)
		return;
	printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
	PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */
	PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */
}

中序遍历二叉树

/* 初始条件: 二叉树T存在 */
/* 操作结果: 中序递归遍历T */
void InOrderTraverse(BiTree T)
{ 
	if(T==NULL)
		return;
	InOrderTraverse(T->lchild); /* 中序遍历左子树 */
	printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
	InOrderTraverse(T->rchild); /* 最后中序遍历右子树 */
}

后续遍历二叉树

/* 初始条件: 二叉树T存在 */
/* 操作结果: 后序递归遍历T */
void PostOrderTraverse(BiTree T)
{
	if(T==NULL)
		return;
	PostOrderTraverse(T->lchild); /* 先后序遍历左子树  */
	PostOrderTraverse(T->rchild); /* 再后序遍历右子树  */
	printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
}

其它操作

/* 初始条件: 二叉树T存在,p指向T中某个结点 */
/* 操作结果: 返回p所指结点的值 */
TElemType Value(BiTree p)
{
	return p->data;
}
/* 给p所指结点赋值为value */
void Assign(BiTree p,TElemType value)
{
	p->data=value;
}

下面是所有代码汇总:

#include <stdio.h>
#include <stdlib.h>

typedef char TElemType;

/* 结点结构 */
typedef struct BiTNode  /* 结点结构 */
{
   TElemType data;		/* 结点数据 */
   struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
}BiTNode,*BiTree;

/* 构造空二叉树T */
void InitBiTree(BiTree *T)
{ 
	*T=NULL;
}

/* 按前序输入二叉树中结点的值(一个字符) */
/* #表示空树,构造二叉链表表示二叉树T。 */
void CreateBiTree(BiTree *T){ 
	TElemType ch;
	
	scanf("%c",&ch);
    fflush(stdin);

	if(ch=='#'){
        *T=NULL;
    }
	else{
		*T=(BiTree)malloc(sizeof(BiTNode));
		if( !*T ){
            exit(0);
        }

		(*T)->data=ch; /* 生成根结点 */
        printf("输入%c的左孩子:", ch);
		CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        printf("输入%c的右孩子:", ch);
		CreateBiTree(&(*T)->rchild); /* 构造右子树 */
	}
}

/* 初始条件: 二叉树T存在。操作结果: 销毁二叉树T */
void DestroyBiTree(BiTree *T)
{ 
	if(*T) 
	{
		if((*T)->lchild) /* 有左孩子 */
			DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */
		if((*T)->rchild) /* 有右孩子 */
			DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */
		free(*T); /* 释放根结点 */
		*T=NULL; /* 空指针赋0 */
	}
}

/* 初始条件: 二叉树T存在 */
/* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
int BiTreeEmpty(BiTree T)
{ 
	if(T)
		return 0;
	else
		return 1;
}

/* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
int BiTreeDepth(BiTree T)
{
	int i,j;
	if(!T)
		return 0;
	if(T->lchild)
		i=BiTreeDepth(T->lchild);
	else
		i=0;
	if(T->rchild)
		j=BiTreeDepth(T->rchild);
	else
		j=0;
	return i>j?i+1:j+1;
}

/* 初始条件: 二叉树T存在。操作结果: 返回T的根 */
TElemType Root(BiTree T)
{ 
	if(BiTreeEmpty(T))
		return ' ';
	else
		return T->data;
}

/* 初始条件: 二叉树T存在 */
/* 操作结果: 前序递归遍历T */
void PreOrderTraverse(BiTree T)
{ 
	if(T==NULL)
		return;
	printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
	PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */
	PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */
}

/* 初始条件: 二叉树T存在 */
/* 操作结果: 中序递归遍历T */
void InOrderTraverse(BiTree T)
{ 
	if(T==NULL)
		return;
	InOrderTraverse(T->lchild); /* 中序遍历左子树 */
	printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
	InOrderTraverse(T->rchild); /* 最后中序遍历右子树 */
}

/* 初始条件: 二叉树T存在 */
/* 操作结果: 后序递归遍历T */
void PostOrderTraverse(BiTree T)
{
	if(T==NULL)
		return;
	PostOrderTraverse(T->lchild); /* 先后序遍历左子树  */
	PostOrderTraverse(T->rchild); /* 再后序遍历右子树  */
	printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
}

int main(){
    int i;
    BiTree T;
    TElemType e1;
    InitBiTree(&T);

    // 创建二叉树
    printf("请输入二叉树结点:");
    CreateBiTree(&T);
    printf("构造空二叉树后,树是否为空?%d (1:是,0:否), 树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));
    e1 = Root(T);
    printf("树的根结点值为%c\n", e1);

    printf("\n先序遍历二叉树:");
    PreOrderTraverse(T);

    printf("\n中序遍历二叉树:");
    InOrderTraverse(T);

    printf("\n后序遍历二叉树:");
    PostOrderTraverse(T);

    // 销毁二叉树
    DestroyBiTree(&T);

    printf("\n清楚二叉树后,树是否为空?%d(1:是,0:否), 树的深度=%d\n", BiTreeEmpty(T), BiTreeDepth(T));

    if (BiTreeEmpty(T))
        printf("二叉树为空,销毁成功!\n");

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值