二叉树
1.二叉树树的定义:
二叉树是一种特殊的树结构,所有的节点度小于或等于2.
2.二叉树的5种基本形态:
- 空二叉树
- 只有一个根节点的二叉树
- 只有左子树的二叉树、
- 只有右子树的二叉树
- 完全二叉数
3.两种特殊的二叉树:
满二叉树:所有的叶节点都在同一层上,若深度为k,则二叉树的节点为2的k次方减一。
完全二叉树:最后一层都存在节点或则右边缺少节点的树
4.二叉树的顺序存储:
对于一个完全二叉树,可以用一个一维数组进行存储,将二叉树按照自上而下,由左向右的顺序进行顺序存储。但对于一般的二叉树而言,就会浪费空间,因此,顺序存储适合完全二叉树。
5.二叉树的链式存储:
链式存储可以有不同的形式,如:二叉链表,三叉链表,双亲链表等,二叉链表最为常用。所以,一下就用二叉链表进行存储。
二叉树的链式存储:
二叉树上的每一个节点分为三个域组成,其中data域为存储的元素的值,lchild作为指针指向该节点的左孩子,rchild为该节点的右孩子节点。
typedef struct node{
char data;
struct node* lchild, * rchild;
}BinTNode,*BiTree;
6.二叉树的遍历:有二叉树的定义可知,每一棵非空子树有根节点(D),根节点的左子树(L),根节点的右子树®组成,因为每次先访问左子树在访问右子树所以自由三种不同的访问方式:DLR(先序遍历),LDR(中序遍历),LRD(后序遍历)。还有一种是按层次遍历是访问根节点,将根节点入队,然后,安顺序取出从队列中的一个节点,并按照其左右孩子节点先左后右分别入队,若队列为空则结束,否则继续执行。
//先序
void Preorder(BinTNode* T)
{
if (T)
{
printf("%c", T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
//中序
void Inorder(BinTNode* T)
{
if (T)
{
Inorder(T->lchild);
printf("%c", T->data);
Inorder(T->rchild);
}
}
//后序
void Postorder(BinTNode* T)
{
if (T)
{
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c", T->data);
}
}
//层次遍历
void Leveorder(BinTNode* T)
{
int front = 0, rear = 1;
BinTNode* cq[Max], * p;
cq[1] = T;
while (front != rear)
{
front = (front + 1) % NodeNum;
p = cq[front]; //出队
printf("%c", p->data); //出队,输出
if (p->lchild != NULL)
{
rear = (rear + 1) % NodeNum;
cq[rear] = p->lchild; //左子树入队
}
if (p->rchild != NULL)
{
rear = (rear + 1) % NodeNum;
cq[rear] = p->rchild; //右子树入队
}
}
}
7.求二叉树的深度:
int TreeDepth(BinTNode* T)
{
int hl, hr, max;
if (T)
{
hl = TreeDepth(T->lchild);
hr = TreeDepth(T->rchild);
max = hl > hr ? hl : hr;
NodeNum = NodeNum + 1;
if (hl == 0 && hr == 0)
leaf = leaf + 1;
return max + 1;
}
else
return 0;
}
8.求叶子节点个数:
int countleaf(BinTNode* T)
{
int hl, hr;
if (T)
{
hl = countleaf(T->lchild);
hr = countleaf(T->rchild);
if (hl == 0 && hr == 0) //若左右深度为0,即为叶子
{
return 1;
}
else
return hl + hr;
}
else
return 0;
}
练习:建立一棵树,先后用先序,中序,后序,层次遍历输出,在求其深度和节点数
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define Max 30 //节点最大个数
typedef struct node {
char data;
struct node* lchild, * rchild;
}BinTNode;
int NodeNum, leaf;
BinTNode* CreatBinTree()
{
BinTNode* T;
char ch;
if ((ch = getchar()) == '#')
{
return NULL;
}
else
{
T = (BinTNode*)malloc(sizeof(BinTNode));
T->data = ch;
T->lchild = CreatBinTree();
T->rchild = CreatBinTree();
return T;
}
}
//先序
void Preorder(BinTNode* T)
{
if (T)
{
printf("%c", T->data);
Preorder(T->lchild);
Preorder(T->rchild);
}
}
//中序
void Inorder(BinTNode* T)
{
if (T)
{
Inorder(T->lchild);
printf("%c", T->data);
Inorder(T->rchild);
}
}
//后序
void Postorder(BinTNode* T)
{
if (T)
{
Postorder(T->lchild);
Postorder(T->rchild);
printf("%c", T->data);
}
}
//求深度
int TreeDepth(BinTNode* T)
{
int hl, hr, max;
if (T)
{
hl = TreeDepth(T->lchild);
hr = TreeDepth(T->rchild);
max = hl > hr ? hl : hr;
NodeNum = NodeNum + 1;
if (hl == 0 && hr == 0)
leaf = leaf + 1;
return max + 1;
}
else
return 0;
}
void Leveorder(BinTNode* T)
{
int front = 0, rear = 1;
BinTNode* cq[Max], * p;
cq[1] = T;
while (front != rear)
{
front = (front + 1) % NodeNum;
p = cq[front]; //出队
printf("%c", p->data); //出队,输出
if (p->lchild != NULL)
{
rear = (rear + 1) % NodeNum;
cq[rear] = p->lchild; //左子树入队
}
if (p->rchild != NULL)
{
rear = (rear + 1) % NodeNum;
cq[rear] = p->rchild; //右子树入队
}
}
}
int countleaf(BinTNode* T)
{
int hl, hr;
if (T)
{
hl = countleaf(T->lchild);
hr = countleaf(T->rchild);
if (hl == 0 && hr == 0) //若左右深度为0,即为叶子
{
return 1;
}
else
return hl + hr;
}
else
return 0;
}
int main()
{
BinTNode* root;
int i;
int depth;
printf("\n");
printf("Creat Bin_Tree Input preorder:");//输入完全二叉树先序序列,#表示虚节点
root = CreatBinTree(); //创建二叉树
do {
printf("\t*********select**********\n");
printf("\t1:Preorder Traversal\n");
printf("\t2:Iorder Traversal\n");
printf("\t3:Postorder Traversal\n");
printf("\t4:PostTreeDepth,Node number,Leaf number\n");
printf("\t5:Level Depth\n");//按层次遍历前,应先选择4,求出该树节点
printf("\t0:Exit\n");
printf("\t*************************\n");
getchar();
scanf_s("%d", &i); //输入菜单号(0-5)
switch (i)
{
case 1:
printf("Print Bin_tree Preorder:");
Preorder(root);//先序遍历
break;
case 2:
printf("Print Bin_tree Inorder:");
Inorder(root);//先序遍历
break;
case 3:
printf("Print Bin_tree Postorder:");
Postorder(root);//先序遍历
break;
case 4:
depth = TreeDepth(root);//求深度以及叶子数
printf("BinTree Depth=%d\nBinTree Node Number=%d\n:", depth, NodeNum);
printf("BinTree Leaf number=%d", countleaf(root));
break;
case 5:
printf("LevePrint Bin_Tree:");
Leveorder(root);//按层次
break;
case 0:
exit(1);
}
printf("\n");
} while (i != 0);
system("pause");
return 0;
}