二叉树:是n个结点的有限集合,该集合或者为空集(空树), 或者由有个根结点和两棵子树树组成。
特点:每个树结点最多有两个子结点,所以二叉树中不存在度大于2.
二叉树的五种形态:
1、空树。
2、只有根结点。
3、根结点只有左子树。
4、根结点只有右子树。
5、根结点既有左子树又有右子树。
二叉树的特殊形式:
满二叉树:在一个二叉树中,如果分支结点都存在左子树和右子树并且所有的叶节点都在同一层上。
特点:叶子只能出现在最小一层。
非叶子结点的度一定是2.
在同样深度的二叉树中,满二叉树的结点个数最多,叶结点数最多。
完全二叉树:对一个具有n个结点的二叉树按层次编号,如果编号为i的结点与同样深度的满二叉树中的位置完全相同,则这个树称为完全二叉树
二叉树的性质
1、二叉树第i层最多有2^(i - 1)个结点。
2、深度为k的二叉树最多有2^k - 1 个结点。
3、对任意一颗二叉树,如果叶结点有N个,度为2的非叶结点有M个, 则 N = M + 1。
4、具有N个结点的完全二叉树高度为【log2N】+ 1 。【number】代表取不大于number的最大整数。
编程实现队二树叉的操作
头文件
#ifndef __BTREE_H__
#define __BTREE_H__
#define TRUE 1
#define FALSE 0
#define LEFT 0
#define RIGHT 1
typedef char BTreeData;
//二叉树的结点
typedef struct _btreeNode
{
BTreeData data;
struct _btreeNode* lchild;//指向左孩子的指针
struct _btreeNode* rchild;//指向右孩子的指针
}BTreeNode;
//二叉树
typedef struct _btree
{
BTreeNode *root;//指向根结点
int count;//树的结点树
}BTree;
typedef void (*Print_BTree)(BTreeNode*);
//创建树
BTree* Create_BTree();
//添加结点
int Btree_Insert (BTree*tree, BTreeData, int pos, int count, int flag);
/*
pos为走的路径 类似 110 (左右右) 011(右右左) 0代表左1代表右,倒着看
count为走的步数, flag为被替换的结点应该插入新结点的位置:0(左LEFT),1(右RIGHT)
*/
//显示
void Display (BTree*tree, Print_BTree pfunc);
//删除结点
int Btree_Delete (BTree*tree, int pos, int count);
//树高
int Btree_Height (BTree*tree);
//树的度
int Btree_Degree (BTree*tree);
//清空
int Btree_Clear (BTree*tree);
//销毁
int Btree_Destory (BTree**tree);
//前序遍历树节点
void pre_order (BTreeNode* node);
//中序遍历树节点
void mid_order (BTreeNode* node);
//后序遍历树节点
void last_order (BTreeNode* node);
#endif
操作函数
#include <stdlib.h>
#include "BTree.h"
#include <stdio.h>
//创建树
BTree* Create_BTree()
{
BTree* btree = (BTree*)malloc(sizeof(BTree)/sizeof(char));
if (NULL == btree)
return NULL;
//初始化
btree->count = 0;
btree->root = NULL;
return btree;
}
//添加结点
int Btree_Insert(BTree*tree, BTreeData data, int pos, int count, int flag)
{
if (NULL == tree || (flag != LEFT && flag != RIGHT))
return FALSE;
//创建新结点空间
BTreeNode *node = (BTreeNode*)malloc(sizeof(BTreeNode)/sizeof(char));
if (NULL == node)
return FALSE;
//初始化
node->data = data;
node->rchild = NULL;
node->lchild = NULL;
//找插入位置
BTreeNode* parent = NULL;
BTreeNode* current = tree->root;//current一开始指向根节点,根结点的父节点为空
int way;//保存当前走的位置
while (count > 0 && current != NULL)
{
way = pos & 1;//取当前走的方向
pos = pos >> 1;//移去走过的路
parent = current;//保存走之前的父节点的位置
if (way == LEFT)
current = current->lchild;
else
current = current->rchild;
count--;
}//current最终指向要插入的地方
//把被替换掉的结点插在新建结点下
if (flag == LEFT)
node->lchild = current;
else
node->rchild = current;
//把新建结点插入二叉树,上面while循环最后way保存了要查入的位置(父节点的左/右)
if (parent != NULL)//有父
{
if (way == LEFT)
parent->lchild = node;
else
parent->rchild = node;
}
else
{
tree->root = node;//无父即新建结点替换根节点
}
tree->count ++;//树的结点数+1
return TRUE;
}
//递归显示
void r_display(BTreeNode* node, Print_BTree pfunc, int gap)
{
int i;
if (NULL == node)
{
for (i = 0; i < gap; i++)
{
putchar('-');
}
putchar('\n');
return;
}
for (i = 0; i < gap; i++)
{
putchar('-');
}
//打印结点
//printf ("%c\n", node->data);
pfunc (node);
if (node->lchild != NULL || node->rchild != NULL)
{
r_display(node->lchild, pfunc, gap+4);//打印左孩子
r_display(node->rchild, pfunc, gap+4);//打印右孩子
}
}
//显示
void Display (BTree*tree, Print_BTree pfunc)
{
if (NULL == tree)
return;
r_display(tree->root, pfunc, 0);
}
//递归释放结点空间
void r_delete(BTree*tree, BTreeNode* node)
{
if (NULL == tree || NULL == node)
return;
//先删左孩子
r_delete(tree, node->lchild);
//删右孩子
r_delete(tree, node->rchild);
free(node);
tree->count --;
}
//删除结点
int Btree_Delete (BTree*tree, int pos, int count)
{
if (NULL == tree)
return FALSE;
//找位置
BTreeNode* parent = NULL;
BTreeNode* current = tree->root;//current一开始指向根节点,根结点的父节点为空
int way;//保存当前走的位置
while (count > 0 && current != NULL)
{
way = pos & 1;//取当前走的方向
pos = pos >> 1;//移去走过的路
parent = current;//保存走之前的父节点的位置
if (way == LEFT)
current = current->lchild;
else
current = current->rchild;
count--;
}
if (parent != NULL)//有父
{
if (way == LEFT)
parent->lchild = NULL;
else
parent->rchild = NULL;
}
else
{
tree->root = NULL;//
}//current最终指向要删除的地方
//释放结点空间
r_delete(tree, current);
return TRUE;
}
//树高
int r_height (BTreeNode* node)
{
if (NULL == node)
return 0;
int lh = r_height(node->lchild);//左孩子的高
int rh = r_height(node->rchild);//右孩子的高
return (lh > rh ? lh+1 : rh+1);
}
int Btree_Height (BTree*tree)
{
if (NULL == tree)
return FALSE;
int height = r_height(tree->root);
return height;
}
//树的度
int r_degree (BTreeNode* node)
{
if (NULL == node)
return 0;
int degree = 0;//所给结点自身也有度
if (node->lchild != NULL)
degree++;
if (node->rchild != NULL)
degree++;
if (degree == 1)//二叉树的度最大为2,度为1才有变数,需求其子结点的度,查看有没有子结点的度为2
{
int ld = r_degree (node->lchild);//左孩子的度
if (ld == 2)
return 2;//如果左孩子的度为二,直接返回2,不用再看右孩子的度,二叉树的度最大为2
int rd = r_degree (node->rchild);//右孩子的度
if (rd == 2)
return 2;//如果左孩子的度为二,直接返回2,二叉树的度最大为2
}
return degree;//度为0返回0;度为1返回1;度为2返回2:二叉树的度最大为2
}
int Btree_Degree (BTree*tree)
{
if (NULL == tree)
return FALSE;
int degree = r_degree (tree->root);
return degree;
}
//清空
int Btree_Clear (BTree*tree)
{
if (NULL == tree)
return FALSE;
Btree_Delete (tree, 0, 0);//删除根结点
tree->root = NULL;//删除后tree->root仍指向原先位置,需置空,防止以后使用出现段错误
return TRUE;
}
//销毁(销毁函数里的tree接受的是main函数里的tree指针自身的地址,销毁函数里的*tree是main函数里tree的指向,指向二叉树)
int Btree_Destory (BTree**tree)
{
if (NULL == tree)
return FALSE;
Btree_Clear(*tree);//*tree为二叉树树的地址
free (*tree);//释放tree指向的树空间(BTree)
*tree = NULL;//让main函数中的tree置空
return TRUE;
}
//前序遍历树节点(根,左,右)
void pre_order (BTreeNode* node)
{
if (NULL == node)
return;
printf ("%4c", node->data);
pre_order (node->lchild);
pre_order (node->rchild);
}
//中序遍历树节点(左,根,右)
void mid_order (BTreeNode* node)
{
if (NULL == node)
return;
mid_order (node->lchild);
printf ("%4c", node->data);
mid_order (node->rchild);
}
//后序遍历树节点(左,右,根)
void last_order (BTreeNode* node)
{
if (NULL == node)
return;
last_order (node->lchild);
last_order (node->rchild);
printf ("%4c", node->data);
}
主函数,实例测试
#include <stdio.h>
#include "BTree.h"
void printA (BTreeNode* node)
{
printf ("%c\n", node->data);
}
int main()
{
BTree* btree = Create_BTree();
if (NULL == btree)
{
printf("创建失败\n");
}
else
{
printf("创建成功\n");
}
Btree_Insert(btree, 'A', 0, 0, 0);
Btree_Insert(btree, 'B', 0, 1, 0);
Btree_Insert(btree, 'C', 1, 1, 0);
Btree_Insert(btree, 'D', 0, 2, 0);
Btree_Insert(btree, 'E', 2, 2, 0);
Btree_Insert(btree, 'F', 0, 3, 0);
Btree_Insert(btree, 'G', 4, 3, 0);
Btree_Insert(btree, 'H', 3, 2, 0);
Display(btree, printA);
printf ("前序遍历:\n");
pre_order (btree->root);
putchar ('\n');
printf ("中序遍历:\n");
mid_order (btree->root);
putchar ('\n');
printf ("后序遍历:\n");
last_order (btree->root);
putchar ('\n');
Btree_Delete (btree, 0, 1);//删除B节点
printf ("删除后\n");
Display(btree, printA);
printf ("height = %d\n", Btree_Height(btree));
printf ("degree = %d\n", Btree_Degree(btree));
printf ("清空后\n");
Btree_Clear (btree);
Display (btree, printA);
Btree_Destory (&btree);//要想在调用的函数里将btree置空需将其地址传给函数
if (NULL == btree)
{
printf ("销毁成功\n");
}
else
{
printf ("销毁失败\n");
}
return 0;
}