二叉树的实现-c

1.二叉树概况方向:

在这里我先推荐几道关于二叉树的基础OJ题,加快友友们实现。
链接: 基础OJ题

typedef char BTDataType;
 
typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;
 
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

2.分析与解刨

1.二叉树的销毁,我建议用一级指针,保持与其它的一致(到外面把根置空。),当然也可以用二级的。
2.判断是应该用bool,但是本质就是0是错,1是对,我们可以打印来观看。

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);

在这里插入图片描述

在先序遍历的过程中构建每一个节点
解析图
代码:

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树


BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
	//当结点没有孩子或这走到最后都要返回NULL
	if (a[*pi]=='#' || (*pi) >= n)
	{
		++(*pi);
		return NULL;
	}

	
	//创建一个结点
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		printf("malloc  file!");
		exit(-1);
	}

	root->data = a[(*pi)++];
	root->left = BinaryTreeCreate(a, n, pi);
	root->right= BinaryTreeCreate(a, n, pi);
	
	return root;
}

运行结果:
红框是前序遍历,后面两个是中和后序遍历
红框是前序遍历,后面两个是中和后序遍历
推荐一道题:链接: 二叉树遍历
题解解析:

/*
解题思路:
在先序遍历的过程中构建每一个节点
*/
#include <stdio.h>
#include <malloc.h>
 
typedef struct BTNode
{
    char _data;
    struct BTNode* _left;
    struct BTNode* _right;
}BTNode;
 
//中序遍历
void Inorder(BTNode* root)
{
    if(root)
    {
        Inorder(root->_left);
        printf("%c ", root->_data);
        Inorder(root->_right);
    }
}
 
BTNode* CreatBTree(char* str, int* pi)
{
    if(str[*pi]!= '#')
    {
        //当前节点非空,则创建当前节点
        BTNode*root=(BTNode*)malloc(sizeof(BTNode));
        root->_data = str[*pi];
        //字符位置向后移动一个位置
        ++(*pi);
        //创建左子树
        root->_left=CreatBTree(str,pi);
        //字符位置向后移动一个位置
        ++(*pi);
        //创建右子树
        root->_right=CreatBTree(str,pi);
        return root;
    }
    else
        return NULL;  //如果是空节点,则返回NULL
}
 
int main()
{
    char str[101];
    int i = 0;
    //读入字符串
    scanf("%s", str);
    //创建二叉树
    BTNode* root = CreatBTree(str, &i);
    //中序打印二叉树
    Inorder(root);
    printf("\n");
    return 0;
}
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);

层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在
层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层
上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

层序遍历解析图

层序遍历的思路:我们需要借助队列来实现,c语言只能自己来实现一个。链接: 队列
我们有了一个队列后(当然我们队列里存的是结点),我们可以先存一个树的根,然后取出的时候再放它的孩子,当然它孩子为空不存,只取。例如:存了A,当我们存它的孩子B、C的时候先利用队列的性质把A取出来(打印一下)后存BC。依次类推。
解析图
在这里插入图片描述
在这里插入图片描述
代码:

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}

	//如果队列不为空,进入。
	while (!QueueEmpty(&q))
	{
		//取出 打印 
		BTNode* front = QueueFront(&q);
		printf("%c ", front->data);
		QueuePop(&q);

		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}

	}

	printf("\n");
	//销毁队列
	QueueDestroy(&q);
}

运行结果:
A B C D E F G H

// 二叉树销毁
void BinaryTreeDestory(BTNode** root);

我建议使用一级,不用二级所以就,销毁我采用的是后序的方法来销毁。
代码段:

// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
		return;

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	//printf("%p %c\n", root, root->data);
	free(root);

}

通过打印看销毁成功
在这里插入图片描述

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

层序遍历遇到NULL,不把这个结点放进去,而判断完全二叉树先把NULL存进去,当拿出的那个结点为空;我们跳出来后;此时只有两种情况。(1.如果后面全是空,则是完全二叉树;2.如果后面还有非空,则不是完全二叉树。)

代码段:

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front)
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
		else
		{
			//遇到NULL,跳出。
			break;
		}

	}

	//1.如果后面全是空,则是完全二叉树;
	//2.如果后面还有非空,则不是完全二叉树。
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front)
		{
			QueueDestroy(&q);
			return false;
		}

	}

	QueueDestroy(&q);
	return true;
}

结果展示:
0为假1为真
1、前序遍历的数组"ABD##E#H##CF##G##"构建二叉树,它不是完全二叉树,而"ABD##E##CF##G##"是完全二叉树。
1.在这里插入图片描述
2在这里插入图片描述
显然第二个是完全二叉树

总的代码:

在这里插入图片描述

两个.h文件

#pragma once

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


typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;


// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode* root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);

#pragma once

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

//前置声明
struct BinaryTreeNode;

typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType data;
}QNode;

typedef struct
{
	QNode* head;
	QNode* tail;
}Queue;

//初始化
void QueueInit(Queue* pq);

//销毁
void QueueDestroy(Queue* pq);

//放数据
void QueuePush(Queue* pq, QDataType x);

//删除
void QueuePop(Queue* pq);

//长度
int QueueSize(Queue* pq);

//取头
QDataType QueueFront(Queue* pq);

//取尾
QDataType QueueBack(Queue* pq);

//判断空
bool QueueEmpty(Queue* pq);

3个.c文件

#include"bt.h"
#include"queue.h"

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树


BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
	//当结点没有孩子或这走到最后都要返回NULL
	if (a[*pi]=='#' || (*pi) >= n)
	{
		++(*pi);
		return NULL;
	}

	
	//创建一个结点
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		printf("malloc  file!");
		exit(-1);
	}

	root->data = a[(*pi)++];
	root->left = BinaryTreeCreate(a, n, pi);
	root->right= BinaryTreeCreate(a, n, pi);
	
	return root;
}

// 二叉树销毁
void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
		return;

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	//printf("%p %c\n", root, root->data);
	free(root);

}

// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
		return 0;

	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}

// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;

	if (root->left == NULL && root->right)
		return 1;

	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	assert(k >= 1);
	if (root == NULL)
		return 0;

	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;

	if (root->data == x)
		return root;

	
	BTNode* ret1 = BinaryTreeFind(root->left, x);
	if (ret1)
		return ret1;

	BTNode* ret2 = BinaryTreeFind(root->right, x);
	if (ret2)
		return ret2;

	return NULL;
}

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
		return;

	printf("%c ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
		return;

	BinaryTreePrevOrder(root->left);
	printf("%c ", root->data);
	BinaryTreePrevOrder(root->right);
}

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
		return;

	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
	printf("%c ", root->data);
}

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}

	//如果队列不为空,进入。
	while (!QueueEmpty(&q))
	{
		//取出 打印 
		BTNode* front = QueueFront(&q);
		printf("%c ", front->data);
		QueuePop(&q);

		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}

	}

	printf("\n");
	//销毁队列
	QueueDestroy(&q);
}

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front)
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
		else
		{
			//遇到NULL,跳出。
			break;
		}

	}

	//1.如果后面全是空,则是完全二叉树;
	//2.如果后面还有非空,则不是完全二叉树。
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front)
		{
			QueueDestroy(&q);
			return false;
		}

	}

	QueueDestroy(&q);
	return true;
}
#include"queue.h"

//初始化
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

//销毁
void QueueDestroy(Queue* pq)
{

	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->head = pq->tail = NULL;

}

//放数据
void QueuePush(Queue* pq, QDataType x)
{

	assert(pq);
	//开辟空间
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	//添加数据
	newnode->data = x;
	newnode->next = NULL;

	//链接
	if (pq->tail == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}

}

//判断空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

//删除
void QueuePop(Queue* pq)
{

	assert(pq);
	assert(!QueueEmpty(pq));

	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}

}


//取头
QDataType QueueFront(Queue* pq)
{

	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

//取尾
QDataType QueueBack(Queue* pq)
{

	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

//长度
int QueueSize(Queue* pq)
{

	assert(pq);

	QNode* cur = pq->head;
	int count = 0;
	while (cur)
	{
		++count;
		cur = cur->next;
	}

	return count;
}

#include"bt.h"
#include"queue.h"

int main()
{
    char ch[] = "ABD##E#H##CF##G##";
    //gets(ch);
    int n = strlen(ch);
    int i = 0;
    //BinaryTreeCreate
    BTNode* root = BinaryTreeCreate(ch, n, &i);
    //进行前序遍历,输出遍历结果。
    BinaryTreePrevOrder(root);
    printf("\n");
    //进行中序遍历,输出遍历结果。
    BinaryTreeInOrder(root);
    printf("\n");
    //进行后序遍历,输出遍历结果。
    BinaryTreePostOrder(root);
    printf("\n");
    //结点个数
    int ret = BinaryTreeSize(root);
    printf("%d\n", ret);
    //叶结点的个数
    int ret1 = BinaryTreeLeafSize(root);
    printf("%d\n", ret1);
    //第k个结点
    int ret2 = BinaryTreeLevelKSize(root, 2);
    printf("%d\n", ret2);

    //借用队列实现层序遍历
    BinaryTreeLevelOrder(root);

    // 判断二叉树是否是完全二叉树
    int ret3 = BinaryTreeComplete(root);
    printf("%d\n", ret3);

    BTNode* c = BinaryTreeFind(root, ch[2]);
    printf("%c", c->data);

    BinaryTreeDestory(root);
    root = NULL;
    return 0;
}

看完之后,二叉树的基本友友们已经掌握了,下个文章见.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昨天;明天。今天。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值