1.树的定义
树(Tree)是n(n≥0)个结点的有限集。n=0时称为空树。在任意一颗非空树中;
(1)有且仅有一个特定的称为根(Root)的结点;
(2)当n>1时,其余结点可分为m(m>0)个互不相关的有限集T1、T2、。。。Tm,其中每一个集合本身又是一棵树,并且称为根的子树(SubTree).
2.双亲表示法
#define MAX_TREE_SIZE 100
typedef int TElemType;
typedef struct PTNode
{
TElemType data;
int parent;
}PTNode;
typedef struct
{
PTNode nodes[MAX_TREE_SIZE];
int r, n;
}PTree;
3.孩子表示法
#define MAX_TREE_SIZE 100
typedef struct CTNode
{
TElemType child;
struct CTNode *next;
}*ChildPtr;
typedef struct
{
TElemType data;
ChildPtr firstChild;
}CTBox;
typedef struct
{
CTBox nodes[MAX_TREE_SIZE];
int r,n //根的位置和结点数
}CTree;
4.二叉树建立以及前序、中序、后序排列代码
二叉树的建立可以按照前序、后序、中序来生成,我们这里用前序。
1.二叉树建立代码(用#代替空结点)
typedef char TElemType;
typedef struct BiTNode
{
TElemType data;
BiTNode *rChild,*lchild;
}BiTNode,*BiTree;
void CreateBiTree(BiTree *T) //建立二叉树
{
TElemType ch;
cin >> ch;
if (ch == '#')
{
*T = nullptr;
return;
}
else
{
*T = (BiTree)malloc(sizeof(BiTNode)); //虽然该函数形参是一个指向BiTree指针类型的指针,但是并没有为其指针指向的BiTree类型变量分配地址,所以在这里要动态分配地址
if (!(*T))
throw new exception("无法分配空间");
(*T)->data = ch;
CreateBiTree(&((*T)->lChild));
CreateBiTree(&((*T)->rChild));
}
}
2.前序遍历代码
void PreOrderTraverse(BiTree T) //前序
{
if (T == nullptr)
return;
cout << T->data;
PreOrderTraverse(T->lChild);
PreOrderTraverse(T->rChild);
}
3.中序遍历代码
void InOrderTraverse(BiTree T) //中序
{
if (T == nullptr)
return;
InOrderTraverse(T->lChild);
cout << T->data;
InOrderTraverse(T->rChild);
}
4.后序遍历代码
void PostOrderTraverse(BiTree T) //后序
{
if (T == nullptr)
return;
PostOrderTraverse(T->lChild);
PostOrderTraverse(T->rChild);
cout << T->data;
}
5.测试代码
int main()
{
BiTree *n = new BiTree;
cout << "输入结点数据:";
CreateBiTree(n);
cout << "输出结点数据:"<<endl;
cout << "前序:";
PreOrderTraverse(*n);
cout << '\n';
cout << "中序:";
InOrderTraverse(*n);
cout << '\n';
cout << "后序:";
PostOrderTraverse(*n);
cout << '\n';
}
6.输出结果
如果输入树结点顺序为AB#D##C##,则输出结果如图所示:
说明程序是正确无误的。
5.线索二叉树代码
/*线索二叉树线索化*/
typedef enum {Link,Thread}PointerTag;
typedef struct BiThrNode
{
TElemType data; //结点数据
BiThrNode *lchild, *rchild; //左右子结点
PointerTag LTag;
PointerTag RTag; //左右标志
}BiThrNode,*BiThrTree;
/*中序遍历线索化的递归函数代码*/
void InThreading(BiThTree p)
{
if (p)
{
InThreading(p->lchild);//递归左子树线索化
if (!p->lchild)
{
p->LTag = Thread; //前驱线索
p->lchild = pre; //左孩子指针指向前驱
}
if (!pre->rchild)
{
pre->RTag = Thread; //后驱线索
pre->rchild = p;
}
pre = p;
InThreading(p->rchild); //递归右子树线索化
}
}
/*遍历*/
Status InOrderTraverse_Thr(BiThrTree T)
{
BiThrTree p;
p = T->lchild;
while (p != T)
{
while (p->LTag = Link)
p = p->lchild;
cout << p->data<<endl;
while (p->RTag = Thread && p->rchild != T)
{
p = p->rchild;
cout << p->data;
}
p = p->rchild;
}
return true;
}
6.哈夫曼树
哈夫曼树算法描述
1.根据给定的n个权值(W1,W2,Wn)构成n棵二叉树的集合F={T1,T2,…Tn},其中每棵二叉树Ti中只有一个带权为Wi根节点,其左右子树均为空。
2.在F中选取两棵根节点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根节点的权值为其左右子树上根节点的权值之和。
3.在F中删除这两棵树,同时将新得到的二叉树加入F中。
4.重复2和3步骤,直到F只含一棵树为止。这棵树便是哈夫曼树。