目录
一、二叉树概念及结构
1.1概念
1.2现实中的二叉树:
1.3 特殊的二叉树:
1.4 二叉树的存储结构
1. 顺序存储
2. 链式存储
二、二叉树的顺序结构及实现
2.1 二叉树的顺序结构
三、二叉树链式结构的实现
3.1 前置说明
3.2二叉树的遍历
3.2.1前序、中序以及后序遍历
①前序遍历递归图解:
②中序遍历
③后序遍历
3.2.2二叉树的层序遍历
层序遍历主要代码:
层序遍历全部代码:
3.2.3求一棵树的大小
3.2.4求一棵树的高度
3.2.5二叉树第k层节点个数
3.2.6二叉树查找值为x的节点 BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
递归展开图:
3.2.7代码汇总
一、二叉树概念及结构
1.1概念


1.2现实中的二叉树:
1.3 特殊的二叉树:

1.4 二叉树的存储结构
1. 顺序存储

2. 链式存储


二、二叉树的顺序结构及实现
2.1 二叉树的顺序结构

三、二叉树链式结构的实现
3.1 前置说明
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(BTDataType x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");}node->data = x;node->left = NULL;node->right = NULL;return node;
}
BTNode* CreatTree()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}
int main()
{BTNode* root = CreatTree();return 0;
}

3.2二叉树的遍历
3.2.1前序、中序以及后序遍历
// 二叉树前序遍历
void PreOrder(BTNode* root);
// 二叉树中序遍历
void InOrder(BTNode* root);
// 二叉树后序遍历
void PostOrder(BTNode* root);
下面主要分析前序递归遍历,中序与后序图解类似,同学们可自己动手绘制。
①前序遍历递归图解:
// 二叉树前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){printf("NULL");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}
②中序遍历
// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}PreOrder(root->left);printf("%d ", root->data);PreOrder(root->right);
}
③后序遍历
// 二叉树后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}PreOrder(root->left);PreOrder(root->right);printf("%d ", root->data);
}
3.2.2二叉树的层序遍历
核心思想:用队列,出上一层带入下一层
不能把1的值带进队列,这样不好把1的左右孩子带进去,所以得存1的结构体,但是结构体比较大,所以存1的结构体的指针
层序遍历主要代码:
test.c中的主要代码
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;void LevelOrder(BTNode* root)
{Queue q;QueueInit(&q);if (root){QueuePush(&q, root);}while (!QueueEmpty(&q)){//出上一层,带下一层BTNode* front = QueueFront(&q);QueuePop(&q);printf("%d ",front->data);if (front->left){QueuePush(&q, front->left);}if (front->right){QueuePush(&q, front->right);}}
}
Queue.h中的主要代码
typedef struct BinaryTreeNode* QDataType;
// 链式结构:表示队列
typedef struct QueueNode
{struct QListNode* next;QDataType data;
}QNode;
层序遍历全部代码:
Queue.h
#pragma once
#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include<stdbool.h>
#include"test.c"
typedef struct BinaryTreeNode* QDataType;
// 链式结构:表示队列
typedef struct QueueNode
{struct QListNode* next;QDataType data;
}QNode;
// 队列的结构
typedef struct Queue
{QNode* head;QNode* tail;int size;
}Queue;
// 初始化队列
void QueueInit(Queue* pq);
// 队尾入队列
void QueuePush(Queue* pq, QDataType x);
// 队头出队列
void QueuePop(Queue* pq);
// 获取队列头部元素
QDataType QueueFront(Queue* pq);
// 获取队列队尾元素
QDataType QueueBack(Queue* pq);
// 获取队列中有效元素个数
int QueueSize(Queue* pq);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq);
// 销毁队列
void QueueDestroy(Queue* pq);
Queue.c
#pragma once
#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include<stdbool.h>
#include"test.c"
typedef struct BinaryTreeNode* QDataType;
// 链式结构:表示队列
typedef struct QueueNode
{struct QListNode* next;QDataType data;
}QNode;
// 队列的结构
typedef struct Queue
{QNode* head;QNode* tail;int size;
}Queue;
//front rear为什么不能放在struct QListNode里面
//冗余存储:
//每个 QListNode 节点都会包含 front 和 rear 指针,这会导致大量的冗余存储。实际上,front 和 rear 只需要存储一次,而不是在每个节点中都存储。
//
//不一致性:
//如果每个节点都包含 front 和 rear 指针,那么当队列发生变化时(如入队或出队操作),需要更新所有节点的 front 和 rear 指针,这会导致数据不一致性和额外的复杂性。
//
//逻辑分离:
//QListNode 结构体的目的是表示队列中的一个节点,而 front 和 rear 指针是用于管理整个队列的。将它们放在 QListNode 中会混淆节点的表示和队列的管理逻辑。
// 初始化队列
void QueueInit(Queue* pq);
// 队尾入队列
void QueuePush(Queue* pq, QDataType x);
// 队头出队列
void QueuePop(Queue* pq);
// 获取队列头部元素
QDataType QueueFront(Queue* pq);
// 获取队列队尾元素
QDataType QueueBack(Queue* pq);
// 获取队列中有效元素个数
int QueueSize(Queue* pq);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq);
// 销毁队列
void QueueDestroy(Queue* pq);
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Queue.h"
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(BTDataType x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");}node->data = x;node->left = NULL;node->right = NULL;return node;
}
BTNode* CreatTree()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}
// 二叉树前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}
// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}
// 二叉树后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);
}
//求一颗树的大小
int TreeSize(BTNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
//求一颗树的高度
int TreeHeight(BTNode* root)
{if (root == NULL)return 0;int leftHeight = TreeHeight(root->left);int rightHeight = TreeHeight(root->right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
// 二叉树第k层节点个数
int TreeKLevel(BTNode* root, int k)
{assert(k > 0);if (root == 0){return 0;}if (k == 1){return 1;}int leftk = TreeKLevel(root->left, k - 1);int rightk=TreeKLevel(root->right, k - 1);return leftk + rightk;
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* lret=BinaryTreeFind(root->left,x);if (lret)//如果左数找到了,那么返回,没找到返回空{return lret;}BTNode* rret = BinaryTreeFind(root->right, x);if (rret)//如果左数找到了,那么返回,没找到返回空{return rret;}return NULL;
}void LevelOrder(BTNode* root){Queue q;QueueInit(&q);if (root){QueuePush(&q, root);}while (!QueueEmpty(&q)){//出上一层,带下一层BTNode* front = QueueFront(&q);QueuePop(&q);printf("%d ",front->data);if (front->left){QueuePush(&q, front->left);}if (front->right){QueuePush(&q, front->right);}}}
int main()
{BTNode* root = CreatTree();BTNode* ret = BinaryTreeFind(root, 5);int k=TreeKLevel(root,3);printf("%d", k);return 0;
}
3.2.3求一棵树的大小
方法一:
//求一颗树的大小
int TreeSize(BTNode* root,int *psize)
{if (root == NULL)return;++(*psize);TreeSize(root->left,psize);TreeSize(root->right,psize);
}
方法二:
//求一颗树的大小
int TreeSize(BTNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
3.2.4求一棵树的高度
//求一颗树的高度
int TreeHeight(BTNode* root)
{if (root == NULL)return 0;int leftHeight = TreeHeight(root->left);int rightHeight = TreeHeight(root->right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
3.2.5二叉树第k层节点个数
// 二叉树第k层节点个数
int TreeKLevel(BTNode* root, int k)
{if (root == 0){return 0;}if (k == 1){return 1;}int leftk = TreeKLevel(root->left, k - 1);int rightk=TreeKLevel(root->right, k - 1);return leftk + rightk;
}
3.2.6二叉树查找值为x的节点 BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* lret=BinaryTreeFind(root->left,x);if (lret)//如果左数找到了,那么返回,没找到返回空{return lret;}BTNode* rret = BinaryTreeFind(root->right, x);if (rret)//如果左数找到了,那么返回,没找到返回空{return rret;}return NULL;
}
递归展开图:
3.2.7代码汇总
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;
}BTNode;
BTNode* BuyNode(BTDataType x)
{BTNode* node = (BTNode*)malloc(sizeof(BTNode));if (node == NULL){perror("malloc fail");}node->data = x;node->left = NULL;node->right = NULL;return node;
}
BTNode* CreatTree()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}
// 二叉树前序遍历
void PreOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}printf("%d ", root->data);PreOrder(root->left);PreOrder(root->right);
}
// 二叉树中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}
// 二叉树后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("NULL ");return;}PostOrder(root->left);PostOrder(root->right);printf("%d ", root->data);
}
//求一颗树的大小
int TreeSize(BTNode* root)
{return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
//求一颗树的高度
int TreeHeight(BTNode* root)
{if (root == NULL)return 0;int leftHeight = TreeHeight(root->left);int rightHeight = TreeHeight(root->right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
// 二叉树第k层节点个数
int TreeKLevel(BTNode* root, int k)
{assert(k > 0);if (root == 0){return 0;}if (k == 1){return 1;}int leftk = TreeKLevel(root->left, k - 1);int rightk=TreeKLevel(root->right, k - 1);return leftk + rightk;
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->data == x){return root;}BTNode* lret=BinaryTreeFind(root->left,x);if (lret)//如果左数找到了,那么返回,没找到返回空{return lret;}BTNode* rret = BinaryTreeFind(root->right, x);if (rret)//如果左数找到了,那么返回,没找到返回空{return rret;}return NULL;
}
int main()
{BTNode* root = CreatTree();BTNode* ret = BinaryTreeFind(root, 5);int k=TreeKLevel(root,3);printf("%d", k);return 0;
}