Data Structure---BinaryTree

来源:互联网 发布:苹果一键开启蜂窝数据 编辑:程序博客网 时间:2024/06/06 10:52

二叉树的存储结构

树中,结点数=所有结点的度数+1,即 N0+...+Nm=mi=0ini
非空二叉树中,叶子结点数=度为2的结点数+1,即 N0=N2+1

顺序存储结构

用一组地址连续的存储单元依次从上而下、从左至右存储完全二叉树的结点元素,将完全二叉树编号为i的结点元素存储在某个数组下标为i-1的分量中,适合完全二叉树和满二叉树

链式存储结构

用一个链表来存储一棵二叉树,二叉树中每个节点用链表的一个链结点存储;二叉链表至少包含三个域(数据域data,左指针域lchild,右指针域rchild),含有n个结点的二叉链表含有n+1个空链域

//二叉树的链式存储结构定义typedef struct BiTNode{    ElemType data;    struct BiTNode *lchild,*rchild;} BiTNode,*BiTree;

二叉树的基本操作

二叉树的历遍

由NLR/LRL/Level+LNR可唯一确定一棵BiTree

PreOrder
//NLR递归实现void PreOrder(BiTree T){    if(T != NULL){        visit(T);        PreOrder(T->lchild);        PreORder(T->rchild);    }}
InOrder
//LNR递归实现void InOrder(BiTree T){    if(T != NULL){        InOrder(T->lchild);        visit(T);        InOrder(T->rchild);    }}
//LNR非递归实现,借助一个栈先后扫描左右结点void InOrder2(BiTree T){    InitStack(S);   //初始化Stack    BiTree p=T;     //p是历遍指针    while(p || !isEmpty(S)){        if(p){            Push(S,p);            p=p->lchild;        } else{            Pop(S,p);            visit(p);            p=p->rchild;        }    }}
PostOrder
//LRN递归实现void PostOrder(BiTree T){    if(T != NULL){        PostOrder(T->lchild);        PostOrder(T->rchild);        visit(T);    }}
LevelOrder
//层次历遍,借助一个队列按层序依次入队void LevelOrder(BiTree T){    InitQueue(Q);   //初始化Queue    BiTree p;    EnQueue(Q,p);    while(!isEmpty(Q)){        DeQueue(Q,p);        visit(p);        if(p->lchild != NULL){            EnQueue(Q,p->ichild);        }        if(p->rchild != NULL){            EnQueue(Q,p->rchild);        }    }}

线索二叉树

线索二叉树的存储结构

利用空链域加快查找结点前驱和后继,五个域(ltag, lchild, data, rchild, rtag),将空的lchild指向前驱结点,将空的rchild指向后继结点;ltag域表示线索情况时为1

//线索二叉树存储结构定义typedef struct ThreadNode{    ElemType data;    struct ThreadNode *lchild,*rchild;    int ltag,rtag;  //左右线索标志}THreadNode,*ThreadTree;
线索二叉树的构造

二叉树线索化–历遍二叉树中修改空指针,包括本结点p左指针和前驱结点pre右指针

//LNR递归建立中序线索二叉树void CreateInThread(ThreadTree T){    ThreadTree pre=NULL;    if(T != NULL){        InThread(T,pre);    //线索化二叉树        pre->rchild=NULL;        pre->rtag=1;    }}void InThread(ThreadTree &p,ThreadTree &pre){    if(p != NULL){        InThread(p->lchild,pre);        if(p->lchild==NULL){            p->lchild=pre;  //p指向当前结点            p->ltag=1;        }        if(pre!=NULL && pre->rchild==NULL){            pre->rchild=p;  //pre指向前驱结点            pre->rtag=1;        }        pre=p;              //标记当前结点为访问过的结点        InThread(p->rchild,pre);    }}
不含头结点的线索二叉树的历遍
//求中序线索二叉树中序序列下的第一个结点ThreadNode *FirstNode(ThreadNode *p){    while(p-ltag==0){        p=p->lchild;    }    return p;}//求中序线索二叉树中结点p在中序序列下的后继结点ThreadNode *NextNode(ThreadNode *p){    if(p->rtag==0){        return FirstNode(p->rchild);     } else {        return p->rchild;       }}//不含头结点的中序线索二叉树的中序历遍算法void InOrder(ThreadNode *T){    for(ThreadNode *p=FirstNode(T);p!=NULL;p=NextNode(p)){        visit(p);    }}

二叉树的应用

Binary-Sorting-Tree(BST)

二叉排序树,二叉查找树,一种递归数据结构
左子树结点值<根结点值<右子树结点值,对BST进行中序遍历,可得到一个递增的有序序列

//BST非递归查找算法BSTNOde *BST_Search(BiTree T,ElemType key,BSTNode *&p){    p=NULL;    while(T!=NULL && key!=T->data){        p=T;    //p指向被查找结点的双亲,用于插入删除操作        if(key<T->data){            T=T->lchild;        } else{            T=T-rchild;        }    }    return T;}
BST-Insert
//BST递归插入算法,插入的新结点一定是某个叶结点,O(H)int BST_Insert(BiTree &T,KeyType k){    if(T==NULL){        T=(BiTree)malloc(sizeof(BSTNode));        T->key=k;        T->lchild=T->rchild=NULL;        return 1;    } else if(k=T->key){        return 0;    } else if(k<T->key){        return BST_Insert(T->lchild,k);    } else if(k>T->key){        return BST_Insert(T->rchild,k);    }}
BST-Create
//BST构造,判定树不唯一,相同的关键字插入顺序不同则生成结果也可能不同void Creat_BST(BiTree &T,KeyType str[],int n){    T=NULL;    int i=0;    while(i<n){        BST_Insert(T,str[i]);        i++    }}
BST-Delete

左右子树均不空,在右子树上找中序第一个子女填补,转换为删除该结点,O(H)

AVL-Tree

平衡二叉树–任意结点左右子树高度差的绝对值不超过1,平均查找长度O(log2n)
四种插入方式:LL/RR平衡旋转(右单/左单旋转),LR/RL平衡旋转(先左后右/先右后左双旋转)

Huffman-Tree

某一根结点的带权路径长度–树中根结点到任意结点的路径长度与该结点上权值的乘积,树的带权路径长度 WPL=ni=1wili
哈夫曼树–最优二叉树,在含N个带权叶子结点的二叉树中WPL最小的二叉树
前缀编码–没有一个编码是另一个编码的前缀,如0、101、100
利用Huffman树可设计出总长度最短的二进制前缀编码,各Huffman树的带权路径长度相同且为最优

树和森林

树的存储结构

双亲表示法、孩子表示法、孩子兄弟表示法

双亲表示法

采用一组连续存储空间存储每个结点,每个节点增设一个伪指针指示双亲结点在数组中的位置,便于找到结点双亲,求结点孩子需历遍整个结构

//树的双亲表示法存储结构定义#define MAX_TREE_SIZE 100typedef struct PTNode{    ElemType data;    int parrent;    //双亲位置域} PTNode;typedef struct{    PTNode nodes[MAX_TREE_SIZE];    int n;          //结点数} PTree;
孩子表示法

每个结点的孩子结点用单链表链接起来形成一个线性结构,n个结点就有n个孩子链表

孩子兄弟表示法

二叉树表示法,以二叉链表作为树的存储结构,可方便树转换为二叉树,易于查找结点孩子
三个域(数据域data,第一个孩子指针域firstchild,右兄弟指针域nextsibling)

////树的孩子兄弟表示法存储结构定义typedef struct CSNode{    ElemType data;    struct CSNode *firstchild,*nextsibling;} CSNode,*CSTree;

树和森林的历遍

与二叉树层次历遍类似,按层序依次访问各结点

树 森林 二叉树 先根历遍 先序历遍 先序历遍 后根历遍 后序历遍 后序历遍

树的应用–并查集

并查集是一种简单的集合表示,通常用树或森林的双亲表示作为并查集的存储结构

//并查集结构定义#define SIZE 100int UFSets[SIZE];//三个基本操作void Initial(int S[]);int find(int S[],int x);void Union(int S[],int Root1,int Root2);
原创粉丝点击