树
基本定义
- Tree,是n(n≥0)个结点的有限集合。树有且仅有一个特定的称为根root的结点,当n>1时,除根结点的其余结点被分成m(m>00)个不相交的有限集合T1,T2,…,Tm,其中每一个集合又是一棵树,并称为这个根结点的子树。
- 某结点所拥有子树的个数称为该结点的度,树中各结点度的最大值称为该树的度
- 度为零的结点称为以叶子结点,度不为零的结点称为分支结点
- 某结点的子树的根节点称为该结点的孩子结点,该结点称为其孩子结点的双亲结点
- 规定根节点的层数为1,对其余任何结点,若结点在k层,则其孩子结点在第k+1层;树中所有结点的最大层数称为树的深度
- m(m≥0)棵互不相交的树的集合构成森林
存储结构
-双亲表示法
const int MaxSize = 10;
typedef int DataType;
typedef struct
{
DataType data;
int parent;
} PNode;
typedef struct
{
PNode Data[MaxSize];
int treeNum;
} PTree;
- 孩子表示法
const int MaxSize = 10;
typedef int DataType;
typedef struct CTNode // 定义孩子结点
{
int child;
struct CTNode *next;
} CTNode;
Typedef struct // 定义表头结点
{
DataType data;
CTNode *firstchild;
} CBNode;
typedef struct // 定义孩子表示法
{
CBNode data[MaxSize];
int treeNum;
} CTTree;
- 孩子兄弟表示法
typedef int DataType;
typedef struct TNode
{
DataType data;;
struct Tnode *firstchild, *rightsib;
} Tnode;
遍历
- 前序遍历:访问根节点,按照从左到右的顺序遍历根结点的每一棵子树
- 后序遍历:按照从左到右的顺序遍历根结点的每一棵子树,访问根结点
- 层序遍历:广度遍历,从第一层(根结点)开始,自上而下逐层遍历,同一层按照从左到右的顺序遍历
二叉树
基本定义
- binary tree,是n(n≥0)个结点的有限集合,该集合或为空集或者有一个根结点和两棵互不相交的、分贝称为根节点的左子树和右子树的二叉树组成
- 每个结点最多有两棵树,二叉树中不存在度大于2的结点
- 二叉树的左右子树不能颠倒,必须指明左右
- 所有结点都只有左子树的二叉树称为左斜树,所有结点都只有右子树的二叉树称为右斜树
- 在一棵二叉树中,如果所有的分支都存在左子树和右子树,并且叶子节点都在同一层上,这样的二叉树称为满二叉树
- 对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中的位置完全相同,则这棵二叉树称为完全二叉树
基本性质
- 二叉树的第i层上最多有2^(i-1)个结点(i≥1)
- 在一棵深度为k的二叉树中,最多有2^k-1个结点
- 在一棵二叉树中,如果叶子结点的个数为n0,度为2的结点的个数n2,则n0 = n2 + 1
- 具有n个结点的完全二叉树的深度为log2(n) + 1
顺序存储结构
- 按照完全二叉树进行程序编号,使用一维数组进行存储,并不是很常用
const int MaxHigh = 10;
typedef int DataType;
typedef struct
{
DataType data[2^MaxHigh - 1];
int biTreeNum;
} SeqBiTree;
二叉链表
- 一般会采用的存储方式。
- 基本思想:令二叉树的每个结点对对应一个链表的结点,链表结点除了存放二叉树结点的数据信息外,还要设置指示左右孩子的指针。
- 存储结构
typedef int DataType;
typedef struct BiNode
{
DataType Data;
struct BiNode *lchild, *rchild;
} BiNode, *root;
- 遍历
// 前序遍历
void PreOrder(BiNode *root)
{
if(root == NULL)
return;
else {
printf(root->data);
PreOrder(root->lchild);
PreOrder(root->rchild);
}
}
// 后序遍历
void PostOrder(BiNode *root)
{
if(root == NULL)
return;
else {
PreOrder(root->lchild);
PreOrder(root->rchild);
printf(root->data);
}
}
// 层序遍历,使用队列Q
void LevelOrder(BiNode *root)
{
front=rear = -1;
if(root == NULL)
return;
Q[++rear] = root;
while( front != rear ) {
q = Q[++front];
printf(q->data);
if (q->lchild != NULL )
Q[++rear] = q->lchild;
if (q->rchild != NULL )
Q[++rear] = q->rchild;
}
}
- 建立算法
// pre[n]、pin[n]中分别保存二叉树的前序序列和中序序列
// pos(x, pin, i)返回数组pin中从第i个元素开始等于x的位置
BiNode* Create(BiNode *root, int i1, int i2, int k)
{
if(K <= 0)
root = NULL;
else {
root = (BiNode *)malloc(sizeof(BiNode));
root->data = pre[i1];
m = pos(pre[i1], pin, i2);
leftlen = m - i2;
rightlen = k - (leftlen + 1);
root->lchild = Creat(root->lchild, i1+1, i2, leftlen);
root->rchild = Creat(root->rchild, i1+leftlen+1, i2, rightlen);
}
return root;
}
三叉链表
- 在二叉链表的基础上,增加一个parent域来指向该节点的双亲结点
哈弗曼树和哈弗曼编码
基本定义
- huffman tree,给定一组具有确定权值的叶子节点
todo