C语言基本数据结构之二(二叉树的三种遍历,节点数以及深度算法)
2016-12-05 19:29
661 查看
关于二叉树的定义,网上有比较好的介绍,在这里就简单介绍二叉树的一些性质
2)深度为 h 的二叉树中至多含有 2^h – 1 个结点;
3)若在任意一棵二叉树中,有 n0 个叶子结点,有 n2 个度为 2 的结点,则:n0 = n2 + 1。
特殊形式的二叉树
1)满二叉树
特点:深度为h且含有2h-1个结点的二叉树,为满二叉树。图示满二叉树,结点编号为自上而下,自左而右。
2)完全二叉树(左图)
特点:指深度为k的,有n个结点的,且每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应,完全一致,则为完全二叉树。(右图)
3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为0,-1,1。
用一组连续的存储单元存放二叉树的数据元素。结点在数组中的相对位置蕴含着结点之间的关系。
其所需的存储单元数为:2^h-1= 24-1 = 15,若父结点在数组中i下标处,其左孩子在2*i处,右孩子在2*i+1处。
(2)链式存储结构
链式存储结构的每个结点由数据域、左指针域和右指针域组成。左指针和右指针分别指向下一层的二叉树
放二叉树的数据元素。结点在数组中的相对位置蕴含着结点之间的关系
(2)中序遍历(L D R): 按中序遍历左子树,访问根结点,按中序遍历右子树。
(3)后序遍历(L R D): 按后序遍历左子树,按后序遍历右子树,访问根结点。
还是直接上代码吧~~这里用的是链式存储结构,相对顺序存储结构,前者所需存储容量更小,更易于理解~~
二叉树的结构体
初始化二叉树,添加数据
先序,中序,后序遍历的递归算法(ps:递归真是个好东西~~,写出来的代码就是简洁~~)
二叉树的层次遍历
计算二叉树的深度;
计算总的节点数和叶子数
全部代码如下
大概就这么多了。想起了在补充吧~~
3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为0,-1,1。
二叉树的基本性质
1)二叉树的第i层上至多有 2^(i-1)(i ≥1)个结点;2)深度为 h 的二叉树中至多含有 2^h – 1 个结点;
3)若在任意一棵二叉树中,有 n0 个叶子结点,有 n2 个度为 2 的结点,则:n0 = n2 + 1。
特殊形式的二叉树
1)满二叉树特点:深度为h且含有2h-1个结点的二叉树,为满二叉树。图示满二叉树,结点编号为自上而下,自左而右。
2)完全二叉树(左图)
特点:指深度为k的,有n个结点的,且每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应,完全一致,则为完全二叉树。(右图)
3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为0,-1,1。
关于二叉树的存储方式(顺序和链式存储)
(1) 顺序存储结构用一组连续的存储单元存放二叉树的数据元素。结点在数组中的相对位置蕴含着结点之间的关系。
其所需的存储单元数为:2^h-1= 24-1 = 15,若父结点在数组中i下标处,其左孩子在2*i处,右孩子在2*i+1处。
(2)链式存储结构
链式存储结构的每个结点由数据域、左指针域和右指针域组成。左指针和右指针分别指向下一层的二叉树
放二叉树的数据元素。结点在数组中的相对位置蕴含着结点之间的关系
关于二叉树的三种遍历方式
(1)先序遍历(D L R): 访问根结点,按先序遍历左子树,按先序遍历右子树。(2)中序遍历(L D R): 按中序遍历左子树,访问根结点,按中序遍历右子树。
(3)后序遍历(L R D): 按后序遍历左子树,按后序遍历右子树,访问根结点。
还是直接上代码吧~~这里用的是链式存储结构,相对顺序存储结构,前者所需存储容量更小,更易于理解~~
二叉树的结构体
struct Tree{ int data;//这里可以改成你想要的数据类型 tree *left; tree *right; };
初始化二叉树,添加数据
tree *initTree(tree* H){ H = NULL; int data = 0; printf(" 输入data \n "); scanf("%d",&data); if(data!=0){ H = (tree *)malloc(sizeof(tree)); H->data = data; printf(" t data is %d \n",H->data); printf(" 请输入左字树data \n"); H->left = initTree(H->left); printf(" 请输入右字树data \n"); H->right = initTree(H->right); } return H; }
先序,中序,后序遍历的递归算法(ps:递归真是个好东西~~,写出来的代码就是简洁~~)
/* 先序遍历 */ void DLR(tree* T){ if(NULL!=T){ printf(" data is %5d \n ",T->data); DLR(T->left); DLR(T->right); } } /* 中序遍历 */ void LDR(tree* T){ if(NULL!=T){ LDR(T->left); printf(" data is %5d \n",T->data); LDR(T->right); } } /* 后序遍历 */ void LRD(tree* T){ if(NULL!=T){ LRD(T->left); LRD(T->right); printf(" data is %5d \n",T->data); } }
二叉树的层次遍历
void LOrder(tree* T) /* 层次遍历二叉树T */ { treeQ[MAXNODE]; /* 辅助队列,MAXNODE为最大的队列容量 */ int f,r; /* 队列的首、尾指针 */ if (T == NULL) return; /* 空树,直接返回 */ f = -1; /* 队首,队尾指针初始化 */ r = 0; Q[r] = T; /* 树根进队 */ while( f != r ) { f++; printf(“%d”,Q[f]->data); /* 访问队首结点的数据域 */ if (Q[f]->left!= NULL) /* 将队首结点的左孩子入队列 */ { r++; Q[r] = Q[f]->left; } if (Q[f]->right!= NULL) /* 将队首结点的右孩子入队列 */ { r++; Q[r] = Q[f]->right; } } }
计算二叉树的深度;
/*计算树的深度*/ int deep(tree* H){ int d1 = 0; int d2 = 0; if(NULL!=H){ d1 = deep(H->left) +1; d2 = deep(H->right) +1; } return d1>=d2? d1:d2; }
计算总的节点数和叶子数
//计算总的节点数 int node(tree* H){ int n = 0; if(NULL!=H){ n = node(H->left)+node(H->right) +1; } return n; } //计算叶子节点 int CountLeaf(tree* H){ if(NULL==H) return 0; if((NULL==H->left)&&(NULL==H->right)){ return 1; } return CountLeaf(H->left) + CountLeaf(H->right); }
全部代码如下
#include <stdio.h>
#include <malloc.h>
typedef struct Tree tree ;
/*
定义二叉树的结构体
*/
struct Tree{
int data;
tree *left;
tree *right;
};
tree *p[100];
/*
初始化二叉树
*/
tree *initTree(tree* H){ H = NULL; int data = 0; printf(" 输入data \n "); scanf("%d",&data); if(data!=0){ H = (tree *)malloc(sizeof(tree)); H->data = data; printf(" t data is %d \n",H->data); printf(" 请输入左字树data \n"); H->left = initTree(H->left); printf(" 请输入右字树data \n"); H->right = initTree(H->right); } return H; }
/*
先序遍历
*/
void DLR(tree* H){
if(NULL!=H){
printf(" data is %5d \n ",H->data);
DLR(H->left);
DLR(H->right);
}
}
/*
中序遍历
*/
void LDR(tree* H){
if(NULL!=H){
LDR(H->left);
printf(" data is %5d \n",H->data);
LDR(H->right);
}
}
/*
后序遍历
*/
void LRD(tree* H){
if(NULL!=H){
LRD(H->left);
LRD(H->right);
printf(" data is %5d \n",H->data);
}
}
/*
计算树的深度
*/
int deep(tree* H){
int d1 = 0;
int d2 = 0;
if(NULL!=H){
d1 = deep(H->left) +1;
d2 = deep(H->right) +1;
}
return d1>=d2? d1:d2;
}
//计算总的节点数 int node(tree* H){ int n = 0; if(NULL!=H){ n = node(H->left)+node(H->right) +1; } return n; } //计算叶子节点 int CountLeaf(tree* H){ if(NULL==H) return 0; if((NULL==H->left)&&(NULL==H->right)){ return 1; } return CountLeaf(H->left) + CountLeaf(H->right); }
void main(){
tree *H = (tree*)malloc(sizeof(tree)) ;
H = initTree(H);
printf("DLR : \n");
DLR(H);
printf("LDR : \n");
LDR(H);
printf("LRD : \n");
LRD(H);
printf("\n deep is %5d \n ",deep(H));
printf(" CountLeaf is %5d \n",CountLeaf(H));
printf(" node number is %5d \n",node(H));
}
大概就这么多了。想起了在补充吧~~
3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为3)平衡二叉树
特点:又称AVL树,它或为一棵空树,或具如下性质:其左子树和右子树都是平衡二叉树,且左、右子树的深度之差的绝对值不超过1。左、右子树的深度之差为平衡因子,平衡二叉树的平衡因子只能为0,-1,1。
相关文章推荐
- C语言实现二叉树的基本操作---创建、遍历、求深度、求叶子结点
- 初识树结构,简单模拟无规律的二叉树,实现二叉树的构建,计算树的深度以及三种遍历方式以及搜索删除,销毁整个树
- 八.二叉树各种操作的C语言实现 深度遍历求深度,广度遍历求深度,交换左右子树,求叶子节点数
- 二叉树(1)基本概念以及三种遍历
- 基本数据结构——二叉树的建立,遍历,求叶子节点,深度计算
- C语言实现二叉树的基本操作---创建、遍历、求深度、求叶子结点
- [C/C++] 先序建立二叉树| 先序、中序、后序遍历二叉树| 求二叉树深度、节点数、叶节点数 算法实现
- 二叉树基本算法,递归非递归遍历以及求高度、宽度等
- C语言学习历程(十八) 数据结构二叉树的创建、遍历、深度等算法
- 二叉树基本操作--创建,三种遍历,叶子节点
- c语言实现二叉树先序,中序,后序(递归),层次遍历,求叶子节点个数及树的深度,下一篇写非递归的遍历
- 二叉树的基本操作精集(创建、遍历、求深度结点以及叶子结点个数)
- 由先序遍历序列和中序遍历序列恢复二叉树以及统计叶子节点个数和树的深度
- 某研究院的二叉树深度优先遍历变种的算法面试题以及答案
- 二叉树的深度优先,广度优先,以及层次遍历算法
- 【Python排序搜索基本算法】之二叉树的遍历
- 如何在遍历二叉树的同时,打印出每个节点的深度
- C语言创建二叉树数据结构, 以及各种遍历
- C语言笔试题(16)——二叉树基本算法
- 二叉树 遍历|统计叶子节点|求深度|交换左右子树|查找是否存在某个特定叶子节点练习题