数据结构 树

来源:互联网 发布:linux http代理服务器 编辑:程序博客网 时间:2024/06/05 03:59

1、节点拥有的子树数称为节点的度(degree)。度为0的节点称为叶节点(leaf)或终端节点;

度不为0的节点称为非终端节点或分支节点。除根节点之外,分支节点也称为内部节点。树的度是

树内各节点的度的最大值。

2、节点间关系:节点的子树的根称为该节点的孩子(child),该节点称为孩子的双亲(parent)。

同一个双亲的孩子间互称兄弟(Sibling)。节点的祖先是从根到该节点所经分支上的所有节点。

以某节点为根的字数中任意节点都称为该节点的子孙。。。。。。

3、节点的层次:从根开始定义,根为第一层,根的孩子为第二层,根的孩子的孩子在第三层,

以此类推……树中节点的最大层次称为树的深度或高度。如果将树中节点的各子树看成从左至右是

有次序的不能交换的,则称该树是有序树,否则称为无序树。森林是m(m>=0)棵不想交的

树的集合;对树中每个节点而言,其子树的集合即为森林。

/*********双亲表示法**********//*树的双亲表示法节点结构定义*/const MaxTreeSize 100typedef int telmtp;//树节点的数据类型typedef struct PTNode//节点结构{telmtp data;//节点数据int parent;//双亲位置(指针)}PTNode;typedef struct//树结构{PTNode nodes[MaxTreeSize];//节点数组int r,n;//根的位置和节点数}PTree;/*********孩子表示法**********///也称为多重链表表示法/*树的孩子表示法结构定义*/const MaxTreeSize 100typedef struct CTNode//孩子节点{int child;struct CTNode *next;}*ChildPtr;typedef struct //表头结构{telmtp data;ChildPtr firstchild;}CTBox;typedef struct//树结构{CTBox nodes[MaxTreeSize];//节点数组int r,n;//根的位置和节点数}CTree;/*******孩子兄弟表示法*******///设置两个指针,分别指向该节点的第一个孩子和此节点的右兄弟typedef struct CSNode{telmtp data;struct CSNode *firstchild,*rightsib;}CSNode,*CSTree;

4、二叉树

· 每个节点最多有两棵子树,所以二叉树中不存在度大于2的节点

· 左子树和右子树是有顺序的,次序不能任意颠倒。

· 即使树中某节点只有一颗子树,也要区分是左子树还是右子树。

· 斜树:所有节点都只有左子树的称为左斜树,所有节点都只有右子树的称为右斜树,统称斜树

· 满二叉树:所有节点都有两颗子树,除叶节点。

· 完全二叉树:节点序号连续(从左到右,到最后一层次最后一节点,只有左叶节点或者有两叶节点,不可能只有右节点)。

二叉树的性质:

①二叉树在第 i 层上至多有2^(i-1)个节点。

②深度为 k 的二叉树最多有2^k-1个节点。

③对于任何一棵二叉树,端节点总数为n0,度为2的节点数为n2,则n0=n2+1

④具有n个节点的完全二叉树深度为[log(2)n+1].

⑤如果对一刻有n个节点的完全二叉树(其深度为[log(2)n+1])的节点按层序编号

(从第一层到第[log(2)n]+1层,每层从左到右),对任一节点i(1<=i<=n)有:

· 如果i=1,则节点i是二叉树的根;如果i>1,其双亲为节点[i/2]。

· 如果2i>n,则节点i无左孩子(节点i为叶子节点);否则其左孩子是节点2i。

· 如果2i+1>n,则节点i无右孩子;否则其右孩子是节点2i+1。

/*******二叉树的存储结构*******//*顺序存储结构*///该结构一般用于完全二叉树,不然有些极端的二叉树会造成空间浪费。。。。。。。。。。。。。这个。。就是把二叉树各节点用数组表示出来。。。/*二叉链表*///二叉树的二叉链表节点结构定义typedef struct BiTNode//节点结构{telmtp data;//节点数据struct BiTNode *lchild,*rchild;//左右孩子指针}BiTNode,*BiTree;


5、遍历二叉树
指的是从根节点出发,按照某种次序依次访问二叉树中所有节点,使得每个节点被访问一次
且仅被访问一次。
①前序遍历:规则是若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树。
//前序遍历第归算法void preOrderTraverse(BiTree T){if(T==NULL)return;printf("%c",T->data);//显示节点数据,可以更改为其它对节点操作、preOrderTraverse(T->lchild);//再先序遍历左子树preOrderTraverse(T->rchild);//最后先序遍历右子树}
②中序遍历:规则是若树为空,则空操作返回,否则从根节点开始,中序遍历根节点左子树,然后是访问根节点,最后中序遍历右子树。
//中序遍历第归算法void InOrderTraverse(BiTree T){if(T==NULL)return;InOrderTraverse(T->lchild);//中序遍历左子树printf("%c",T->data);//显示节点数据,可以更改为其它对节点的操作InOrderTraverse(T->rchild;)//最后中序遍历右子树}
③后序遍历:若树为空,则空操作返回,否则从左到右先叶子后节点方式遍历访问左右子树,最后访问根节点。
//后序遍历算法void PostOrderTraverse(BiTree T){if(T==NULL)return;PostOrderTraverse(T->lchild);//先后序遍历左子树PostOrderTraverse(T->rchild);//再后序遍历右子树printf("%c",T->data);//显示节点数据,可以更改为其它对节点的操作}
④层序遍历:若树为空,则空操作返回,否则从树的第一层,从上而下逐层遍历,同一层中,按从左到右顺序对节点逐个访问。

6、二叉树的建立

void CreteBiTree(BiTree *T){telmtp ch;scanf("%c",&ch);if(ch=='#')*T=NULL;else{*T=(BiTree)malloc(sizeof(BiTNode));if(!*T)exit(OVERFLOW);(*T)->data=ch;//生成根节点CreateBiTree(&(*T->lchild));//构造左子树CreateBiTree(&(*T->rchild));//构造右子树}}
7、线索二叉树
把指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树就称为线索二叉树。线索二叉树不仅节省了空间还可以减少遍历数,降低时间复杂度。
/*二叉树的二叉线索存储结构定义*///Link==0表示指向左右孩子指针//Thread==1表示指向前驱或者后继的线索//二叉线索存储节点结构typedef enum{Link,Thread} PointerTag;typedef struct BiThrNode//二叉线索存储节点结构{telmtp data;//节点数据struct BiThrNode *lchild,*rchild;//左右孩子指针PointerTag LTag;PointerTag TTag;//左右标志}BiThrNode,*BiThrTree;/*例子:中序遍历线索化递归函数*/BiThrTree pre;//全局变量,始终指向刚刚访问过的节点//中序遍历进行中序线索化void InThreading(BiThrTree p){if(p){InThreeding(p->lchild);//第归左子树线索化if(!p->lchild)//没有左孩子{p->LTag=Thread;//线索前驱p->lchild=pre;//左孩子指针指向前驱}if(!pre->rchild)//前驱没有右孩子{pre->RTag=Thread;//后继线索pre->rchild=p;//前驱右孩子指针指向后继(当前节点p)}pre=p;InThreading(p->rchild);//递归右子树线索化}}
8、树转化为二叉树
①、所有兄弟节点之间加一条线
②、只保留连接的横线和长子的线
③、树自然下垂
森林转化为二叉树
①每棵树转化为二叉树
②第一棵树不动,从第二棵树开始,依次把后一根二叉树作为第一棵二叉树的右孩子,
用线连接起来,所有二叉树连接起来得到由森林转化的二叉树。
二叉树转换为树
①加线,左孩子的n个右孩子节点都作为此节点的孩子。将该节点与这些右孩子节点用线连接起来。
②去线:删除原二叉树中所有节点与其右孩子节点的连线。
③层次调整。。。自然下垂。。
二叉树转化为森林
①去线:从根节点寻找右孩子去线
②连线:把去线后的几个二叉树的右孩子连到新分出来的根节点还原。
9、赫夫曼树及其应用
……再见。


0 0