【数据结构】树与二叉树、树与森林部分习题以及算法设计例题 2

news2024/11/28 2:29:36

目录

  • 【数据结构】树与二叉树、树与森林部分习题以及算法设计例题
    • 一、交换二叉树每个结点的左右孩子
      • Swap 函数(先序遍历):
      • Swap 函数(中序遍历)××× 不可行:
      • Swap 函数(后序遍历):
    • 二、非递归算法求森林中有几棵树
      • 树的二叉链表(孩子-兄弟)存储表示法
    • 三、判断二叉树是否为完全二叉树
    • 四、求二叉树的最小深度 以及 二叉树树高

  1. 树与二叉树知识点文章: 【数据结构】树与二叉树(递归法先序、中序、后序、层次遍历二叉树、二叉树的建立以及求树高的方法)
  2. 二叉树遍历算法的应用: 【数据结构】树与二叉树遍历算法的应用(求叶子节点个数、求树高、复制二叉树、创建二叉树、二叉树存放表达式、交换二叉树每个结点的左右孩子)
  3. 树与森林知识点文章: 【数据结构】树与森林(树的存储结构、森林与二叉树的转化、树与森林的遍历)
  4. 树与二叉树、树与森林部分习题: 【数据结构】树与二叉树、树与森林部分习题与算法设计例题

【数据结构】树与二叉树、树与森林部分习题以及算法设计例题

一、交换二叉树每个结点的左右孩子

以上代码实现了交换二叉树每个节点的左右孩子的功能,分别使用了先序、中序和后序遍历的方式。

遍历二叉树算法的变式:

  1. Swap 函数(先序遍历):

    • 从根节点开始,先交换当前节点的左右孩子。
    • 然后递归地对左子树和右子树执行相同的操作。
  2. Swap2 函数(中序遍历):

    • 与先序遍历不同,中序遍历中需要先对左子树进行操作,然后交换当前节点的左右孩子,最后对右子树进行操作。
    • 但是这个实现方式是错误的,因为在交换左子树之后,对右子树进行操作时,右子树的结构已经发生了变化,导致结果错误。
  3. Swap3 函数(后序遍历):

    • 与先序遍历类似,但是是在遍历完左右子树之后再交换当前节点的左右孩子。
    • 这样可以保证在交换左右孩子时,左右子树的结构不会被改变。

通过上述分析,正确的交换方式是采用先序或后序遍历,中序遍历方式不适合这个场景。

Swap 函数(先序遍历):

//前序
void Swap(BiTree& T){
	//(先序遍历) 
	if(T){
	//根节点 
		if(T->lchild||T->rchild){
			BiTree p;
			p= T->lchild;
			T->lchild = T->rchild;
			T->rchild = p;
		}
		Swap(T->lchild);
		Swap(T->rchild);
	}
}

Swap 函数(中序遍历)××× 不可行:

//中序的不行 
void Swap2(BiTree& T){
	//(中序遍历) 
	
	if(T){
	//根节点 
		Swap2(T->lchild);
		if(T->lchild||T->rchild){
			BiTree p;
			p= T->lchild;
			T->lchild = T->rchild;
			T->rchild = p;
		}
		Swap2(T->rchild);
		
	}
}

Swap 函数(后序遍历):

//后序
void Swap3(BiTree& T){
	//(后序遍历) 
	
	if(T){
	//根节点 
		Swap3(T->lchild);
		Swap3(T->rchild);
		if(T->lchild||T->rchild){
			BiTree p;
			p= T->lchild;
			T->lchild = T->rchild;
			T->rchild = p;
		}
	}
	
	
}

综上可行的只有先序和后序这两种方法:

//交换二叉树每个结点的左右孩子
//先序
void XXSwap_LandRchild(BiTree &T){
    BiTree p;
    if(T==NULL) return;
    else{//先序
        if(!T->lchild&&!T->rchild) return;

        p=T->lchild;
        T->lchild=T->rchild;
        T->rchild=p;

        XXSwap_LandRchild(T->lchild);

        XXSwap_LandRchild(T->rchild);
    }
}
//后序
void HXSwap_LandRchild(BiTree &T){
    BiTree p;
    if(T==NULL) return;
    else{//后序
        if(!T->lchild&&!T->rchild) return;
        HXSwap_LandRchild(T->lchild);
        HXSwap_LandRchild(T->rchild);

        p=T->lchild;
        T->lchild=T->rchild;
        T->rchild=p;
    }
}

完整代码示例:

//设二叉树采用二叉链表存储,设计递归算法实现二叉树中所有结点的左右孩子交换。
#include<iostream>
using namespace std;

//二叉链表
typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;

//二叉树的建立的算法(按先序遍历序列建立)
void CreateBiTree(BiTree &T) {
	char ch; 
    scanf("%c",&ch);
    if (ch=='#') T = NULL;
    else {
        T = (BiTNode*)malloc(sizeof(BiTNode));
        T->data = ch;      // 生成根结点
        CreateBiTree(T->lchild); // 构造左子树
        CreateBiTree(T->rchild); // 构造右子树
    }
}


void XXSwap_LandRchild(BiTree &T){
    BiTree p;
    if(T==NULL) return;
    else{//先序
        if(!T->lchild&&!T->rchild) return;

        p=T->lchild;
        T->lchild=T->rchild;
        T->rchild=p;

        XXSwap_LandRchild(T->lchild);

        XXSwap_LandRchild(T->rchild);
    }
}

void HXSwap_LandRchild(BiTree &T){
    BiTree p;
    if(T==NULL) return;
    else{//后序
        if(!T->lchild&&!T->rchild) return;
        HXSwap_LandRchild(T->lchild);
        HXSwap_LandRchild(T->rchild);

        p=T->lchild;
        T->lchild=T->rchild;
        T->rchild=p;
    }
}


void XXPrintTree(BiTree T){
    if(T==NULL) return;
    else{
        cout<<T->data<<" ";
        XXPrintTree(T->lchild);
        XXPrintTree(T->rchild);
    }
}


int main()
{
    BiTree T;
    CreateBiTree(T);
    XXPrintTree(T);
    cout<<endl;
    XXSwap_LandRchild(T);
    XXPrintTree(T);
    cout<<endl;
    HXSwap_LandRchild(T);
    XXPrintTree(T);
    cout<<endl;
    return 0;
}

二、非递归算法求森林中有几棵树

树的二叉链表(孩子-兄弟)存储表示法

[fc,data,nb]
在这里插入图片描述

typedef struct CSNode{
    int data;
    struct CSNode *fc, *nb;
}CSNode, *CSTree;

树中每个结点三部分:
数据域(data),长子指针域(fc),
右邻兄弟指针域(nb)

树和二叉树的转换
• 树以孩子兄弟表示法存,相当于将树转换成二叉树,但此二叉树根结点无右子树
• 好处:借助二叉树的操作实现树的操作

森林与二叉树的转换

⮚ 树采用二叉链表(孩子-兄弟)存储表示法,转换成二叉树
⮚ 森林由多棵树组成: F = ( T 1 , T 2 , … , T n ) F = ( T1, T2, …, Tn ) F=(T1,T2,,Tn); 将其每棵树转换成二叉树 B T 1 , B T 2 , … , B T n BT₁, BT₂, …, BTn BT1,BT2,,BTn;
⮚ 每棵二叉树BT的根的右子树皆为空树,从BTn开始依次将其根结点链为前一棵二叉树的根的右孩子
⮚ 将森林转换成一棵二叉树,森林的操作可借助二叉树的操作完成

森林和二叉树的转换
• 森林以孩子兄弟表示法存,相当于将森林转换成二叉树
• 好处:借助二叉树的操作实现森林的操作

因此只需要一直向右下数结点的个数就行

typedef struct CSNode{
    int data;
    struct CSNode *fc, *nb;
}CSNode, *CSTree;

//非递归算法求森林中有几棵树。
int CountForestTrees(CSTree F){
    CSTree p=F;
    int num=1;
    while(p){
        p=p->nb;//右子树
        num++;
    }
    return num;
}

完整代码示例:

//设森林采用根节点为T的二叉链表存储,设计非递归算法求森林中有几棵树。
#include<iostream>
using namespace std;

typedef struct CSNode{
    int data;
    struct CSNode *fc, *nb;
}CSNode, *CSTree;


//二叉树的建立的算法(按先序遍历序列建立)
void CreateBiTree(CSTree &T) {
	char ch; 
    scanf("%c",&ch);
    if (ch=='#') T = NULL;
    else {
        T = (CSNode*)malloc(sizeof(CSNode));
        T->data = ch;      // 生成根结点
        CreateBiTree(T->fc); // 构造左子树
        CreateBiTree(T->nb); // 构造右子树
    }
}


//非递归算法求森林中有几棵树。
int CountForestTrees(CSTree F){
    CSTree p=F;
    int num=1;
    while(p){
        p=p->nb;//右子树
        num++;
    }
    return num;
}


int main()
{
    CSTree T;
    CreateBiTree(T);
    cout<<"森林一共有"<<CountForestTrees(T)<<"棵树"<<endl;

    return 0;
}

三、判断二叉树是否为完全二叉树

判断二叉树是否为完全二叉树的函数:

//完全二叉树的性质
bool check(BiTree T){
    if((T->lchild && T->rchild)||(!T->lchild && !T->rchild))
        return true;
    return false;
}       


//判断是否的完全二叉树
bool is_Complete_Binarytree(BiTree T){
    BiTree p=T;
    SqQueue Q;
    if(!T) return true;//空树也是完全二叉树
    InitQueue(Q);
    EnQueue(Q,p);
    while(!is_QueueEmpty(Q)){
        DeQueue(Q,p);
        if(!check(p)) return false;
        else{
            if(p->lchild) 
                EnQueue(Q,p->lchild);
		    if(p->rchild) 
                EnQueue(Q,p->rchild);
        }
    }
    return true;
}

(带main函数)题解代码示例:

//给定一个二叉树,找出其最小深度。
//最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

#include<iostream>
using namespace std;


//判断二叉树是否为完全二叉树

//结点定义入下:
//二叉链表
typedef struct BiTNode{
    char data;
    struct BiTNode *lchild,*rchild;
} BiTNode, *BiTree;

//若用到队列,请用循环队列,并请实现队列的相关操作以供调用。

#define MAXQSIZE 100

typedef struct {
    BiTree *base;
    int front,rear;
} SqQueue; //定义循环队列


//二叉树的建立的算法(按先序遍历序列建立)
void CreateBiTree(BiTree &T) {
	char ch; 
    scanf("%c",&ch);
    if (ch=='#') T = NULL;
    else {
        T = (BiTNode*)malloc(sizeof(BiTNode));
        T->data = ch;      // 生成根结点
        CreateBiTree(T->lchild); // 构造左子树
        CreateBiTree(T->rchild); // 构造右子树
    }
}
//队列的初始化
void InitQueue(SqQueue &Q){
    Q.base = (BiTree *)malloc(MAXQSIZE*sizeof(BiTree));
    Q.front = Q.rear = 0;//队列初始化
}

//队空
bool is_QueueEmpty(SqQueue Q){
    if(Q.rear==Q.front) return true;
    return false;
}

//队满
bool is_QueueMAX(SqQueue Q){
    if((Q.rear+1)%MAXQSIZE == Q.front) return true;
    return false;
}


//入队
void EnQueue(SqQueue &Q,BiTree e){
    if(!is_QueueMAX(Q)){
        Q.base[Q.rear]=e;
        Q.rear = (Q.rear + 1) % MAXQSIZE;
    }
    
    else{
        cout<<"ERROR!!! 队列已满"<<endl;
    }
}
//出队
void DeQueue(SqQueue &Q,BiTree &e){
    if(!is_QueueEmpty(Q)){
        e = Q.base[Q.front];
        Q.front = (Q.front + 1) % MAXQSIZE;
    }
    else{
        cout<<"ERROR!!! 队列为空"<<endl;
    }
}

//完全二叉树的性质
bool check(BiTree T){
    if((T->lchild && T->rchild)||(!T->lchild && !T->rchild))
        return true;
    return false;
}       


//判断是否的完全二叉树
bool is_Complete_Binarytree(BiTree T){
    BiTree p=T;
    SqQueue Q;
    if(!T) return true;//空树也是完全二叉树
    InitQueue(Q);
    EnQueue(Q,p);
    while(!is_QueueEmpty(Q)){
        DeQueue(Q,p);
        if(!check(p)) return false;
        else{
            if(p->lchild) 
                EnQueue(Q,p->lchild);
		    if(p->rchild) 
                EnQueue(Q,p->rchild);
        }
    }
    return true;
}

//层次遍历算法 
void LevelOrderTraverse(BiTree T)
{	BiTree p = T;
	SqQueue Q;
	
	
	if(!T) return;	
	
	InitQueue(Q); EnQueue(Q,p);
	while (!is_QueueEmpty(Q))
	{	DeQueue(Q,p);
		printf("%c ", p->data);
		if(p->lchild) EnQueue(Q,p->lchild);
		if(p->rchild) EnQueue(Q,p->rchild);
	}
}




int main(){
	 
	BiTree T;
	//例如输入:ABC##DE##F### 来创建二叉树 
	CreateBiTree(T);
    LevelOrderTraverse(T);
    cout<<endl;
    if(is_Complete_Binarytree(T)){
        cout<<"是完全二叉树"<<endl;
    }
    else{
        cout<<"不是完全二叉树"<<endl;
    }
	

	return 0; 
} 

四、求二叉树的最小深度 以及 二叉树树高

给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

求二叉树的最小深度的函数:

//直接就是将求树高的程序进行修改,将找左右子树最大树高 改为求左右子树 最小树高
//求二叉树的最小深度
int Get_minHeigt(BiTree T){
    //二叉树的最小深度
    if(T==NULL) return 0;
    else{
        int Left_Height = Get_minHeigt(T->lchild);
        int Right_Height = Get_minHeigt(T->rchild);
        int Tree_minHeight = 1+(Left_Height < Right_Height?Left_Height:Right_Height);//取最短路径
        return Tree_minHeight;
    }

}

(带main函数)题解代码示例:

//给定一个二叉树,找出其最小深度。
//最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

#include<iostream>
using namespace std;


typedef struct TreeNode{
	int data;//数据域
	TreeNode *rchild;//右孩子指针
	TreeNode *lchild;//左孩子指针
}TreeNode, *BiTree;


//二叉树的建立的算法(按先序遍历序列建立)
void CreateBiTree(BiTree &T) {
	char ch; 
    scanf("%c",&ch);
    if (ch=='#') T = NULL;
    else {
        T = (TreeNode*)malloc(sizeof(TreeNode));
        T->data = ch;      // 生成根结点
        CreateBiTree(T->lchild); // 构造左子树
        CreateBiTree(T->rchild); // 构造右子树
    }
}


//求树高 
int Get_Height(BiTree node){//递归 求树高 
	if(node==NULL) return 0;
	else{
		int Left_Height = Get_Height(node->lchild);
		int Right_Height = Get_Height(node->rchild);
		int Tree_Height = 1 + (Left_Height > Right_Height?Left_Height:Right_Height);//计算树高
    	return Tree_Height;
	}
	
}
//求二叉树的最小深度
int Get_minHeigt(BiTree T){
    //二叉树的最小深度
    if(T==NULL) return 0;
    else{
        int Left_Height = Get_minHeigt(T->lchild);
        int Right_Height = Get_minHeigt(T->rchild);
        int Tree_minHeight = 1+(Left_Height < Right_Height?Left_Height:Right_Height);//取最短路径
        return Tree_minHeight;
    }

}


int main(){
	 
	BiTree T;
	//例如输入:ABC##DE##F### 来创建二叉树 
	CreateBiTree(T);

	cout<<"树高为:" ;
	cout<<Get_Height(T)<<endl;
    cout<<"根节点到叶节点的最短路径上的节点数量为:";
    cout<<Get_minHeigt(T)<<endl;

	return 0; 
} 

感谢阅读!!!

  1. 树与二叉树知识点文章: 【数据结构】树与二叉树(递归法先序、中序、后序、层次遍历二叉树、二叉树的建立以及求树高的方法)
  2. 二叉树遍历算法的应用: 【数据结构】树与二叉树遍历算法的应用(求叶子节点个数、求树高、复制二叉树、创建二叉树、二叉树存放表达式、交换二叉树每个结点的左右孩子)
  3. 树与森林知识点文章: 【数据结构】树与森林(树的存储结构、森林与二叉树的转化、树与森林的遍历)
  4. 树与二叉树、树与森林部分习题: 【数据结构】树与二叉树、树与森林部分习题与算法设计例题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1599469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java小白教学—五千字带你了解多线程机制及线程安全问题

基础概念 &#x1f4d6; 问题一 : 什么是线程&#xff1f;线程和程序、进程有什么区别&#xff1f; 程序&#xff1a;为实现某种功能&#xff0c;使用计算机语言编写的一系列指令的集合。 指的是静态的代码&#xff08;例如安装在电脑上的那些文件&#xff09; 进程&#xff…

由于找不到msvcr120.dll,无法继续执行代码的详细处理方法,教你快修复msvcr120.dll

DLL文件&#xff0c;全称动态链接库文件&#xff0c;在计算机系统中具有重要作用。其中&#xff0c;msvcr120.dll是一个常见的DLL文件&#xff0c;它关联了许多程序和应用的正常运行。本指南将深入解释 msvcr120.dll文件的功能&#xff0c;并阐述如果缺少该文件会引起什么样的问…

C语言案例——输出以下图案(两个对称的星型三角形)

目录 图片代码 图片 代码 #include<stdio.h> int main() {int i,j,k;//先输出上半部图案for(i0;i<3;i){for(j0;j<2-i;j)printf(" ");for(k0;k<2*i;k)printf("*");printf("\n");}//再输出下半部分图案for(i0;i<2;i){for(j0;j&…

WebKit简介及工作流程

文章目录 一、WebKit简介二、WebKit结构三、Webkit工作流程四、WebKit常见问题五、WebKit优点六、相关链接 一、WebKit简介 WebKit是一个开源的浏览器引擎&#xff0c;它的起源可以追溯到2001年&#xff0c;当时苹果公司推出了其首款基于Unix的操作系统Mac OS X。在2002年&…

ST-LINK Utility 4.6.0 下载安装及使用方法介绍

一、介绍 STM32 ST-LINK Utility是针对STM32全系芯片进行编程&#xff08;读、写、擦除、选项字&#xff09;的一款工具。 STM32 ST-LINK Utility软件主要的功能就是量产&#xff08;批量下载代码的工具&#xff09;。它也是比较实用的一个工具&#xff0c;当我们需要查看芯片F…

BackTrader 中文文档(十)

原文&#xff1a;www.backtrader.com/ 用户自定义佣金 原文&#xff1a;www.backtrader.com/docu/user-defined-commissions/commission-schemes-subclassing/ 重塑 CommInfo 对象到实际形式的最重要部分涉及&#xff1a; 保留原始的 CommissionInfo 类和行为 为轻松创建用户定…

Android Material Design学习笔记

Material Design控件学习记录 Toolbar 新建一个工程后&#xff0c;在res/values/themes.xml文件里 <resources xmlns:tools"http://schemas.android.com/tools"><!-- Base application theme. --><style name"Theme.MaterialTest" paren…

【C++航海王:追寻罗杰的编程之路】异常——错误处理方式之一

目录 引言 1 -> C语言传统的处理错误的方式 2 -> C异常概念 3 -> 异常的使用 3.1 -> 异常的抛出和捕获 3.2 -> 异常的重新抛出 3.3 -> 异常规范 4 -> 自定义异常体系 5 -> C标准库的异常体系 6 -> 异常的优缺点 引言 在C编程中&#xff…

《剑指 Offer》专项突破版 - 面试题 110 : 所有路径(C++ 实现)

题目链接&#xff1a;所有路径 题目&#xff1a; 一个有向无环图由 n 个节点&#xff08;标号从 0 到 n - 1&#xff0c;n > 2&#xff09;组成&#xff0c;请找出从节点 0 到节点 n - 1 的所有路径。图用一个数组 graph 表示&#xff0c;数组的 graph[i] 包含所有从节点 …

javaWeb项目-游泳馆管理系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、SSM框架 开发信息…

机器学习实验------决策树

第1关&#xff1a;什么是决策树 任务描述 本关任务&#xff1a;根据本节课所学知识完成本关所设置的选择题。 第2关&#xff1a;信息熵与信息增益 任务描述 本关任务&#xff1a;掌握什么是信息增益&#xff0c;完成计算信息增益的程序设计。 import numpy as npdef calcIn…

3d视图模型乱了怎么调?---模大狮模型网

在进行3D建模时&#xff0c;有时候您可能会遇到视图模型混乱的情况。这可能是由于模型结构问题、导入导出错误或编辑操作不当等原因造成的。混乱的模型不仅影响工作效率&#xff0c;还可能导致渲染结果不理想。本文将介绍六种有效的方法来调整混乱的3D视图模型&#xff0c;帮助…

编程新手必看,Python3中函数知识点及语法学习总结(18)

介绍&#xff1a; Python3中的函数是组织好的、可重复使用的代码段&#xff0c;用于实现单一或相关联的功能。 以下是Python3中函数的一些基本介绍&#xff1a; 函数定义&#xff1a;在Python中&#xff0c;可以通过def关键字来定义一个函数。函数定义后&#xff0c;可以多次调…

从建表语句带你学习doris_表索引

1、doris建表概述 1.1、doris建表模板 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [DATABASE.]table_name (column_definition1[,column_deinition2,......][,index_definition1,[,index_definition2,]] ) [ENGINE [olap|mysql|broker|hive]] [key_desc] [COMMENT "tabl…

【Shell语言学堂】sed命令最全详解

三剑客之sed linux sed命令详解1.简介2.定址3.sed选项4.正则表达式元字符5.具体应用1、行打印2、替换指定文本3、插入文本行&#xff0c;追加文本行4、sed命令的删除功能5、其他命令6、sed 的分组替换功能7、sed -r或者sed -E linux sed命令详解 CSDN划过手的泪滴t 1.简介 se…

L2-1 堆宝塔分数

本题链接&#xff1a;PTA | 程序设计类实验辅助教学平台 题目&#xff1a; 样例&#xff1a; 输入 11 10 8 9 5 12 11 4 3 1 9 15 输出 4 5 思路&#xff1a; 这是一道模拟题&#xff0c;需要有耐心读题&#xff0c;跟着题目走一遍&#xff0c;就可以了。 代码详解如下&…

润乾报表平台 InputServlet 任意文件读取漏洞复现

0x01 产品简介 润乾报表是一个纯JAVA的企业级报表工具&#xff0c;支持对J2EE系统的嵌入式部署&#xff0c;无缝集成。服务器端支持各种常见的操作系统&#xff0c;支持各种常见的关系数据库和各类J2 EE的应用服务器&#xff0c;客户端采用标准纯html方式展现&#xff0c;支持…

基于SSM的游戏攻略管理系统

游戏攻略管理系统的构建与实现 一、系统概述二、系统架构与技术选型三、系统功能模块四、系统特点五、总结与展望 随着网络游戏的普及和发展&#xff0c;游戏攻略成为玩家们提升游戏技能、了解游戏机制的重要途径。为了更好地满足玩家需求&#xff0c;提高游戏攻略的管理效率和…

Xinstall:实现注册后自动绑定,提升用户体验

在移动互联网时代&#xff0c;App的注册与绑定流程对于用户体验至关重要。繁琐的注册步骤和手动绑定操作往往会让用户望而却步&#xff0c;导致用户流失。为了解决这一问题&#xff0c;Xinstall品牌推出了注册后自动绑定功能&#xff0c;极大提升了用户体验。 Xinstall的自动…

优惠券布局的最终方案------css属性mask

先贴图&#xff1a; 以上这些都是通过mask去实现出来&#xff1a; <!DOCTYPE html><html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…