天勤2022数据结构(五)树与二叉树

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

天勤2022数据结构(五)树与二叉树


前言

typedef struct BTNode{
	char data;
	struct BTNode *lchild;
	struct BTNode *rchild;
}BTNode; 

typedef struct TBTNode{
	char data;
	int ltag, rtag;
	struct TBTNode *lchild;
	struct TBTNode *rchild;
}TBTNode;

一、基础算法

  1. 层次遍历

    void level(BTNode *p){
    	if(p == NULL)
    		return ;
    	int front, rear;
    	BTNode *qu[maxSize];
    	front = rear = 0;
    	BTNode *q;
    	rear = (reaar + 1) % maxSize;
    	qu[rear] = p;
    	while(front != rear){
    		front = (front + 1) % maxSize;
    		q = qu[front];
    		Print(q);
    		if(q->lchild != NULL){
    			rear = (rear + 1) % maxSize;
    			qu[rear] = q->lchild;
    		}
    		if(q->rchild != NULL){
    			rear = (rear + 1) % maxSize;
    			qu[rear] = q->rchild;
    		}
    	}
    }
    
  • 扩展
    假设二叉树用二叉链表结构存储,求宽度(结点最多那一层的结点个数)
  1. 中序遍历对二叉树线索化

    void InThread(TBTNode *p, TBTNode *&pre){
    	if(p == NULL)
    		return;
    	InThread(p->lchild, pre);
    	if(p->lchild == NULL){
    		p->lchild = pre;
    		p->ltag = 1;
    	}
    	if(pre != NULL && p->rchild == NULL){
    		p->rchild = p;
    		p->rtag = 1;
    	}
    	pre = p;
    	InThread(p->rchild, pre);
    }
    
    void createInThread(TBTNode *root){
    	TBTNode *pre = NULL;
    	if(root != NULL){
    		InThread(root, pre);
    		pre->rchild = NULL;
    		pre->rtag = 1;
    	}
    }
    
    TBTNode *First(TBTNode *p){
    	while(p->ltag == 0){
    		p = p->lchild;
    	}
    	return p;
    }
    
    TBTNode *Next(TBTNode *p){
    	if(p->rtag == 0){
    		return First(p->rchild);
    	}else{
    		return p->rchild;
    	}
    }
    
    void Inorder(TBTNode *root){
    	for(TBTNode *p = First(root); p!=NULL; p=Next(p)){
    		Visit(p);
    	}
    }
    

二、综合应用题

  1. 设二叉树根结点所在层次为1,树的深度d为距离根最远的叶结点所在的层次

    1. 试精确给出深度为d的完全二叉树的不同二叉树棵数

      2 ( d − 1 ) 2^{(d-1)} 2(d1)

    2. 试精确给出深度为d的满二叉树的不同二叉树棵数

      1

  2. 假设二叉树采用二叉链存储结构,设计一个算法,计算一棵给定二叉树的所有结点数

    int count(BTNode *p){
    	if(p == NULL)
    		return 0;
    	return count(p->lchild)+count(p->rchild)+1;	
    }
    
  3. 假设二叉树采用二叉链存储结构,设计一个算法,计算一棵给定二叉树的所有叶子结点

    int count(BTNode *p){
    	if(p == NULL)
    		return 0;
    	else if(p->lchild == NULL && p->rchild == NULL)
    		return 1;
    	return count(p->lchild)+count(p->rchild);	
    }
    
  4. 假设二叉树采用二叉链存储结构,设计一个算法,利用结点的右孩子指针rchild将一棵二叉树的叶子结点按照从左往右的顺序串成一个单链表(在题目中定义两个指针head与tail,其中head指向第一个叶子结点,head初值为NULL,tail指向最后一个叶子结点)

    Tip:无论哪种遍历方式     叶子节点 在序列中的 相对位置 总是 不变

    void link(BTNode *p, BTNode *&head, BTNode *&tail){
    	if(p == NULL)
    		return;
    	if(p->lchild == NULL && p->rchild == NULL){
    		if(head == NULL){
    			head = p;
    			tail = p;
    		}else{
    			tail -> rchild = p;
    			tail = p;
    		}
    	}
    	link(p->lchild, head, tail);
    	link(p->rchild, head, tail);
    }
    
  5. 在二叉树的二叉链存储结构中,增加一个指向双亲结点的parent指针,设计一个算法,给这个指针赋值,并输出所有结点到根结点的路径

    typedef struct BTNode{
    	char data;
    	struct BTNode *parent;
    	struct BTNode *lchild;
    	struct BTNode *rchild;
    }BTNode;
    
    void triBtree(BTNode *p, BTNode *q){
    	if(p == NULL)
    		return;
    	p->parent = q;
    	q = p;
    	triBtree(p->lchild, q);
    	triBtree(p->rchild, q);
    }
    
    void printPath(BTNode *p){
    	while(p!=NULL){
    		cout<<p->data<<" "<<endl;
    		p = p->parent;
    	}
    }
    	
    void allPath(BTNode *p){
    	while(p!=NULL){
    		printPath(p);
    		allPath(p->lchild);
    		allPath(p->rchild);
    	}
    }
    
  6. 假设满二叉树b的 先序 遍历序列已经存在于数组中(在解题过程中,此数组名称可自定义,长度为n),设计一个算法将其 转换后序 遍历序列

    思路:
      1. 根节点移动到整个序列的末尾
      2. 递归处理序列左子树、右子树

    void change(char arr[], int L1, int R1, char res[], int L2, int R2){
    	if(L1<=R1){
    		res[R2] = arr[R1];
    		change(arr, L1+1, (L1+1+R1)/2, res, L2, (L2+R2-1)/2);
    		change(arr, (L1+1+R1)/2+1, R1, res, (L2+R2-1)/2+1, R2-1);
    	}
    }
    
  7. 假设二叉树采用二叉链存储结构,设计一个算法,求二叉树b中值为x的结点的层号

    在这里插入代码片
    
  8. 以数据集合(2,5,7,9,13}为权值构造一棵赫夫曼树,并计算其带权路径长度

    (2+5) * 3 + (7 + 9 + 13) * 2 = 79

  9. 对于一个堆栈,若其入栈序列为1,2,3,…,n,不同的出入栈操作将产生不同的出栈序列。其出栈序列的个数正好等于结点个数为n的二叉树的个数,且与不同形态的二叉树一一对应。请简要叙述一种从堆栈输入(固定为1,2,3,…,n)和输出序列对应一种二叉树形态的方法,并以入栈序列1,2,3(n=3)为例确定所有的二叉树。

    Tips:
    (二叉树遍历都是递归,递归用到系统栈)
        1. 先序遍历:入栈时进行打印的序列
        2. 中序遍历:出栈时进行打印的序列


    二叉树 先序遍历和中序遍历 可唯一确定一棵二叉树
    入栈序列:1,2,3,…,n,相当于先序遍历序列是1,2,3,…,n
       出栈序列:对应的二叉树的中序遍历序列
       有了进栈和出栈序列,相当于知道一棵二叉树的先序和中序遍历序列,即确定了对应的二叉树


    在这里插入图片描述

  10. 二叉树的 双序遍历 是指:对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树。试写出执行这种双序遍历的算法。

    void Double_order(BTNode *t){
    	if(t == NULL)
    		return;
    	Print(t);
    	Double_order(t->lchild);
    	Print(t);
    	Double_order(t->rchild);
    }
    
  11. 中序线索二叉树 的类型为TBTNode* InThTree;

    1. 设计算法,在一棵中序线索二叉树中寻找结点 t 的子树上中序下的最后一个结点。

      TBTNode *inLast(TBTNode *t){
      	TBTNode *p = t;
      	while(p && p->rtag == 1){
      		p = p->rchild;
      	}
      	return p;
      }
      
    2. 设计算法,在一棵中序线二叉树中寻找结点 t 的中序下的前驱。

      TBTNode *inPrior(TBTNode *t){
      	TBTNode *p = t->lchild;
      	if(p && p->ltag == 0){
      		p = inLast(p);
      	}
      	return p;
      }
      
    3. 设计算法,在一棵中序线索二叉树中寻找结点 t 的前序下的后继。

      在这里插入代码片
      

总结

提示:这里对文章进行总结:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值