树(tree)是n(n>=0)个结点的有限集,它或为空树(n=0);或为非空树,对于非空树T:
(1)有且仅有一个称之为根的结点;
(2)除根以外的其余结点可分为m(m>0)个互不相交的有限集T1,T2,…,Tm,其中每一个集合本身又是一棵树,并且称为根的子树。
树的结构定义是一个递归的定义,即在树的定义中又用到树的定义,它道出了树的固有特性。
下面介绍一些树形结构中的基本术语。
二叉树是n个结点所构成的集合,它或为空树(n=0);或为非空树,对于非空树T:
(1)有且仅有一个称之为根的结点;
(2)除根以外的其余结点可分为2个互不相交的有限集T1和T2,分别称为T的左子树和右子树,且T1和T2本身又都是二叉树。
二叉树与树一样具有递归性质,二叉树与树的区别主要有以下几点:
(1)二叉树每个结点至多只有两棵子树(即二叉树中不纯在度大于2的结点);
(2)二叉树的子树有左右之分,其次序不能任意颠倒。
满二叉树与完全二叉树是二叉树的两种特殊形态。
定义:满二叉树是深度为k且含有 2的k次方 - 1 个结点的二叉树。
满二叉树的特点是:每一层上的结点数都是最大结点数,即每一层i的结点数都具有最大值 2的(i-1) 个。
可以对满二叉树的结点进行连续编号,约定编号从根结点起,自上而下,自左至右。由此可引出完全二叉树的定义。
定义:如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。
(或深度为k的,有n个结点的二叉树,且其每个结点都与深度为k的满二叉树中编号从1至n的结点一一对应)
完全二叉树的特点是:
(1)叶子结点只可能在层次最大的两层上出现;
(2)对任一结点,若其右分支下的子孙的最大层次为l,则其左分支下的子孙的最大层数必为l或l+1。
前序遍历(前根遍历):根——>左——>右
中序遍历(中根遍历):左——>根——>右
后序遍历(后根遍历):左——>右——>根
层序遍历:按照层次遍历
通过前(或后)序遍历和中序遍历的结果我们可以完全确定一个二叉树
而通过前序遍历和后序遍历的结果我们不一定能够确定一个二叉树
(这里不再证明)
#define Status int
#define MAXSIZE 100
//二叉树的链表存储形式
typedef string TElemType;
typedef struct BiNode
{
TElemType data; //结点数据域
struct BiNode* lchild, * rchild; //左右孩子指针
} BiTNode, * BiTree;
Status InitBiTree(BiTree& T,string str)//构造空二叉树T( 先序序列)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
string ch;
cin >> ch;
if (ch == str)
T = NULL; //递归结束,建空树
else
{
T = new BiTNode;
T->data = ch; //生成根结点
InitBiTree(T->lchild,str); //递归创建左子树
InitBiTree(T->rchild,str); //递归创建右子树
}
return 1;
}
Status ClearNode(BiTNode *T)//清除叶子
{
delete T;
return 1;
}
Status ClearBiTree(BiTree &T)//将二叉树清为空树(差根结点
{
if (T->lchild != NULL&& T->rchild != NULL)
{
if (T->lchild != NULL)
ClearBiTree(T->lchild);
if (T->rchild != NULL)
ClearBiTree(T->rchild);
}
else
ClearNode(T);
return 1;
}
Status DestroyBiTree(BiTree &T)//销毁二叉树(需上面那个递归函数
{
ClearBiTree(T);
ClearNode(T);
T = NULL;
return 1;
}
bool BiTreeEmpty(BiTree T)//若T为空二叉树,返回1
{
if (T!=NULL)
return 0;
else
return 1;
}
int BiTreeDepth(BiTree T)//返回二叉树深度
{
int m, n;
if (T == NULL)
return 0; //如果是空树,深度为0,递归结束
else
{
m = BiTreeDepth(T->lchild); //递归计算左子树的深度记为m
n = BiTreeDepth(T->rchild); //递归计算右子树的深度记为n
if (m > n)
return (m + 1); //二叉树的深度为m 与n的较大者加1
else
return (n + 1);
}
}
BiTNode *ROOT(BiTree& T)//返回根结点
{
BiTNode *p = T;
return p;
}
BiTNode *Value(BiTree T, TElemType e)//返回值为e的结点
{
BiTree Q[MAXSIZE];
int front = 0, rear = 0;
BiTree p;
if (T)
{
Q[rear] = T;
rear++;
while (front != rear)/*队列不空*/
{
p = Q[front];/*出队*/
front = (front + 1) % MAXSIZE;
if (p->data == e)/*如果找到*/
return p;
if (p->lchild)/*左树入队*/
{
Q[rear] = p->lchild;
rear = (rear + 1) % MAXSIZE;
}
if (p->rchild)/*右树入队*/
{
Q[rear] = p->rchild;
rear = (rear + 1) % MAXSIZE;
}
}
}
return NULL;
}
void Assign(BiTree T, TElemType e, TElemType value)//结点e赋值为value
{
BiTNode *p= Value(T, e);
p->data = value;
return;
}
BiTNode *arent(BiTree T, TElemType e)//返回双亲,否则返回空
{
BiTNode* p;
if (T->lchild != NULL)
if (T->lchild->data == e)
return T;
if (T->rchild != NULL)
if (T->rchild->data == e)
return T;
if (T->lchild != NULL)
{
p = arent(T->lchild, e);
if(p!=NULL)
return arent(T->lchild, e);
}
if (T->rchild != NULL)
{
p = arent(T->rchild, e);
if (p!=NULL)
return arent(T->rchild, e);
}
return NULL;
}
BiTNode *LeftChild(BiTree T, TElemType e)//返回左孩子,否则返回空
{
BiTNode* p = Value(T, e);
return p->lchild;
}
BiTNode *RightChild(BiTree T, TElemType e)//返回右孩子,否则返回空
{
BiTNode* p = Value(T, e);
return p->rchild;
}
void PreOrderTraverse(BiTree T)//先序遍历
{
if (T == NULL) { return; }
cout << T->data << ",";// 当前节点
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
void InOrderTraverse(BiTree T)//中序遍历
{
if (T == NULL) { return; }
InOrderTraverse(T->lchild);
cout << T->data << ",";// 当前节点
InOrderTraverse(T->rchild);
}
void PostOrderTraverse(BiTree T)//后序遍历
{
if (T == NULL) {return;}
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
cout << T->data << ",";// 当前节点
}
剩下的还有一些关于森林转换二叉树、哈夫曼树和哈夫曼编码的知识点,但是我已经肝到神志不清了。。。下次一定,下次一定好吧