王道考研408 数据结构 5.3 二叉树的遍历和线索二叉树

5.3 二叉树的遍历和线索二叉树

5.3.03

编写后序遍历二叉树的非递归算法

思路:1. 将元素沿着左孩子依次入栈;2.读栈顶,如果右孩子不空且未被访问过,则将右子树执行1,否则出栈并访问

void PostOrder(BiTree T)
{
    InitStack(S);
    p = T;
    r = NULL;
    while(p||!IsEmpty(S)){
        if(p){
            push(S,p);
            p = p->lchild;
        }
        else{
            GetTop(S,p);
            if(p->rchild&&p->rchild!=r)
                p = p->rchild;
            else{
                pop(S,p);
                visit(p->data);
                r = p;
                p = NULL;
            }
        }//end else
    }// end while
}
5.3.04

二叉树的自下而上、从右到左的层次遍历算法

void InvertLevel(BiTree bt){
    Stack s; Queue Q;
    if(bt != NULL){
        InitStack(s);
        InitQueue(Q);
        EnQueue(Q,bt);
        while(IsEmpty(Q)  == false){
            DeQueue(Q,p);
            Push(s,p);
            if(p->lchild)
                EnQueue(Q,p->lchild);
            if(p->rchild)
                EnQueue(Q,p->rchild);
        }// end while
        while(IsEmpty(s) == false){
            Pop(s,p);
            visit(p->data);
        }
    }// end if
}
5.3.05

假设二叉树采用二叉链表存储结构,设计一个非递归算法求二叉树的高度。

int Btdepth(BiTree T)
{
    if(!T) return 0;
    int front = -1, rear = -1;
    int last = 0, level = 0;
    BiTree Q[MaxSize];
    Q[++rear] = T;
    BiTree p;
    while(front<rear){
        p = Q[++front];
        if(p->lchild) Q[++rear] = p->lchild;
        if(p->rchild) Q[++rear] = p->rchild;
        if(front == last){
            level++;
            last = rear;
        }
    }//end while
    return level;
}
//递归法
int Btdepth2(BiTree T){
    if(T==NULL) return 0;
    ldep = Btdepth2(T->lchild);
    rdep = Btdepth2(T->rchild);
    if(ldep>rdep) return ldep+1;
    else return rdep+1;
}
5.3.06

设一棵二叉树中各结点的值不同,其先序遍历序列和中序遍历序列分别存于两个一维数组A[1…n]和B[1…n]中,建立二叉链表

这道题思路很难啊,想不出来力TT

BiTree PreInCreat(ElemType A[], ElemType B[], int l1, int h1, int l2, int h2){
    //l1,h1为先序的第一和最后一个节点下标,l2,h2为中序的第一和最后一个下标
    root = (BiTNode *) malloc (sizeof(BiTNode));
    root->data = A[l1];
    for(i = l2; B[i]!=root->data;i++);
    llen = i-l2;
    rlen = h2-i;
    if(llen) root->lchild = PreInCreat(A,B,l1+1,l1+llen,l2,l2+llen-1);
    else root->lchild = NULL;
    if(rlen) root->rchild = PreInCreat(A,B,h1-rlen+1,h1,h2-rlen+1,h2);
    else root->rchild = NULL;
    return root;
}
5.3.07

二叉树按二叉链表形式存储,判断是否是完全二叉树

我也不会,看的答案。建立队列之后先让父节点进去,然后抽出父节点让子节点进去,没有就

bool IsComplete(BiTree T)
{
	InitQueue(Q);
    if(!T) return 1;
    EnQueue(Q,T);
    while(!IsEmpty(Q)){
        DeQueue(Q,p);
        if(p){
            EnQueue(Q,p->lchild);
            EnQueue(Q,p->rchild);
        }
        else
            while(!IsEmpty(Q)){
				DeQueue(Q,p);
                if(p) return 0;
            }
    }//end while
    return 1;
}
5.3.08

假设二叉树采用二叉链表存储结构存储,计算二叉树所有双分支节点个数。

int cntdl(BiTree b){
    if(b == NULL) return 0;
    else if(b->lchild != NULL && b->rchild != NULL)
        return cntdl(b->lchild)+cntdl(b->rchild)+1;
    else return cntdl(b->child)+cntdl(b->rchild);
}
5.3.09

左节点和右节点交换一哈

void swap(BiTree b)
{
    if(b){
        swap(b->lchild);
        swap(b->rchild);
        temp = b->lchild;
        b->lchild = b->rchild;
        b->rchild = temp;
    }
}
5.3.12

在二叉树中寻找值为x的结点,试编写算法打印值为x的结点的所有祖先,假设值为x的结点不多于一个

typedef struct{
    BiTree t;
    int tag; //tag=0表示左子女被访问,tag=1表示右子女被访问
}stack;
void Search(BiTree bt, ElemType x)
{
	stack s[];
    top = 0;
    while(bt!=NULL||top>0){
        while(bt!=NULL && bt->data != x){
            s[++top].t = bt;
            s[top].tag = 0;
            bt = bt->lchild;//沿着左分支往下
        }
        if(bt!=NULL && bt->data == x){
            printf("所有节点值为:\n");
            for(i=1;i<=top;i++)
                printf("%d ",s[i].t->data);
            exit(1);
        }
        while(top != 0 && s[top].tag == 1) top--;
        if(top != 0){
            s[top].tag = 1;
            bt = s[top].t->rchild;
        }
    }// end while
}
5.3.13

设一棵二叉树的结点结构为(LLINK,INFO,RLINK),ROOT为指向该二叉树根节点的指针,p和q分别为指向该二叉树中任意两个结点的指针,试编写算法ANCESTER(ROOT,p,q,r),找到p和q的最近公共祖先结点r

思路完全一样啊TT

typedef struct{
    BiTree t;
    int tag; //tag=0表示左子女被访问,tag=1表示右子女被访问
}stack;
stack s[],s1[];
BiTree ANCESTER(BiTree ROOT,BiNode *p, BiNode *q))
{
    top = 0; bt = ROOT;
    while(bt!=NULL||top>0){
        while(bt!=NULL && bt->data != x){
            s[++top].t = bt;
            s[top].tag = 0;
            bt = bt->lchild;//沿着左分支往下
        }
        while(top != 0 && s[top].tag == 1){
            if(s[top].t == p){
                for(i = 1;i <= top;i++)
                    s1[i] = s[i];
               	top1 = top;
            }
            if(s[top].t == q)
                for(i = top; i>0; i--){
                    for(j = top1; j>0; j--)
                        if(s1[j].t == s[i].t) return s[i].t;
                }
            top--;
        }// end while
        if(top! = 0){
            s[top].tag = 0;
            bt = s[top].t->rchild;
        }
    }//end while
    return NULL;//找不到
}
5.3.15

设有一棵满二叉树(所有节点值均不同),已知其先序序列为pre,设计一个算法求其后续序列post

void PreToPost(ElemType pre[], int l1, int h1, ElemType post[], int l2, int h2)
{
    int half;
    if(h1>l1){
        post[h2]  = pre[l1];
        half = (h1-l1)/2;//满二叉树
        PreToPost(pre,l1+1,l1+half,post,l2,l2+half-1);
        PreToPost(pre,l1+half+1,h1,post,l2+half,l2-1);
    }
}
5.3.16

设计一个算法将二叉树的叶结点按从左到右的顺序连成一个单链表,表头指针为head,二叉树按二叉链表方式存储,连接时用叶节点的右指针域来存放单链表指针。

LinkedList head, pre = NULL;
LinkedList InOrder(BiTree bt)
{
    if(bt){
        InOrder(bt->lchild);
        if(bt->lchild == NULL && bt->rchild == NULL)
            if(pre == NULL){
                head = bt;
                pre = bt;
            }
        	else{
                pre->rchild = bt;
                pre = bt;
            }
		InOrder(bt->rchild);
        pre->rchild = NULL;
  	}
    return head;
}
5.3.17

试设计判断两棵二叉树是否相似的算法(指是否是空二叉树或只有一个根节点,或T1的左子树和T2的左子树是相似的)

int similar(BiTree T1, BiTree T2)
{
    int leftS,rightS;
    if(T1 == NULL && T2 == NULL)
        return 1;
    else if(T1 == NULL || T2 == NULL)
        return 0;
    else{
        leftS = similar(T1->lchild, T2->lchild);
        rightS = similar(T1->rchild, T2->rchild);
        return leftS&&rightS;
    }
    return -1;
}
5.3.18

写出在中序线索二叉树里查找指定节点在后序的前驱结点的算法

BiThrTree InPostPre(BiThrTree t, BiThrTree p)
{
	BiThrTree q;
    if(p->rtag == 0) p = q->rchild; //p有右子女,右子女是其后序前驱
    else if(p->ltag == 0) q = p->lchild; //p只有左子女,左子女是其后序前驱
    else if(p->lchild == NULL) q = NULL;//都没有,没有前驱
    else {//p祖先的左子女
        while(p->ltag == 1 && p->lchild !=NULL) p = p->child;
        if(p->ltag == 0) q = p->lchild;
        else q = NULL;
    }
    return q;
}
5.3.19

二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和,给定一棵二叉树T,采用二叉链表存储,结点结构为left,weight,right。其中叶结点的weight域存放该结点的非负权值。设root为指向T的根节点的指针,请设计求T的WPL的算法。

带权路径长度=叶子结点深度与其指定权重的乘积总和。

typedef struct BiTNode{
    int weight;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
//先序遍历
int WPL(BiTree root){
    return wpl_PreOrder(root, 0);
}
int wpl_PreOrder(BiTree root, int deep){
    static 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为尾指针,队列最多容纳MaxSize-1个元素
    end1 = end2 = 0;
    int wpl = 0, deep = 0;
    BiTree lastNode; //记录当前层的最后一个结点
    BiTree newlastNode; //记录下一层的后一个结点
    lastNode = root;
    newlastNode = NULL;
    q[end2++] = root; //根节点入队
    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(t->rchild != NULL)
        {
            q[end2++] = t->rchild;
            newlastNode = t->rchild;
        }
        if(t == lastNode){
            lastNode = newlastNode;
            deep += 1;
        }
    }// end while
    return wpl;
}
5.3.20

请设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。

typedef struct node{
    char data[10];
    struct node *left, *right;
}BTree;
void BTreeToE(BTree *root){
    BtreeToExp(root, 1);
}
void BTreeToExp(BTree *root, int deep)
{
	if(root == NULL) return;
    else if(root->left == NULL && root->right == NULL)
        printf("%s",root->data);
    else{
        if(deep>1) printf("(");
        BtreeToExp(root->left, deep+1);
        printf("%s",root->data);
        BtreeToExp(root->right, deep+1);
        if(deep>1) printf(")");
    }
    return;
}
后记

好难啊好难啊好难啊!!!!!后面我还会回来刷的!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值