树
静态查找
顺序查找
typedef struct LNode *List
struct LNode{
ElementType Element[MAXSIZE];
int length;
};
int SequentialSearch(List Tb1, ElementType K)
{
int i;
Tb1->Element[0] = K; //建立哨兵
for(i = Tb1->length; Tb1->Element[i]!=K;i--); //从最后一个元素还是向前查找,找到时终止循环
return i; //此时i即为查找元素所在下标
}
//因为我们设置第1个元素为K,在事先判断过第一个元素不是K的情况下,如果最终返回值是0,说明遭遇哨兵,未找到K元素
树的定义
树:n(n>=0)个结点构成的有限集合
当n=0时,称为空树
对于任何一棵非空树,具备以下性质
- 树中有一个称为**“根”**的特殊结点,用 r 表示
- 其余结点可分为m(m>0)个互不相交的有限集,其中每个集合本身又是一棵树,称为原来树的**“子树”**
字树是不相交的
除了根结点外,每个结点有且仅有一个父节点
一棵N个结点的树有N-1条边
树的基本术语
- 结点的度:结点的子树个数
- 树的度:树的所有结点中最大的度数
- 叶结点:度为0的结点
- 父结点:有子树的结点是其子树根结点的父结点
- 子结点:与父结点相对应,也称为孩子结点
- 兄弟结点:具有同一父结点的各结点彼此是兄弟结点
- 路径与路径长度:从结点n1到结点nk的路径为一个结点序列n1,n2…nk,ni是n(i+1)的父结点。路径所包含边的个数即为路径长度
- 祖先结点:沿树根到某一结点路径上的所有结点都是这个结点的祖先结点
- 子孙结点:某一结点的子树中所有结点是这个结点的子孙
- 结点的层次:规定根结点在第1层,其他任一结点的层数是其父结点的层数加1
- 树的深度:树中所有结点中最大层次是这棵树的深度
树的表示
儿子-兄弟表示法即二叉树
二叉树
定义:一个有穷的结点集合,集合可以为空
若不为空,则它是由根结点和称为其左子树和右子树的两个不相交的二叉树组成
特殊二叉树
- 斜二叉树:相当于链表
- 满二叉树(完美二叉树
- 完全二叉树:与满二叉树编号一致,但可以缺少
二叉树的重要性质
- 一个二叉树第i层的最大结点数为:2^(i-1),i>=1
- 深度为k的二叉树有最大结点总数为:2^k-1, k>=1
- 对任何非空二叉树T,若n0表示叶结点个数,n2是度为2的非叶结点个数
那么两者关系满足n0=n2+1
二叉树的存储结构
顺序存储结构
适用于完全二叉树
- 非根结点的父结点的序号是i/2
- 结点的左孩子结点的序号为2i,右孩子为2i+1
若2i<=n,则没有左孩子,2i+1<=n则没有右孩子
一般二叉树也可以用顺序存储结构,但会浪费空间
链式存储结构
struct TreeNode{
ElementType Data;
BinTree Left
BinTree Right;
}
typedef struct TreeNode *BinTree;
typedef BinTree Position;
二叉树的遍历
先序遍历
遍历过程:
- 访问根结点
- 先序遍历其左子树
- 先序遍历其右子树
void PreOrderTraversal(BinTree BT)
{
if(BT) {
printf("%d", BT->Data);
PreOrderTraversal( BT->Left);
PreOrderTraversal( BT->Right);
}
}
中序遍历
void PreOrderTraversal(BinTree BT)
{
if(BT) {
PreOrderTraversal( BT->Left);
printf("%d", BT->Data); //改变了打印结点数据的位置
PreOrderTraversal( BT->Right);
}
}
后序遍历
void PreOrderTraversal(BinTree BT)
{
if(BT) {
PreOrderTraversal( BT->Left);
PreOrderTraversal( BT->Right)