数据结构:树

数据结构:树

typedef char TElemType;

//二叉树的二叉链表存储结构
typedef struct BiTNode
{
    TElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//二叉树的二叉线索存储结构
typedef enum PointerTag{Link, Thread}; //Link==0指针 Thread==1线索
typedef struct BiThrNode
{
    TElemType data;
    struct BiThrNode *lchild, *rchild;
    PointerTag LTag, RTag;
}BiThrNode, *BiThrTree;

//树的二叉链表存储结构(孩子兄弟)
typedef struct CSNode
{
    TElemType data;
    struct CSNode *firstchild, *nextsibling;
}CSNode, *CSTree;

//赫夫曼
typedef struct
{
    unsigned int weight;
    unsigned int parent, lchild, rchild;

}HTNode, *HuffmanTree;

int BiTreeDepth(BiTree T)
{ // 初始条件:二叉树T存在。操作结果:返回T的深度
   int i, j;
   if(!T)
        return 0; // 空树深度为0
   if(T->lchild)
        i = BiTreeDepth(T->lchild); // i为左子树的深度
   else
        i = 0;
   if(T->rchild)
        j = BiTreeDepth(T->rchild); // j为右子树的深度
   else
        j = 0;
   return i > j ? i + 1 : j + 1; // T的深度为其左右子树的深度中的大者+1
 }

//先序递归遍历
void PreOrder(BiTree T void(*Visit)(TElemType))
{
    if(T != NULL)
    {
        Visit(T);
        PreOrder(T->lchild);
        PreOrder(T->rchlid);
    }
}

//中序非递归
void InOrderTraverse1(BiTree T, void(*Visit)(TELemType))
{
    Sqstack S;
    InitStack(S);
    while(T || !StackEmpty(S))
    {
        if(T)
        {
            Push(S, T);
            T = T ->lchild;
        }
        else
        {
            Pop(S, T);
            Visit(T->data);
            Push(T->rchild);
        }
    }
}
void InOrderTraverse2(BiTree T, void(*Visit)(TElemType))
{
    SqStack S;
    BiTree p;
    InitStack(S);
    Push(S, T)
    while(!StackEmpty(S))
    {
        while(Getop(S, p) && p)
            Push(S, p->lchild);
        Pop(S, p);
        if(!StackEmpty(S))
        {
            Pop(S, p)
            Visit(p->data);
            Push(S, p->rchild);
        }
    }
}

//后序非递归遍历
void PostOrder(BiTree T, void(*Visit)(TElemType))
{
    SqStack S;
    InitStack(S);
    BiTree p;
    p = T;
    int Tag[];
    while(p || !StackEmpty(S))
    {
        while(p) //遍历左子树
        {
            Push(S, p);
            Tag[Stack->top] = 0;
            p = p->lchild;
        }
        while(!StackEmpty(S) && Tag[Stack->top] == 1)  //左右子树访问完毕 访问根结点
        {
            Pop(S, p);
            Visit(p->data);
        }
        if(!StackEmpty(S))  //遍历右子树
        {
            Tag[S->top] = 1;
            GetTop(S, p);
            p = p->rchild;
        }
    }

}

//层序遍历
void levelOrder(BiTree T, void(*Visit)(TElemType))
{
    LinkQueue q;
    QElemType a;
    if(T)
    {
        InitQueue(q);
        EnQueue(q, T);
        while(!QueueEmpty)
        {
            DeQueue(q, a);
            Visit(a->data);
            if(a->lchild != NULL)
                EnQueue(q, a->lchild);
            if(a->rchild != NULL)
                EnQueue(q, a->rchild);
        }
    }
}

//二叉树找双亲
TElemType Nil = ' ';
TElemType Parent(BiTree T, TElemType e)
{ //若e是非根结点,返回双亲,否则返回空
    LinkQueue q;
    QElemType a;
    if(T)
    {
        InitQueue(q);
        EnQueue(q, T);
        while(!QueueEmpty(q))
        {
            DeQueue(q, a);
            if(a->lchild && a->lchild->data = e || a->rchild && a->rchild->data = e )
                return a->data;
            else
            {
                if(a->lchild)
                    EnQueue(q, a->lchild);
                if(a->rchild)
                    EnQueue(q, a->rchild);
            }
        }
    }
}

//二叉树中序线索化
BiThree pre; //全局变量, 始终指向刚刚访问过的结点
void InThreading(BiThrTree p)
{  //通过中序遍历进行中序线索化, 线索化后pre指向最后一个结点
    if(p)
    {
        InThreading(p->lchild);
        if(!p->lchild)
        {
            p->LTag = Thred;
            p->lchild = pre;
        }
        if(!pre->rchild)
        {
            pre->RTag = Thread;
            pre->rchild = p;
        }
        pre = p; //始终保持pre指向p的前驱
        InThreading(p->rchild);
    }
}
Status InOrderThreading(BiTree &Thrt, BiThrTree T{ //Thrt指向头结点, 头结点左孩子指向根结点, 右孩子指针(线索)指向中序遍历最后一个结点
    if(!(Thrt =(BiTree)malloc(sizeof(BiThrNode))))
        exit(OVERFLOW);
    Thrt->LTag = Link;
    Thrt->RTag = Thread;
    Thrt->rchild = Thrt; //右指针回指
    if(!T)
        Thrt->lchild = Thrt;
    else
    {
        Thrt->lchild = T;
        InThreading(T); /
        pre->rchild = Thrt; //最后一个结点的右指针指向头结点
        pre->RTag = Thread;
        Thrt->rchild = pre; //头结点的右指针指向中序遍历最后一个结点
    }
    return OK}

//中序线索二叉树查找指定结点在后序的前驱结点算法
BiThrNode InPostPre(BiTree T, BiThrNode p)
{
    BiThrNode q;
    if(p->RTag == Link) //若p有右子女,则右子女是其后序前驱
        q = p->rchild;
    else if(p->LTag == Link) //若p只有左子女,则左子女是其后序前驱
        q = p->lchild;
    else if(p->lchild == NULL) //若p是中序序列第一结点,无后序前驱
        q = NULL;
    else
    { //顺左线索往上找p的祖先, 若存在,再找祖先的左子女
        while(p->LTag == Thread && p->lchild != NULL) //找到祖先
            p = p->lchild;
        if(p->LTag == Link)
            q = p->lchild;
        else
            q = NULL;
    }
    return q;
}

//树找双亲(利用孩子兄弟存储结构)
TElemType Parent(CSTree T, TElemType cur_e, void(*Visit)(TElemType))
{ //若cur_e是T的非根结点, 则返回它的双亲,否则函数值为空
    CSTree p, t;
    LinkQueue q;
    if(T)
    {
        if(Visit(T-data) == cur_e)
            return Nil;
        EneQueue(q, T);
        while(!QueueEmpty(q))
        {
            DeQueue(q, p);
            if(p->firstchild)
            {
                if(p->firstchild->data == cur_e)
                    return Visit(p->data);
                t = p;
                p = p->firstchild;
                EnQueue(p->nextsibling);
                while(p->nextsibling)
                {
                    if(Visit(p->data) == cur_e)
                        return Visit(p->data);
                    EnQueue(q, p);
                }
            }
        }
    }
    return Nil;
}

Status InsertChild(CSTree &T,CSTree p,int i,CSTree c)
 { // 初始条件:树T存在,p指向T中某个结点,1≤i≤p所指结点的度+1,非空树c与T不相交
   // 操作结果:插入c为T中p结点的第i棵子树
   // 因为p所指结点的地址不会改变,故p不需是引用类型
   int j;
   if(T) // T不空
   {
     if(i == 1) // 插入c为p的长子
     {
       c->nextsibling = p->firstchild; // p的原长子现是c的下一个兄弟(c本无兄弟)
       p->firstchild = c;
     }
     else // 找插入点
     {
       p = p->firstchild; // 指向p的长子
       j = 2;
       while(p && j< i)
       {
         p = p->nextsibling;
         j++;
       }
       if(j == i) // 找到插入位置
       {
         c->nextsibling = p->nextsibling;
         p->nextsibling = c;
       }
       else // p原有孩子数小于i-1
         return ERROR;
     }
     return OK;
   }
   else // T空
     return ERROR;
 }

 Status DeleteChild(CSTree &T, CSTree p, int i)
 { // 初始条件:树T存在,p指向T中某个结点,1≤i≤p所指结点的度
   // 操作结果:删除T中p所指结点的第i棵子树
   // 因为p所指结点的地址不会改变,故p不需是引用类型
   CSTree b;
   int j;
   if(T) // T不空
   {
     if(i == 1) // 删除长子
     {
       b = p->firstchild;
       p->firstchild = b->nextsibling; // p的原次子现是长子
       b->nextsibling = NULL;
       DestroyTree(b);
     }
     else // 删除非长子
     {
       p = p->firstchild; // p指向长子
       j = 2;
       while(p && j < i)
       {
         p = p->nextsibling;
         j++;
       }
       if(j == i) // 找到第i棵子树
       {
         b = p->nextsibling;
         p->nextsibling = b->nextsibling;
         b->nextsibling = NULL;
         DestroyTree(b);
       }
       else // p原有孩子数小于i
         return ERROR;
     }
     return OK;
   }
   else
     return ERROR;
 }

//赫夫曼编码
typedef char **HuffmanCode; //动态分配数组存储赫夫曼树
void select(HuffmanTree t, int i, int &s1, int &s2)
{ //在i个结点中选择最小的树的根节点序号
    int j;
    s1 = min(t, i);
    s2 = min(t, i);
    if(s1 > s2)
    {
        j = s1;
        s1 = s2;
        s2 = s1;
    }
}
void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, int *w, int n)
{ //w存放n个字符的权值,构造赫夫曼树HT,并求出n个字符的赫夫曼编码HC
    int m, i, s1, s2, start;
    unsigned c, f;
    HuffmanTree P;
    char *cd;
    if(n <= 1)
            return;
    m = 2 * n -1; //赫夫曼树结点总数
    HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); //0号单元未用
    for(p = HT+1, i = 1; i <= n; ++i, ++p, ++w)
    { //初始n个结点初始化
        (*p).weight = *w;
        (*p).parent = 0;
        (*p).lchild = 0;
        (*p).rchild = 0;
    }
    for(; i <= m; ++i, ++p) //另外的m-n个结点初始化
    for(i = n + 1; i <= m; ++i)
    { //构造赫夫曼树
        select(HT, i - 1, s1, s2);
        HT[s1].parent = HT[s2].parent = i;
        HT[i].lchild = s1;
        HT[i].rchild = s2;
        HT[i].weight = HT[s1].weight + HT[s2].weight;
    }
    //从叶子到根逆向求每个字符的赫夫曼编码
    HC = (HuffmanCode)malloc((n + 1) * sizeof(char *)); //分配n个字符编码的头指针向量
    cd = (char*)malloc(n *sizeof(char)); //分配求编码的工作空间
    cd[n - 1] = "\0"; //编码结束符
    for(i = 1; i <= n; i++)
    { //逐个字符求赫夫曼编码
        strat = n - 1;
        for(c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
        { //逆向
            if(HT[f].lchild = c)
                cd[--start] = '0'; //左子树为0
            else
                cd[--strat] = '1';
            HC[i] = (char*)malloc((n - strat)*sizeof(char)); //为i个字符分配空间
            strcpy(HC[i], &cd[strat]);
        }
    }
    free(cd); //释放工作空间
}

//求T的WPL(带权路径长度)
typedef struct BiTNode
{
    int weight;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
int wpl_PreOrder(BiTree root, int deep)
{ //基于先序遍历
    int wpl =0;
    if(root->lchild == NULL && root->rchild == NULL)
        wpl += deep * root->weight;
    if(root->lchild != NULL)
        wpl_PreOrder(root->lchild, deep + 1);
    if(root->rchild != NULL)
        wpl_PreOrder(root->rchild, deep + 1);
    return wpl;
}
#define MaxSize 100
int wpl_LevelOrder(BiTree root)
{ //基于层次遍历 利用队列
    BiTree q[MaxSize];
    int end1, end2;
    end1= end2 = 0;
    int wpl = 0,;
    int deep = 0;
    BiTree LastNode; //用来记录当前层最后一个结点
    BiTree newLastNode; //下一层最后一个结点
    LastNode = root;
    newLastNode = NULL;
    while(end1 != end2)//队列不空
    {
        BiTree t = q[end1++];
        if(t->lchild == NULL && t->rchild == NULL)
            wpl += deep * t->weight;
        if(t->lchild != NULL)
        {
            q[end2++] = t->lchild;
            newLastNode = t->lchild;
        }
        if(root->rchild != NULL)
        {
            q[end2++] = t->rchild;
            newLastNode = t->rchild;
        }
        if(t == LastNode)
        {
            LastNode = newLastNode;
            deep += 1;
        }
    }
    return wpl;
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值