数据结构:二叉树(二)
在上一篇中我们实现了二叉树的顺序结构——堆的实现,这次实现链式结构,若对堆不了解,可以观看。
目录
在上一篇中我们实现了二叉树的顺序结构——堆的实现,这次实现链式结构,若对堆不了解,可以观看https://blog.csdn.net/w200514/article/details/143086428?sharetype=blog&shareId=143086428&sharerefer=APP&sharesource=w200514&sharefrom=link
一.二叉树链式结构的实现
1.二叉树的创建
对于二叉树的创建,我们只需要创建节点,并将其连接到左右节点上即可
//构建二叉树
BTNode* CreatNode(BTDataType x)
{
BTNode* tmp = (BTNode*)malloc(sizeof(BTNode));
if (tmp == NULL)
return 0;
BTNode* node = tmp;
if (node == NULL)
printf("申请内存失败");
node->_data = x;
node->_left = NULL;
node->_right = NULL;
return node;
}
BTNode* A = CreatNode('A');
BTNode* B = CreatNode('B');
BTNode* C = CreatNode('C');
BTNode* D = CreatNode('D');
BTNode* E = CreatNode('E');
A->_left = B;
A->_right = C;
B->_left = D;
B->_right = E;
如图我们创建出了一个二叉树,在这里我们将空节点显示出来,以便于接下来遍历时的理解
2.二叉树的销毁
二叉树的销毁从底部开始向上逐层销毁,我们用递归的方法来实现
//销毁
void BinaryTreeDestroy(BTNode* root)
{
if (root == NULL)
return;
BinaryTreeDestroy(root->_left);
BinaryTreeDestroy(root->_right);
free(root);
}
3.二叉树的遍历
二叉树遍历分为两种,广度优先(层序遍历),深度优先(前/中/后序遍历)
1.深度优先
前/中/后序遍历的不同,主要是因为根节点遍历的顺序不同
前序遍历:按照根-左子树-右子树的顺序遍历.
对于我们上图创建的二叉树来说,前序遍历应为A B D NULL NULL E NULL NULL C NULL NULL
为何会出现这种情况,我们将使用递归的方式来实现
//前序排列
void PrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->_data);
PrevOrder(root->_left);
PrevOrder(root->_right);
}
中序遍历:左子树-根-右子树
NULL D NULL B NULL E NULL A NULL C NULL
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->_left);
printf("%c ", root->_data);
InOrder(root->_right);
}
后序遍历:左子树-右子树-根
NULL NULL D NULL NULL E B NULL NULL C A
void LastOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
LastOrder(root->_left);
LastOrder(root->_right);
printf("%c ", root->_data);
}
2.广度优先
层序遍历:自上而下,自左而右的遍历
A B C D E
对于层序遍历,我们可以利用队列来实现.
将根节点存入队列,每次取出一个节点,就将其的左右节点放入队列(如果有左右节点)
//层序遍历
void LevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
return;
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->_data);
if (front->_left)
QueuePush(&q, front->_left);
if (front->_right)
QueuePush(&q, front->_right);
}
QueueDestory(&q);
printf("\n");
}
4.求二叉树节点数
二叉树节点数我们只需要将左子树节点数加上右子树节点数,再加1(根节点)即可
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
return 0;
else
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}
5.求二叉树叶子节点个数
当只有根节点时,返回1,否则返回左子树加右子树节点数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
return 0;
if (root->_left == NULL && root->_right == NULL)
return 1;
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
6.求第k层节点数
int BinaryTreeLeveIKSize(BTNode* root, int k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
return BinaryTreeLeveIKSize(root->_left, k - 1) + BinaryTreeLeveIKSize(root->_right, k - 1);
}
7.查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
return NULL;
if (root->_data == x)
return root;
BTNode* node = BinaryTreeFind(root->_left, x);
if (node != NULL)
return node;
node = BinaryTreeFind(root->_right, x);
if (node != NULL)
return node;
return NULL;
}
8.判断是否为完全二叉树
int BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
return 1;
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
break;
QueuePush(&q, front->_left);
QueuePush(&q, front->_right);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front)
{
QueueDestory(&q);
return 0;
}
}
QueueDestory(&q);
return 1;
}
二.整体代码
1.BinaryTree.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
void PrevOrder(BTNode* root);
void InOrder(BTNode* root);
void LastOrder(BTNode* root);
int BinaryTreeSize(BTNode* root);
int BinaryTreeLeafSize(BTNode* root);
int BinaryTreeLeveIKSize(BTNode* root, int k);
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
BTNode* CreatNode(BTDataType x);
void BinaryTreeDestroy(BTNode* root);
void LevelOrder(BTNode* root);
int BinaryTreeComplete(BTNode* root);
2.BinaryTree.c
#include "BinaryTree.h"
#include "Queue.h"
//前序排列
void PrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->_data);
PrevOrder(root->_left);
PrevOrder(root->_right);
}
//中序排列
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->_left);
printf("%c ", root->_data);
InOrder(root->_right);
}
//后序排列
void LastOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
LastOrder(root->_left);
LastOrder(root->_right);
printf("%c ", root->_data);
}
//层序遍历
void LevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
return;
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->_data);
if (front->_left)
QueuePush(&q, front->_left);
if (front->_right)
QueuePush(&q, front->_right);
}
QueueDestory(&q);
printf("\n");
}
//求二叉树节点数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
return 0;
else
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}
//二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
return 0;
if (root->_left == NULL && root->_right == NULL)
return 1;
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
//二叉树第k层节点数
int BinaryTreeLeveIKSize(BTNode* root, int k)
{
if (root == NULL)
return 0;
if (k == 1)
return 1;
return BinaryTreeLeveIKSize(root->_left, k - 1) + BinaryTreeLeveIKSize(root->_right, k - 1);
}
//二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
return NULL;
if (root->_data == x)
return root;
BTNode* node = BinaryTreeFind(root->_left, x);
if (node != NULL)
return node;
node = BinaryTreeFind(root->_right, x);
if (node != NULL)
return node;
return NULL;
}
//构建二叉树
BTNode* CreatNode(BTDataType x)
{
BTNode* tmp = (BTNode*)malloc(sizeof(BTNode));
if (tmp == NULL)
return 0;
BTNode* node = tmp;
if (node == NULL)
printf("申请内存失败");
node->_data = x;
node->_left = NULL;
node->_right = NULL;
return node;
}
//销毁
void BinaryTreeDestroy(BTNode* root)
{
if (root == NULL)
return;
BinaryTreeDestroy(root->_left);
BinaryTreeDestroy(root->_right);
free(root);
}
//判断是否为完全二叉树,是返回1不是返回0
int BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
return 1;
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
break;
QueuePush(&q, front->_left);
QueuePush(&q, front->_right);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front)
{
QueueDestory(&q);
return 0;
}
}
QueueDestory(&q);
return 1;
}
3.Queue.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
extern struct BinaryTreeNode;
typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
struct QueueNode* _next;
QDataType _data;
}QueueNode;
typedef struct Queue
{
QueueNode* _head;
QueueNode* _tail;
}Queue;
void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
4.Queue.c
#include "Queue.h"
//初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->_head = pq->_tail = NULL;
}
//销毁
void QueueDestory(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->_head;
while (cur != NULL)
{
QueueNode* next = cur->_next;
free(cur);
cur = next;
}
pq->_head = pq->_tail = NULL;
}
//队尾入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
if (newNode == NULL)
{
printf("申请内存失败");
exit(-1);
}
newNode->_data = x;
newNode->_next = NULL;
if (pq->_head == NULL)
pq->_head = pq->_tail = newNode;
else
pq->_tail->_next = newNode;
pq->_tail = newNode;
}
//队头出
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->_head);
QueueNode* next = pq->_head->_next;
free(pq->_head);
pq->_head = next;
if (pq->_head == NULL)
pq->_tail = NULL;
}
//取队头数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->_head);
return pq->_head->_data;
}
//取队尾数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->_tail);
return pq->_tail->_data;
}
//返回1为空,返回0为非空
int QueueEmpty(Queue* pq)
{
assert(pq);
return pq->_head == NULL ? 1 : 0;
}
//获取数据个数
int QueueSize(Queue* pq)
{
assert(pq);
assert(pq->_head);
QueueNode* cur = pq->_head;
int size = 0;
while (cur != NULL)
{
++size;
cur = cur->_next;
}
return size;
}
5.test.c
#include "BinaryTree.h"
void TestBinaryTree()
{
BTNode* A = CreatNode('A');
BTNode* B = CreatNode('B');
BTNode* C = CreatNode('C');
BTNode* D = CreatNode('D');
BTNode* E = CreatNode('E');
A->_left = B;
A->_right = C;
B->_left = D;
B->_right = E;
printf("前序排列: ");
PrevOrder(A);
printf("\n");
printf("中序排列: ");
InOrder(A);
printf("\n");
printf("后序排列: ");
LastOrder(A);
printf("\n");
printf("层序排列: ");
LevelOrder(A);
printf("\n");
printf("二叉树节点为: ");
printf("%d", BinaryTreeSize(A));
printf("\n");
printf("二叉树叶子节点个数为: ");
printf("%d",BinaryTreeLeafSize(A));
printf("\n");
printf("二叉树第3层节点数为: ");
printf("%d",BinaryTreeLeveIKSize(A, 3));
printf("\n");
BTNode* result = BinaryTreeFind(A, 'C');
if (result != NULL)
{
printf("结点的地址为: %p\n", (void*)result);
printf("结点的值为: %c\n", result->_data);
}
else
printf("节点不存在\n");
printf("%d", BinaryTreeComplete(A));
BinaryTreeDestroy(A);
}
int main()
{
TestBinaryTree();
return 0;
}

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)