1、完全二叉树的存储可以使用一维数组进行存储。因为每个节点 i 的左儿子为 i*2,右儿子为 i*2 + 1;每个节点 i 的双亲为 i / 2;
2、链式存储结构
(1):二叉链表结构,结点由 结点元素和两个分别指向左、右子树的指针组成;
struct ChainTwo
{
DATA data;
struct ChainTwo *left;
struct ChainTwo *right;
};
(2):三叉链表结构,结点由 结点元素和两个分别指向左、右子树和父结点的指针组成;
struct ChainThree
{
DATA data;
struct ChainThree *left;
struct ChainThree *right;
struct ChainThree *parent;
};
#include <stdio.h>
#include <stdlib.h>
#define QUEUE_MAXSIZE 50
typedef char DATA;
//定义二叉链式结构
typedef struct ChainTree
{
DATA data;
struct ChainTree *left;
struct ChainTree *right;
}ChainBinTree;
//初始化二叉树
ChainBinTree * BinTreeInit(ChainBinTree *node)
{
if (node != NULL)
return node;
else
return NULL;
}
/************************************************************************
函数名称:BinTreeAddNode
函数功能:添加结点到二叉树
函数参数:bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树
函数返回:成功返回1,失败返回0
************************************************************************/
int BinTreeAddNode(ChainBinTree *bt, ChainBinTree *node, int n)
{
if (bt == NULL)
{
printf("父结点不存在,请先设置父结点!\n");
return 0;
}
switch(n)
{
case 1: //添加到左结点
if (bt->left)
{
printf("左子树不为空!\n");
return 0;
}
else
bt->left = node;
break;
case 2://添加到右结点
if (bt->right)
{
printf("右子树不为空!\n");
return 0;
}
else
bt->right = node;
break;
default:
printf("输入错误!\n");
return 0;
}
return 1;
}
/************************************************************************
函数名称:BinTreeLeft
函数功能:返回结点的左子树
函数参数:bt为父结点
函数返回:返回值为结点的左子树
************************************************************************/
ChainBinTree * BinTreeLeft(ChainBinTree *bt)
{
if (bt)
return bt->left;
else
return NULL;
}
/************************************************************************
函数名称:BinTreeRight
函数功能:返回结点的右子树
函数参数:bt为父结点
函数返回:返回值为结点的右子树
************************************************************************/
ChainBinTree * BinTreeRight(ChainBinTree *bt)
{
if (bt)
return bt->right;
else
return NULL;
}
/************************************************************************
函数名称:BinTreeIsEmpty
函数功能:判断树是否为空
函数参数:bt为父结点
函数返回:返回0表示树非空,返回1表示是空树
************************************************************************/
int BinTreeIsEmpty(ChainBinTree *bt)
{
if (bt)
return 0;
else
return 1;
}
/************************************************************************
函数名称:BinTreeIsEmpty
函数功能:判断树是否为空
函数参数:bt为父结点
函数返回:返回0表示树非空,返回1表示是空树
************************************************************************/
int BinTreeDepth(ChainBinTree *bt)
{
int dep1, dep2;
if (bt == NULL)
return 0;
else
{
dep1 = BinTreeDepth(bt->left);//左子树深度,递归调用
dep2 = BinTreeDepth(bt->right);//右子树深度,递归调用
if (dep1 > dep2)
return dep1 + 1;
else
return dep2 + 1;
}
}
/************************************************************************
函数名称:BinTreeFind
函数功能:在树中查找某个数值等于data的结点
函数参数:bt为父结点, 数值为data
函数返回:若没有找到返回NULL,若找到返回该结点的指针
************************************************************************/
ChainBinTree *BinTreeFind(ChainBinTree *bt, DATA data)
{
ChainBinTree *p;
if (bt == NULL)
return NULL;
else
{
if (bt->data == data)
return bt;
else
{
if (p = BinTreeFind(bt->left, data))
return p;
else if (p = BinTreeFind(bt->right, data))
return p;
else
return NULL;
}
}
}
/************************************************************************
函数名称:BinTreeClear
函数功能:清空二叉树,释放每个结点的内存,使树变为空树
函数参数:bt为父结点
函数返回:没有返回值
************************************************************************/
void BinTreeClear(ChainBinTree *bt)
{
if (bt)
{
BinTreeClear(bt->left);
BinTreeClear(bt->right);
free(bt);
bt = NULL;
}
return;
}
/************************************************************************
函数名称:oper
函数功能:输出结点的数据data
函数参数:bt为结点
函数返回:没有返回值
************************************************************************/
void oper(ChainBinTree *p)
{
if (p)
{
printf("%c ", p->data);
}
return;
}
/************************************************************************
函数名称:BinTree_DLR
函数功能:先序遍历树(DLR,D表示树根,L表示左子树,R表示右子树)
函数参数:bt为父结点, oper表示处理结点数据的函数
函数返回:没有返回值
************************************************************************/
void BinTree_DLR(ChainBinTree *bt, void (*oper)(ChainBinTree *p))
{
if (bt)
{
oper(bt);
BinTree_DLR(bt->left, oper);
BinTree_DLR(bt->right, oper);
}
return;
}
/************************************************************************
函数名称:BinTree_LDR
函数功能:中序遍历树(LDR,D表示树根,L表示左子树,R表示右子树)
函数参数:bt为父结点, oper表示处理结点数据的函数
函数返回:没有返回值
************************************************************************/
void BinTree_LDR(ChainBinTree *bt, void (*oper)(ChainBinTree *p))
{
if (bt)
{
BinTree_LDR(bt->left, oper);
oper(bt);
BinTree_LDR(bt->right, oper);
}
return;
}
/************************************************************************
函数名称:BinTree_LRD
函数功能:后序遍历树(LRD,D表示树根,L表示左子树,R表示右子树)
函数参数:bt为父结点, oper表示处理结点数据的函数
函数返回:没有返回值
************************************************************************/
void BinTree_LRD(ChainBinTree *bt, void (*oper)(ChainBinTree *p))
{
if (bt)
{
BinTree_LRD(bt->left, oper);
BinTree_LRD(bt->right, oper);
oper(bt);
}
return;
}
/************************************************************************
函数名称:BinTree_Level
函数功能:按层遍历树
函数参数:bt为父结点, oper表示处理结点数据的函数
函数返回:没有返回值
************************************************************************/
void BinTree_Level(ChainBinTree *bt, void (*oper)(ChainBinTree *p))
{
ChainBinTree *p;
ChainBinTree *q[QUEUE_MAXSIZE];
int head = 0, tail = 0;
if (bt)
{
tail = (tail + 1) % QUEUE_MAXSIZE;
q[tail] = bt;
}
while (head != tail)
{
head = (head + 1) % QUEUE_MAXSIZE;
p = q[head];
oper(p);
if (p->left != NULL)
{
tail = (tail + 1) % QUEUE_MAXSIZE;
q[tail] = p->left;
}
if (p->right != NULL)
{
tail = (tail + 1) % QUEUE_MAXSIZE;
q[tail] = p->right;
}
}
return;
}
/************************************************************************
函数名称:InitRoot
函数功能:创建二叉树的根
函数参数:bt为父结点, oper表示处理结点数据的函数
函数返回:没有返回值
************************************************************************/
ChainBinTree *InitRoot()
{
ChainBinTree *node;
if (node = (ChainBinTree *)malloc(sizeof(ChainBinTree)))
{
printf("\n输入根结点数据:");
scanf("%s", &node->data);
node->left = NULL;
node->right = NULL;
return node;
}
return NULL;
}
/************************************************************************
函数名称:AddNode
函数功能:向指定的结点添加子节点
函数参数:bt为根结点
函数返回:没有返回值
************************************************************************/
void AddNode(ChainBinTree *bt)
{
ChainBinTree * node, *parent;
DATA data;
char select;
if (node = (ChainBinTree *)malloc(sizeof(ChainBinTree)))
{
printf("\n输入二叉树结点数据:");
fflush(stdin);//清空输入缓冲区
scanf("%c", &node->data);
node->left = NULL;
node->right = NULL;
printf("输入父结点数据:");
fflush(stdin);
scanf("%c", &data);
parent = BinTreeFind(bt, data);
if (!parent)
{
printf("未找到父结点!\n");
free(node);
return;
}
printf("1.添加到左子树\n2.添加到右子树\n");
do
{
select = getchar();
select = select - '0';
if (select == 1 || select == 2)
BinTreeAddNode(parent, node, select);
}while(select != 1 && select != 2);
}
return;
}
/************************************************************************
函数名称:main
函数功能:测试树结构及其操作
函数参数:无
函数返回:0表示成功
************************************************************************/
int main()
{
ChainBinTree *root = NULL;
char select;
//void (*oper1)();
//oper1 = oper;
do
{
system("cls");
printf("1.设置二叉树根元素 2.添加二叉树结点\n");
printf("3.先序遍历 4.中序遍历\n");
printf("5.后序遍历 6.按层遍历\n");
printf("7.二叉树深度 8.清空树\n");
printf("0.退出\n");
select = getchar();
getchar();
switch(select)
{
case '1':
root = InitRoot();
getchar();
getchar();
break;
case '2':
AddNode(root);
getchar();
break;
case '3':
printf("\n先序遍历的结果:");
BinTree_DLR(root, oper);
printf("\n");
getchar();
break;
case '4':
printf("\n中序遍历的结果:");
BinTree_LDR(root, oper);
printf("\n");
getchar();
break;
case '5':
printf("\n后序遍历的结果:");
BinTree_LRD(root, oper);
printf("\n");
getchar();
break;
case '6':
printf("\n按层遍历的结果:");
BinTree_Level(root, oper);
printf("\n");
getchar();
break;
case '7':
printf("\n二叉树的深度为:%d\n", BinTreeDepth(root));
getchar();
break;
case '8':
BinTreeClear(root);
root = NULL;
break;
case '0':
break;
default:
break;
}
}while(select != '0');
BinTreeClear(root);
root = NULL;
getchar();
getchar();
return 0;
}