1、基本特征
A、表达树形结构的最简模型, 每个节点最多有两个子节点
B、单根, 每个子节点有且仅有一个父节点, 整棵树只有一个根节点
C、具有递归结构的特征, 用递归的方法处理, 可以简化算法
2、基本操作: 生成、遍历
按照特定的规则生成或遍历, 能得到一个特定的结构
3、实现要点
A、由父及子的生成方式
B、三种遍历序
(a)前序遍历: 处理节点自己的数据->处理左节点->处理右节点
(b)中序遍历: 处理左节点->处理节点自己的数据->处理右节点
(c)后序遍历: 处理左节点->处理右节点->处理节点自己的数据
范例:
有序二叉树(二叉搜索树)
在树中的任何一个节点, 左子节点的值 < 节点值 < 右子节点的值
// .h
// 有序二叉树(二叉搜索树)
#ifndef _BT_H
#define _BT_H
#include <sys/types.h>
/*
中序二叉树
50,70,20,60,40,30,10,90,80
50
_/ \_
/ \
20 70
/ \ / \
10 40 60 90
/ /
30 80
中序遍历: 10,20,30,40,50,60,70,80,90
前序遍历: 50,20,10,40,30,70,60,90,80
后续遍历: 10,30,40,20,60,80,90,70,50
*/
// 节点
typedef struct BsTreeNode
{
int data; // 数据
struct BsTreeNode* left; // 左子树
struct BsTreeNode* right; // 右子树
} BSTREE_NODE;
// 二叉树
typedef struct BsTree
{
BSTREE_NODE* root; // 根节点
size_t size; // 数量
} BSTREE;
// 初始化为空树
void bstree_init(BSTREE* bstree);
// 释放剩余节点并恢复到初始状态
void bstree_deinit(BSTREE* bstree);
// 插入
void bstree_insert(BSTREE* bstree, int data);
// 删除
int bstree_erase(BSTREE* bstree, int data);
// 删除所有匹配数据
void bstree_remove(BSTREE* bstree, int data);
// 清空
void bstree_clear(BSTREE* bstree);
// 更新
void bstree_update(BSTREE* bstree, int old, int new);
// 判断是否存在
int bstree_exist(BSTREE* bstree, int data);
// 中序遍历
void bstree_travel(BSTREE* bstree);
// 数量
size_t bstree_size(BSTREE* bstree);
// 高度
size_t bstree_height(BSTREE* bstree);
#endif
// .c
#include <stdio.h>
#include <stdlib.h>
#include "cbtree.h"
static BSTREE_NODE* create_node(int data)
{
BSTREE_NODE* node = (BSTREE_NODE*)malloc(sizeof(BSTREE_NODE));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
static void destroy_node(BSTREE_NODE* node)
{
free(node);
}
// -----------------------递归形式的内部接口--------------------------
// 清空以参数节点为根的子树
static void clear(BSTREE_NODE** tree)
{
if (*tree) {
clear(&(*tree)->left);
clear(&(*tree)->right);
destroy_node(*tree);
*tree = NULL;
}
}
static void insert(BSTREE_NODE* node, BSTREE_NODE** tree)
{
if (!*tree) {
*tree = node;
}
else if (node) {
if (node->data < (*tree)->data) {
// 插入左子树
insert(node, &(*tree)->left);
}
else {
// 插入右子树
insert(node, &(*tree)->right);
}
}
}
// 返回以参数tree的目标所指向的节点为根的子树中,
// 数值与参数data相匹配的节点的父节点中,指向该节点的指针型成员变量的地址
static BSTREE_NODE** find(int data, BSTREE_NODE** tree)
{
if (! *tree) {
return tree;
}
else {
if (data == (*tree)->data) {
return tree;
}
else {
if (data < (*tree)->data) {
return find(data, &(*tree)->left);
}
else {
return find(data, &(*tree)->right);
}
}
}
}
static void travel(BSTREE_NODE* tree)
{
if (tree) {
travel(tree->left);
printf("%d ", tree->data);
travel(tree->right);
}
}
static size_t height(BSTREE_NODE* tree)
{
if (tree) {
size_t lh = height(tree->left);
size_t rh = height(tree->right);
return (lh > rh ? lh : rh) + 1;
}
return 0;
}
// 初始化为空树
void bstree_init(BSTREE* bstree)
{
bstree->root = NULL;
bstree->size = 0;
}
// 释放剩余节点并恢复到初始状态
void bstree_deinit(BSTREE* bstree)
{
clear(&bstree->root);
bstree->size = 0;
}
// 插入
void bstree_insert(BSTREE* bstree, int data)
{
insert(create_node(data), &bstree->root);
++bstree->size;
}
// 删除
int bstree_erase(BSTREE* bstree, int data)
{
// 删除节点前, 要把左子树插入右子树,然后把右子树提升到当前节点
BSTREE_NODE** node = find(data, &bstree->root);
if (*node) {
// 将匹配节点的左子树插入右子树
insert((*node)->left, &(*node)->right);
BSTREE_NODE* temp = *node;
// 用匹配节点的右子树的根节点取代匹配节点
*node = (*node)->right;
// 删除匹配节点
destroy_node(temp);
--bstree->size;
return 1;
}
return 0;
}
// 删除所有匹配数据
void bstree_remove(BSTREE* bstree, int data)
{
while (bstree_erase(bstree, data));
}
// 清空
void bstree_clear(BSTREE* bstree)
{
bstree_deinit(bstree);
}
// 更新
void bstree_update(BSTREE* bstree, int old, int new)
{
while (bstree_erase(bstree, old)) {
bstree_insert(bstree, new);
}
}
// 判断是否存在
int bstree_exist(BSTREE* bstree, int data)
{
return *find(data, &bstree->root) != NULL;
}
// 中序遍历
void bstree_travel(BSTREE* bstree)
{
travel(bstree->root);
printf("\n");
}
// 数量
size_t bstree_size(BSTREE* bstree)
{
return bstree->size;
}
// 高度
size_t bstree_height(BSTREE* bstree)
{
return height(bstree->root);
}
#include <stdio.h>
#include <stdlib.h>
#include "cbtree.h"
int main(void)
{
BSTREE tree;
bstree_init(&tree);
bstree_insert(&tree, 50);
bstree_insert(&tree, 70);
bstree_insert(&tree, 20);
bstree_insert(&tree, 60);
bstree_insert(&tree, 40);
bstree_insert(&tree, 30);
bstree_insert(&tree, 10);
bstree_insert(&tree, 90);
bstree_insert(&tree, 80);
printf("%zu, %zu \n", bstree_size(&tree), bstree_height(&tree));
bstree_travel(&tree);
bstree_erase(&tree, 60);
bstree_travel(&tree);
bstree_insert(&tree, 50);
bstree_insert(&tree, 50);
bstree_travel(&tree);
bstree_remove(&tree, 50);
bstree_travel(&tree);
bstree_insert(&tree, 40);
bstree_insert(&tree, 40);
bstree_travel(&tree);
bstree_update(&tree, 40, 85);
bstree_travel(&tree);
printf("%d, %d\n", bstree_exist(&tree, 40), bstree_exist(&tree, 85));
bstree_deinit(&tree);
return 0;
}
/*
Output:
9, 4
10 20 30 40 50 60 70 80 90
10 20 30 40 50 70 80 90
10 20 30 40 50 50 50 70 80 90
10 20 30 40 70 80 90
10 20 30 40 40 40 70 80 90
10 20 30 70 80 85 85 85 90
0, 1
*/