【23考研】408代码题参考模板——二叉树

对应视频:23考研408数据结构代码题参考模板(二叉树)
红色的为必须掌握
有多个模板的只要掌握一种即可。

非递归不要求,看不懂算了!!!

二叉树

二叉树结点结构体

模板1

struct node{
	int data;//数据域
	node* lchild;//左指针域 
	node* rchild;//右指针域 
};

模板2

struct node{
	int data;//数据域
	node *lchild,*rchild;//指针域 
};

先序遍历

模板1

void pre_order(node *root){
	//先序遍历 
	if(root!=NULL){
		cout<<root->data;
		pre_order(root->lchild);
		pre_order(root->rchild);
	}
}

模板2

void visit(node *n){
	//对结点的一些操作 
	cout<<n->data;
} 

void pre_order(node *root,void(*visit)(node*)){
	//先序遍历 
	if(root!=NULL){
		visit(root);
		pre_order(root->lchild,visit);
		pre_order(root->rchild,visit);
	}
}

中序遍历

模板1

void in_order(node *root){
	//中序遍历 
	if(root!=NULL){
		in_order(root->lchild);
		cout<<root->data; 
		in_order(root->rchild);
	}
} 

模板2

void visit(node *n){
	//对结点的一些操作 
	cout<<n->data;
} 

void in_order(node *root,void(*visit)(node*)){
	//中序遍历 
	if(root!=NULL){
		in_order(root->lchild,visit);
		visit(root);
		in_order(root->rchild,visit);
	}
} 

后序遍历

模板1

void post_order(node *root){
	//后序遍历 
	if(root!=NULL){
		post_order(root->lchild);
		post_order(root->rchild);
		cout<<root->data;
	}
} 

模板2

void visit(node *n){
	//对结点的一些操作 
	cout<<n->data;
} 

void post_order(node *root,void(*visit)(node*)){
	//后序遍历 
	if(root!=NULL){
		post_order(root->lchild,visit);
		post_order(root->rchild,visit);
		visit(root);
	}
} 

层序遍历

模板1

void level_order(node *root){
	//层序遍历
	queue<node*> q;//队列,存放的是一个个结点所在的位置
	q.push(root);//根节点入队
	while(!q.empty()){
		node *tmp=q.front();//遍历到该结点了 
		q.pop();//该结点出队 
		
		//对该节点进行一些操作,此处是输出该结点存的值
		cout<<tmp->data;
		
		if(tmp->lchild!=NULL){
			//如果有左孩子,则将其入队
			q.push(tmp->lchild);
		} 
		if(tmp->rchild!=NULL){
			// 如果有右孩子,则将其入队
			q.push(tmp->rchild); 
		}
		 
	} 
} 

模板2

void visit(node *n){
	//对结点的一些操作 
	cout<<n->data;
} 

void level_order(node *root,void(*visit)(node*)){
	//层序遍历
	queue<node*> q;//队列,存放的是一个个结点所在的位置
	q.push(root);//根节点入队
	while(!q.empty()){
		node *tmp=q.front();//遍历到该结点了 
		q.pop();//该结点出队 
		
		//对该节点进行一些操作
		visit(tmp); 
		
		if(tmp->lchild!=NULL){
			//如果有左孩子,则将其入队
			q.push(tmp->lchild);
		} 
		if(tmp->rchild!=NULL){
			// 如果有右孩子,则将其入队
			q.push(tmp->rchild); 
		}
		 
	} 
} 

树的题常用框架

将叶子结点和分支结点分开处理

void dfs(node *root){
	if(root!=NULL){
		if(root->lchild==NULL && root->rchild==NULL){
			//对于叶子结点的一些操作
			 
		}
		else{
			//对于分支结点的一些操作
            //别忘了遍历其子树
			 
		}
	} 
} 

求树的深度(推荐模板1和模板2)

有时候并非要求整棵树的深度,而是要知道当前结点的深度

模板1

采用全局变量来记录当前结点的深度(采用此变量好处就是可以在遍历到任意结点的时候知道其所处的深度,在某些时候可以辅助进行一些操作,比如说求WPL,详见2014年408真题)和树的深度

采用任意顺序的遍历方式均可

int deep=0;//全局变量,计算当前结点的深度
int tree_deep=0;//全局变量,记录树的深度 
 
void dfs(node *root){
	deep++;//父节点访问孩子结点,深度+1 
	if(root!=NULL){
		if(root->lchild==NULL && root->rchild==NULL){
			//叶子结点
			 if(deep>tree_deep){
			 	tree_deep=deep;//找到最深的叶子结点 
			 }
		}
		else{
			//分支结点
			dfs(root->lchild);
			dfs(root->rchild);
		}
	} 
	deep--;//返回父节点,深度-1 
} 

int calc_deep(node *root){
	//返回以root为根的二叉树的深度
	
	//对全局变量初始化
	deep=0;
	tree_deep=0;
	
	dfs(root);//计算深度 
	
	return tree_deep;
}

模板2

思路与模板1类似,只是将deep作为遍历时的函数参数进行传递,好处同样是在遍历的时候可以知道当前结点的深度

int tree_deep=0;//全局变量,记录树的深度 

void dfs(node *root,int deep){
    if(root!=NULL){
		if(root->lchild==NULL && root->rchild==NULL){
			//叶子结点
			 if(deep>tree_deep){
			 	tree_deep=deep;//找到最深的叶子结点 
			 }
		}
		else{
			//分支结点
			dfs(root->lchild,deep+1);//遍历左子树,需要深度+1
			dfs(root->rchild,deep+1);//遍历右子树,需要深度+1
		}
	} 
}

int calc_deep(node* root){
    //返回以root为根的二叉树的深度
	
	//对全局变量初始化
	tree_deep=0;
	
	dfs(root,1);//计算深度 
	
	return tree_deep;
}

模板3

int dfs(node *root){
    if(root!=NULL){
        int l_deep=dfs(root->lchild);//左子树的高度
        int r_deep=dfs(root->rchild);//右子树高度
        return max(l_deep,r_deep)+1;//左右子树最大高度+根节点1
    } 

    return 0;
}

模板4

采用层序遍历

int calc_deep(node *root){
	//层序遍历计算树的深度
    if(root==NULL){
        return 0;
    }

	queue<pair<node*,int> > q;//队列,存放的是一个结点+其所在深度
	q.push({root,1});//根节点入队
    int tree_deep=0;//树的深度

	while(!q.empty()){
		auto tmp=q.front();//遍历到该结点了,tmp为pair
		node *n=tmp.first;//当前结点
        int deep=tmp.second;//当前结点所处深度
        q.pop();//该结点出队

        tree_deep=max(tree_deep,deep); 
		
		if(n->lchild!=NULL){
			//如果有左孩子,则将其入队,其深度+1
			q.push({n->lchild,deep+1});
		} 
		if(n->rchild!=NULL){
			// 如果有右孩子,则将其入队,其深度+1
			q.push({n->rchild,deep+1}); 
		}
		 
	} 
    return tree_deep;//返回树的深度
}

模板5

int calc_deep(node *root){
	//层序遍历计算树的深度
    if(root==NULL){
        return 0;
    }

	queue<node*> q;//队列,存放的是一个个结点所在的位置
	q.push(root);//根节点入队
    int level=1,num=1;//当前深度,当前深度剩余结点个数

	while(!q.empty()){
		node *tmp=q.front();//遍历到该结点了 
		q.pop();//该结点出队 
        num--;
		
		if(tmp->lchild!=NULL){
			//如果有左孩子,则将其入队
			q.push(tmp->lchild);
		} 
		if(tmp->rchild!=NULL){
			// 如果有右孩子,则将其入队
			q.push(tmp->rchild); 
		}

        if(num==0){
            //当前深度已经,没有结点了
            level++;//到下一个深度去
            num=q.size();
        }
		 
	} 

    return level-1;//返回树的深度,这里要-1是因为最后多算了一个深度
} 

你可能感兴趣的:(数据结构(考研),数据结构,算法,c++)