浅谈树和二叉树
树:非线性结构。一对多的关系。
根节点:没有前驱节点的节点。
叶子节点:没有后继节点的节点。
节点的度:一个节点的子节点个数。
树的度:树中度最大的节点的度。
树的节点个数计算:
满树:一棵度为n,高度为h的满树,其节点个数是:
n^0 + n^1 + n^2 + .......+ n^(n-1) 等比公式
总结点树和叶子节点数的计算:
度 个数
1 n1
2 n2
... ...
d nd
n总 = n1 + 2n2 + 3n3 +.... +d*nd -1
n0 = n总 - (n1 + n2 +n3+.....+nd)
n0 = (1-1)*n1 + (2-1)*n2 +(3-1)*n3 +....+(d-1)*nd + 1 这是树的叶子节点计算公式
度为d,高度为h的树,最多可容纳多少节点:d^0 + d^1 +d^2 +...+d^(n-1)
树的存储结构:(链表特点)
typedef struct TREE_NODE{ //这种普通树不好操作或者极大的浪费空间
void *data; //所以二叉树用的比普通树更广泛
struct TREE_NODE **children; //指向子节点的指针数组,动态数组
int childrenCount;
}TREE_NODE;
上面的存储结构存在两个大的缺陷:1,存储利用率低,
2,节点操作复杂。
其实,可以用“线性存储结构”,表达树:即,用数组存储节点及数据“
typedef struct TREE_NODE{
void *data;
int parentIndex; //父节点下标;
} TREE_NODE;
树的遍历:
队列:
是一种线性结构;具有两个数据操作端,且,总是从一端入;从另一端出;入的端是队尾,出的端是队首。
广度优先遍历:优先将一个节点的所有子节点全部访问完。需要队列的支持。
1.根节点入队列
2.while(队列非空){
3.出队列;
4.访问(输出)
5.将这个节点的所有子节点入队列
}
深度优先遍历:
工具:堆栈
二叉树:二叉树有且仅有一个根节点。
二叉树不同于树的关键定义是:任何一个非叶子节点有最多两个子节点,且,严格区分左右孩子
满二叉树:一棵高度为h的满二叉树的节点总数,一定是2^h - 1个!
满二叉树的第h层的节点总数是:2^(h - 1)
拥有n个节点的满二叉树的高度:最多是[log2(n)],
对于二叉树:n0 = n2 + 1
1.完全二叉树可以用一维数组存储和表示
2.若一棵完全二叉树的某节点存在子节点,那么,该节点编号与其左右孩子节点编号存在下列关系
i leftChild : 2*i + 1
rightChild: 2*i + 2
3.一棵拥有n个节点的完全二叉树,其最后一个(编号最大)非叶子结点的编号是
n / 2-1
4.一棵拥有n个节点的完全二叉树的最后一个非叶子节点,要么有左右孩子,要么只有左孩子!
5.一棵拥有n(n为偶数)个节点的完全二叉树,其最底层叶子节点个数一定是奇数个
个数为in0= n / 2 (满二叉树总节点数总是偶数个,而n为偶数)