
-
树的一些概念
- 结点: 树中的⼀个独⽴单元. 包含⼀个数据元素及若⼲指向其他⼦树的分⽀. 例如, A,B,C,D等都是结点;
- 结点的度:结点拥有的子树的个数,A的度是3,B的度是2;
- 树的度:所有结点中的度的最大值就是树的度,上图树的度是3;
- 非终端结点:度不为0的结点
- 双亲和孩子:结点的子树称之为该节点的孩子。对应的该结点是孩子的双亲
- 兄弟:双亲相同的结点;
- 祖先:从根到该结点经历的所有结点;
- 子孙:以某结点为根的⼦树中的任⼀结点都称为该结点的⼦树. 例如,B的⼦孙为E,F;
- 层次:结点的层次从根开始定义起, 根为第⼀层, 根的孩⼦为第⼆层. 树中任⼀层次等于双亲结点的层次 加1;
- 堂兄弟:双亲在同一层,并且互相双亲不是同一个结点;
- 有序树和无序树:如果将树的结点的各⼦树看成从左到右是有次序的(即不能互换)则称为该树为有序树, 否则是⽆序树,在有序树中最左边的⼦树的根称为第⼀个孩⼦,最右边的称为最后⼀个孩⼦;
- 结点的高度:结点到叶子结点的最长路径;
- 结点的深度:根结点到该结点经历的边数;
- 结点的层数:结点的深度+1
- 树的高度:根节点到叶子结点的最长路径
-
树结构中的高度、深度以及层数图解


-
二叉树概念
-
二叉树的特性
- ⼆叉树每个结点⾄多只有2颗⼦树(⼆叉树中不存在度⼤于2的结点). 所以⼆叉树中不存在⼤于2的结点. 注意: 不是只有2个⼦树,⽽是最多只有. 如果⼆叉树中没有⼦树或者只有⼀颗树是可以的
- ⼆叉树的⼦树有左右之分,其次序不能任意颠倒
- 即使只有⼀棵树,也需要区分是左⼦树还是右⼦树
-
二叉树的性质
- 在二叉树的第i层上最多有2^(i-1)个结点
- 深度为K的二叉树最多有2k -1 个结点(K>=1)
- 对于任何一颗二叉树T,如果其终端结点数为n0,度为2的结 点数为n2,则n0 = n2 + 1
- 具有n个结点的完全二叉树深度为(log2(n))+1
- 对具有n个结点的完全二叉树,如果按照从上至下和从左至右的顺序对二 叉树的所有结点从1开始编号,则对于任意的序号为i的结点有:
A.如果i>1,那么序号为i的结点的双亲结点序号为i/2;
B.如果i=1,那么序号为i的结点为根节点,无双亲结点;
C.如果2i<=n,那么序号为i的结点的左孩子结点序号为2i;
D.如果2i>n,那么序号为i的结点无左孩子;
E.如果2i+1<=n,那么序号为i的结点右孩子序号为2i+1;
F.如果2i+1>n,那么序号为i的结点无右孩子。
-
满二叉树
所有非终端结点的度都等于2

-
完全二叉树
对⼀颗具有n个结点的⼆叉树按层序编号,如果编号为i(1=< i <= n)的结点与同样深度的满⼆叉树中编号为i 的结点⼆叉树中位置完全相同. 则这颗⼆叉树称为完全⼆叉树.

-
斜树
只有左子树或者右子树的二叉树

-
二叉树的遍历
-
层序遍历
按照树的层依次冲左向右遍历,例如上图的满二叉树的遍历结果是A、B、C、D、E、F、G
-
先序遍历
先打印根结点然后是先序遍历左子树,然后先序遍历右子树(主要是先打印根然后按照左右打印)例如上图的满二叉树的遍历结果是:A、B、D、E、C、F、G
-
中序遍历
通俗的话说找到坐子树的叶子结点,然后找到其双亲按照左孩子双亲右孩子的次序打印,然后打印根节点然后左子树也找上上述规则打印(右根左的次序),例如上图的满二叉树的遍历结果是D、E、B、A、F、C、G
-
后序遍历
一样从左子树开始找到叶子结点依次打印然后打印双亲,依次往上直到双亲为根节点,然后右子树一样按照上述规则遍历,最后打印根节点,例如上图的满二叉树的遍历结果是D、E、B、F、G、C、A
-
二叉树的顺序存储实现
按照层依次从左到右存储,如果碰见当前结点是空节点,但是后续还有结点的情况则当前结点置为空(存储的结构应该按照完全二叉树的结构存储,如没有结点则补上空节点),例如上图中的二叉树的图,顺序存储后的树结构应该是下图
注:顺序存储只适合完全二叉树,其他二叉树会浪费空间
#include <stdio.h>
#include "stdlib.h"
#include "math.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAX_TREE_SIZE 100
typedef int Status;
typedef int ElemType;
typedef struct {
int level;
int order;
}Position;
typedef ElemType Tree[MAX_TREE_SIZE];
ElemType Nil = 0;
Status initTree(Tree T){
for(int i = 0; i < MAX_TREE_SIZE; i ++){
T[i] = Nil;
}
return OK;
}
Status createTree(Tree T){
for(int i = 1; i <= 10; i ++){
T[i-1] = i;
if(i != 0 && T[(i+1)/2-1] == Nil && T[i] == Nil){
printf("二叉树异常");
exit(0);
}
}
return OK;
}
Status TreeEmpty(Tree T){
if(T[0] == Nil) return TRUE;
return FALSE;
}
int TreeDepth(Tree T){
if(TreeEmpty(T)) return ERROR;
int i = MAX_TREE_SIZE - 1;
for(; T[i] == Nil; i --);
int j = 0;
while ((i + 1)/2 -1 >= 0) {
j ++;
i = (i + 1)/2 -1;
}
return j;
}
ElemType value(Tree T, Position p){
int index = pow(2, p.level - 1) - 1 + p.order - 1;
return T[index];
}
ElemType Root(Tree T){
return T[0];
}
Status setValue(Tree T,Position p,ElemType e){
if(TreeEmpty(T)) return ERROR;
int index = pow(2, p.level - 1) - 1 + p.order - 1;
if(T[(index +1)/2 - 1] == Nil) return ERROR;
if(e == Nil && (T[index *2 + 1] != Nil))
T[index] = e;
return OK;
}
ElemType getParent(Tree T, ElemType e){
int i = 0;
for(;i < MAX_TREE_SIZE; i ++){
if(T[i] == e) break;
}
if(i > 0){
if(T[(i + 1)/2 - 1] == Nil) return ERROR;
return T[(i + 1)/2 - 1];
}
return Nil;
}
ElemType getLeftChild(Tree T, ElemType e){
if(TreeEmpty(T)) return ERROR;
int i = 0;
for(;i < MAX_TREE_SIZE; i ++){
if(T[i] == e) {
return T[2*i +1];
}
}
return Nil;
}
ElemType getRightChild(Tree T, ElemType e){
if(TreeEmpty(T)) return ERROR;
int i = 0;
for(;i < MAX_TREE_SIZE; i ++){
if(T[i] == e) {
return T[2*i +2];
}
}
return Nil;
}
ElemType getLeftBrothers(Tree T, ElemType e){
if(TreeEmpty(T)) return ERROR;
int i = 1;
for(;i < MAX_TREE_SIZE; i ++){
if(T[i] == e) {
if(i%2 != 0) return Nil;
else if(T[i-1] == Nil) return Nil;
return T[i-1];
}
}
return Nil;
}
ElemType getRightBrothers(Tree T, ElemType e){
if(TreeEmpty(T)) return ERROR;
int i = 1;
for(;i < MAX_TREE_SIZE; i ++){
if(T[i] == e) {
if(i%2 == 0) return Nil;
else if(i+1 >= MAX_TREE_SIZE) return Nil;
return T[i+1];
}
}
return Nil;
}
#pragma mark -- 二叉树的遍历
void LevelOrderTraverse(Tree T){
if(TreeEmpty(T)) return;
int index = MAX_TREE_SIZE -1;
for(;T[index] == Nil; index --);
for(int i = 0; i <= index; i ++){
printf("%d ",T[i]);
}
}
void PreTraverse(Tree T,int e){
if(TreeEmpty(T)) return;
printf("%d ",T[e]);
if(T[e*2 +1] != Nil)
PreTraverse(T, e*2 +1);
if(T[2*e +2] != Nil)
PreTraverse(T, 2*e +2);
}
void InTraverse(Tree T, int e){
if(TreeEmpty(T)) return;
if(T[e*2 +1] != Nil)
InTraverse(T, e*2 +1);
printf("%d ",T[e]);
if(T[2*e +2] != Nil)
InTraverse(T, 2*e +2);
}
void PostTraverse(Tree T,int e){
if(TreeEmpty(T)) return;
if(T[e*2 +1] != Nil)
PostTraverse(T, e*2 +1);
if(T[2*e +2] != Nil)
PostTraverse(T, 2*e +2);
printf("%d ",T[e]);
}
int main(int argc, const char * argv[]) {
Tree T;
initTree(T);
createTree(T);
printf("层序遍历的结果:");
LevelOrderTraverse(T);
printf("\n");
printf("先序遍历的结果:");
PreTraverse(T,0);
printf("\n");
printf("中序遍历的结果:");
InTraverse(T,0);
printf("\n");
printf("后序遍历的结果:");
PostTraverse(T,0);
printf("\n");
return 0;
}
#include <stdio.h>
#include "string.h"
#include "stdlib.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define Nil ' '
typedef int Status;
typedef char ElemType;
int indexs = 0;
typedef struct TreeNode{
ElemType data;
struct TreeNode *lchild;
struct TreeNode *rchild;
}TreeNode, *Tree;
char *TreeStr = "ABDH#K###E##CFI###G#J##";
Status initTree(Tree *T){
*T = NULL;
return OK;
}
Status DestroyTree(Tree *T){
if(*T == NULL) return OK;
if((*T)->lchild){
DestroyTree(&(*T)->lchild);
}
if((*T)->rchild){
DestroyTree(&(*T)->rchild);
}
free(*T);
*T = NULL;
return OK;
}
void CreateTree(Tree *T){
ElemType data;
if(indexs < (int)strlen(TreeStr)){
data = TreeStr[indexs++];
if(data != '#'){
*T = (Tree)malloc(sizeof(TreeNode));
if(*T == NULL) exit(0);
(*T)->data = data;
CreateTree(&((*T)->lchild));
CreateTree(&((*T)->rchild));
}else{
*T = NULL;
}
}
}
int TreeDepth(Tree T){
if(T == NULL) return ERROR;
int i,j;
if(T->lchild){
i = TreeDepth(T->lchild);
}else{
i = 0;
}
if(T->rchild){
j = TreeDepth(T->rchild);
}else{
j = 0;
}
return i>j ? i+1:j+1;
}
void PreOrderTraverse(Tree T){
if(T == NULL) return;
printf("%c ",T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
void InOrderTraverse(Tree T){
if(T == NULL) return;
InOrderTraverse(T->lchild);
printf("%c ",T->data);
InOrderTraverse(T->rchild);
}
void PostOrderTraverse(Tree T){
if(T == NULL) return;
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf("%c ",T->data);
}
int main(int argc, const char * argv[]) {
printf("Hello, World!\n");
Tree T;
CreateTree(&T);
printf("%d",TreeDepth(T));
printf("\n");
PreOrderTraverse(T);
printf("\n");
InOrderTraverse(T);
printf("\n");
PostOrderTraverse(T);
return 0;
}