数据结构习题集(三)—— 树与二叉树

第3章 树与二叉树

3.1 顺序结构存储的二叉树求结点i,j的最近公共祖先结点

/* 算法思想:若i>j,结点i所在的层次大于或等于j所在层次。结点i的父亲结点为i/2,若i/2 = j,则i/2就是所要找的结点,否则i = i/2,重复上述过程,j>i同理。 */
ElemType Common_Ancestor(SqTree T,int i,int j){
    if(!T[i] && !T[j]){		//结点存在
        while(i != j){		//不是共同结点
            if(i > j)		//沿i向上
                i = i/2;
            else			//沿j向上
                j = j/2;
        }
        return T[i];
    }
}

*3.2 后序遍历二叉树的非递归算法

/* 算法思想:后序遍历的顺序是左右根,所以需要判断返回根节点时刚访问的是左子树还是右子树,所以设置指针r指向最近访问过的结点。 */
void PostOrder(BiTree){ 
	BiTNode *p = T;
    BiTNode *r = NULL;	//辅助指针
    Stack S;
    InitStack(S);
    while(p || !StackEmpty(S)){
        if(p){
            Push(S,p);		//走到最左边,压栈
            p = p->lchild;
        }
        else{	//左边为空或者已经处理
            GetTop(S,p);	//回到对应头结点
            if(p->rchild && r != p->rchild){		//如果有右孩子结点且未被访问
                p = p->rchild;
                Push(S,p);
            }
            else{	//没有右孩子或已经处理过
                Pop(S,p);		//p出栈
                visit(p);		//访问p结点输出对应数据
                r = p;
                p = NULL;
            }
        }
    }
}

3.3 二叉树自下而上,从右到左的层次遍历

/* 算法思想:原有的层次遍历出队的同时各结点依次入栈,所有结点入栈后依次出栈访问即可。 */
void ReverseLevel(BiTree T){
    Queue Q;
    Stack S;
    InitQueue(Q);
    InitStack(S);
    if(T){
        EnQueue(T);
        while(!QueueEmpty(Q)){
			DeQueue(Q,p);
            Push(S,p);		//出队,入栈
            if(p->lchild)
                EnQueue(Q,p->lchild);
            if(p->rchild)
                EnQueue(Q,p->rchild);
        }
        while(!StackEmpty(S)){
            Pop(S,p);
            visit(p);
        }
    }
}

*3.4 非递归计算二叉链表结构存储的二叉树高度

/* 算法思想:层次遍历,用level记录当前高度,last指向下一层第一个结点,每层次遍历出队与last比较,若相等高度level加一,更新last。 */
int Btdepth(BiTree T){
	if(T == NULL)
        return 0;
    BiTree Q[Maxsize];
    int front = -1;
    int rear = -1;
    int last = 0;
    int level = 0;
    Q[++rear] = T;
    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;	//遍历完一层,更新last
        }
    }
    return level;
}

3.5 判断二叉链表结构存储的二叉树是否为完全二叉树

/* 算法思想:完全二叉树性质:只有最后一排不满,而且一旦出现空,后面均为空。因此采用层次遍历,若遇到空结点,查看其后是否还含有空结点。 */
bool is_complete(BiTree T){
	if(T == NULL)
        return true;
    InitQueue(Q);
    EnQueue(Q,T);
    while(!QueueEmpty(Q)){
        DeQueue(Q,p);
        if(p){		//结点非空,孩子入队
         	EnQueue(Q,p->lchild);
         	EnQueue(Q,p->rchild);
        }
        else{		//结点为空,查看后续是否有非空结点
            while(!QueueEmpty(Q)){
                DeQueue(Q,p);
                if(p)
                    return false;
            }
        }
    }
    return true;
}

3.6 二叉链表结构存储的二叉树中计算所有双分支结点个数

/* 算法思想:用num记录双分支结点个数,进行层次遍历,同时有左右孩子时num++ 。*/
int double_child_node(BiTree T){
	if(T == NULL)
        return 0;
    InitQueue(Q);
    EnQUeue(Q,T);
    BiTNode *p;
    int num = 0;
    while(!QueueEmpty(Q)){
		DeQueue(Q,p);
        if(p->lchild && p->rchild)
            num++;
        if(p->lchild)
            EnQueue(Q,p->lchild);
        if(p->rchild)
            EnQueue(Q,p->rchild);
    }
    return num;
}

/* 递归 */
/* 算法思想:采用递归的方法,若b = NULL,f(b) = 0;若b为双分支结点,则f(b) = f(b->lchild) + f(b->rchild) + 1(加上自己),否则f(b) = f(b->lchild) + f(b->rchild)。 */
int DsonNodes(BiTree b){
    if(!b)
        return 0;
    else if(b->lchild && b->rchild)
        return DsonNodes(b->lchild) + DsonNodes(b->rchild) + 1;
    else	
        return DsonNodes(b->lchild) + DsonNodes(b->rchild);
}

3.7 链式结构存储的二叉树,把树B中所有结点的左右子树进行交换

/* 算法思想:采用递归方法,先交换左孩子的左右左子树,再交换右孩子的左右子树,最后交换根结点的左右子树。(后序遍历) */
void swap(BiTree B){
 	if(B){
        swap(B->lchild);
        swap(B->rchild);
        temp = B->lchild;
        B->lchild = B->rchild;
        B->rchild = temp;
    }   
}

*3.8 二叉链表结构存储的二叉树,求先序遍历序列中第k个结点的值

/* 算法思想:设置全局变量i记录已访问的结点,其初值是根结点序号1,当i == k时找到结点,输出值。 */
int i = 1;
ElemType PreNode(BiTree T,int k){
    if(!T)		//空结点返回 '#'
        return '#'
    if(i == k)
        return T->data;
    i++;
    ch = PreNode(T->lchild,k);
    if(ch != '#')
        return ch;
    ch = PreNode(T->rchild,k);
    return ch;
}

*3.9 二叉链表结构存储的二叉树,对于每个元素值为x的结点,删除以它为根的子树,并释放相应空间

//删除树
void DeleteTree(BiTree T){
	if(T){
        DeleteTree(T->lchild);
        DeleteTree(T->rchild);
        free(T);
        T = NULL;
    }
}

/* 递归 */
void search_X_Tree(BiTree T,ElemType x){
	if(T){
		if(T->data == x)
            DeteleTree(T);
        if(!T){
            search_X_Tree(T->lchild);
            search_X_Tree(T->rchild);
        }
    }
}

/* 非递归 */
void search(BiTree T,ElemType x){
    BiTree Q[];
    if(T){
        if(T->data == x){
            Delete(T);
            exit(0);
        }
        InQueue(Q);
        EnQueue(Q,T);
        while(!QueueEmpty(Q)){
            DeQueue(Q,p);
            if(p->lchild){
                if(p->lchild->data == x)
                    DeleteTree(p->lchild);
                else
                    EnQueue(Q,p->lchild);
            }
             if(p->rchild){
                if(p->rchild->data == x)
                    DeleteTree(p->rchild);
                else
                    EnQueue(Q,p->rchild);
            }
        }
    }
}

*3.10 二叉树中查找值为x的结点,打印所有值为x的结点的祖先(值为x的结点至多一个)

/* 算法思想:采用非递归的后序遍历,最后访问根结点,当访问到值为x的结点时,栈中所有元素均为该元素的祖先。 */
typedef struct{
    BiTree T;
    int tag;	//tag = 0表示访问的是左结点,tag = 1表示访问的是右结点。
}stack;

void Search(BiTree T,ElemType x){
  	stack s[];
    int top = 0;
    while(T || top > 0){
        while(T && T->data != x){	//结点入栈
            s[++top].T = T;
            s[top].tag = 0;
            T = T->lchild;
        }
        if(T->data == x){
            printf("值为x的所有祖先结点的值为:\n");
            for(int 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;
            T = s[top].T->rchild;
        }
    }	
}

*3.11 二叉链表结构存储的二叉树,求宽度

/* 算法思想:采用层次遍历。设置last为本行结尾,count记录本行宽度,max记录最大宽度。 */
int width(BiTree T){
    if(!T)
        return 0;
    BiTree Q[];
    int front = -1;
    int rear = -1;
    Q[++ rear] = T;
    int last = 0;	//本行结束
    int count = 1;	//每行宽度
    int max = 1;
    while(fear < rear){
        p = Q[++ front];
        if(p->lchild)
            Q[++ rear] = p->lchild;
        if(p->rchild)
            Q[++ rear] = p->rchild;
        if(front == last){		//当front达到本行末尾时,利用rear - front计算下一行宽度
            count = rear - front;
            max = max > count? max : count;
            last = rear;
        }
    }
    return max;
}

***3.12 已知满二叉树先序序列为pre,设计一个算法求其后序序列post

https://blog.csdn.net/u012133341/article/details/119547234

/* 算法思想:对于任意满二叉树,任意子结点的左右子树结点数相等,同时,先序遍历的第一个结点为后序遍历的最后一个结点,采用递归的方法。 */
void PreToPost(ElemType pre[],int l1,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,h2 -1);	//转换右子树
    }
}

3.12 判断两二叉树是否相似

所谓T1和T2相似是指,T1和T2都为空或者都只有一个根结点,或T1的左子树和T2的右子树是相似的并且T1和T2的右子树是相似的。

/* 算法思想:采用递归的算法,若T1和T2都是空则相似;若一个为空另一个不空则不相似,否则,递归比较左右子树。 */
bool Similar(BiTree T1,BiTree T2) {
    if(!T1 && !T2)
        return true;
    if(!T || !T)
        return false;
    else{
     	leftS = Similar(T1->lchild,T2->lchild);
        rightS = Similar(T1->rchild,T2->rchild);
        return leftS && rightS;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值