《C++》解密--单链表

目录

一、概念与结构

二、实现单链表

三、链表的分类

四、单链表算法题


一、概念与结构

        1、节点

          结点的组成主要有:当前结点要保存的数据和保存下一个节点的地址(指针变量)

        图中指针变量plist保存的是第一个结点的地址,我们称plist此时“指向”第一个结点。

        链表中每个结点都是独立申请的(如果需要插入数据时才去申请一块结点的空间),我们需            要通过指针变量来保存下一个结点位置才能从当前结点找到下一个结点。

        2、链表的性质

【链表机构在逻辑上是连续的,在物理结构上不一定连续。

【结点一般是从堆上申请的。

【从堆上申请来的空间,是按照一定策略分配出来的,每次申请的空间可能连续,可能不连续。

  

二、实现单链表

 1、创立文件

 2、定义链表的结构

【SList.h】
//定义链表(结点)的位置
typedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;void SLTPrint(SLTNode* phead);

3、打印函数

【SList.h】
//打印函数
void SLTPrint(SLTNode* phead);
【SList.c】
//打印函数
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}
【test.c】
//创建一个链表,并且打印链表
void createSList()
{SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 2;SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 3;SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//第一个结点的地址作为参数传递过去SLTNode* plist = node1;SLTPrint(node1);
}

4、判断插入时,空间是否足够

【SList.c】
//判断插入数据时,空间是否足够
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));if (node == NULL){perror("malloc fail!");exit(1);}node->data = x;node->next = NULL;return node;
}

5、尾插

【SList.h】
//尾插
void SLTPushBack(SLTNode** pphead,SLTDataType x);
【SList.c】
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);//形参:pphead --> 实参:&plist//*pphead 解引用 --> plist//申请新结点SLTNode* newnode = SLTBuyNode(x); //判断是否有足够空间if (*pphead == NULL){*pphead = newnode;}else{//尾节点 --> 新结点//找尾节点SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}//ptail --> newnodeptail->next = newnode;}
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPrint(plist);  //1->NULLSLTPushBack(&plist, 2);SLTPrint(plist);  //1->2->NULLSLTPushBack(&plist, 3);SLTPrint(plist);  //1->2->3->NULLSLTPushBack(&plist, 4);SLTPrint(plist);  //1->2->3->4->NULL
}
【运行结果】

6、头插

【SList.h】
//头插
void SLTPushFront(SLTNode** pphead,SLTDataType x);
【SList.c】
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x); //判断是否有足够空间//newnode *ppheadnewnode->next = *pphead;*pphead = newnode;
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);   //4->3->2->1->NULL
}
【运行结果】

7、尾删

【SList.h】
//尾删
void SLTPopBack(SLTNode** pphead);
【SList.c】
//尾删
void SLTPopBack(SLTNode** pphead)
{//判断链表是不是空,若为空则不可以删assert(pphead && *pphead);//处理只有一个结点的情况:要删除的就是头结点(当next指针为空)if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{//找尾结点ptail 和尾结点的前一个结点prevSLTNode* ptail = *pphead;SLTNode* prev = NULL;//遍历数组,找尾结点while (ptail->next){prev = ptail;ptail = ptail->next;}prev->next = NULL;free(ptail);ptail = NULL;}
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);//尾删SLTPopBack(&plist);SLTPrint(plist);  //4->3->2->NULLSLTPopBack(&plist);SLTPrint(plist);  //4->3->NULLSLTPopBack(&plist);SLTPrint(plist);  //4->NULLSLTPopBack(&plist);SLTPrint(plist);  //NULL
}
【运行结果】

8、头删

【SList.h】
//头删
void SLTPopFront(SLTNode** pphead);
【SList.c】
//头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* next = (*pphead)->next;//删除*pphead --> nextfree(*pphead);*pphead = next;
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);//SLTPrint(plist);   //4->3->2->1->NULL//头删SLTPopFront(&plist);SLTPrint(plist);  //3->2->1->NULLSLTPopFront(&plist);SLTPrint(plist);  //2->1->NULLSLTPopFront(&plist);SLTPrint(plist);  //1->NULLSLTPopFront(&plist);SLTPrint(plist);  //NULL
}
【运行结果】

9、查找

【SList.h】
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
【SList.c】
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{assert(phead);SLTNode* pcur = phead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}//跳出循环,说明没找到return NULL;
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);//SLTPrint(plist);   //4->3->2->1->NULL//查找SLTNode* find = SLTFind(plist, 3);if (find == NULL){printf("没找到!\n");}else{printf("find it!\n");}
}
【运行结果】

10、在指定位置之前插入数据

【SList.h】
//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
【SList.c】
//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);//如果pos恰好是头结点if (pos == *pphead){SLTPushFront(pphead, x); //相当于头插}else{SLTNode* newnode = SLTBuyNode(x);//找到pos的前一个结点:prevSLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//跳出这个循环,说明prev的前一个结点就是pos//将newnode插入prev和pos之间newnode->next = pos;prev->next = newnode;}
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);   //4->3->2->1->NULL//查找SLTNode* find = SLTFind(plist, 2);//在指定位置之前插入数据SLTInsert(&plist, find, 11); //在2之前插入11SLTPrint(plist);   //4->3->11->2->1->NULL
}
【运行结果】

11、在指定位置之后插入数据

【SList.h】
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
【SList.c】
//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);//把newnode放到pos的下一个位置(pos->next)newnode->next = pos->next;pos->next = newnode;
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);   //4->3->2->1->NULL//查找SLTNode* find = SLTFind(plist, 2);//在指定位置之后插入数据SLTInsertAfter(find, 9);  //在2之后插入9SLTPrint(plist);  //4->3->2->9->1->NULL
}
【运行结果】

12、删除pos结点

【SList.h】
//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos);
【SList.c】
//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pos);assert(pphead && *pphead);//头插(如果pos恰好为头结点*pphead,那就没有前一个结点prev了)if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){ //遍历数组,寻找posprev = prev->next;}//跳出循环,prev刚好是pos的前一个结点(要删除pos)prev->next = pos->next;free(pos);pos = NULL;}}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);   //4->3->2->1->NULL//查找SLTNode* find = SLTFind(plist, 2);//删除pos结点SLTErase(&plist, find);  //删除pos(2)这个结点SLTPrint(plist);  //4->3->1->NULL
}
【运行结果】

13、删除pos之后的结点

【SList.h】
//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos);
【SList.c】
//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);//删除pos的下一个结点,就要让pos的下一个结点直接指向pos的next的next//但是后面要把pos->next释放删除掉,所以先把这个指针保存起来SLTNode* del = pos->next;pos->next = pos->next->next;free(del);del = NULL;
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);   //4->3->2->1->NULL//查找SLTNode* find = SLTFind(plist, 2);//删除pos之后的结点SLTEraseAfter(find);SLTPrint(plist);  //4->3->2->NULL
} 
【运行结果】

14、销毁链表

【SList.h】
//销毁链表
void SListDestroy(SLTNode** pphead);
【SList.c】
//销毁链表
void SListDestroy(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}
【test.c】
void SListTest01()
{SLTNode* plist = NULL;//头插SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);   //4->3->2->1->NULL//查找SLTNode* find = SLTFind(plist, 2);//销毁链表SListDestroy(&plist);SLTPrint(plist);  //NULL
} 
【运行结果】

三、链表的分类

四、单链表算法题

1、反转链表

【思路】

【代码】
typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head)
{//处理空链表if(head == NULL){return head;}//创建三个指针ListNode* n1,*n2,*n3;n1 = NULL , n2 = head , n3 = n2->next;   while(n2){n2->next = n1;n1 = n2;n2 = n3;if(n3){n3 = n3->next;}}//此时n1就是链表反转后新的头结点headreturn n1;
}

2、链表的中间结点

【思路】

【代码】
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {ListNode* slow = head,*fast = head;//慢指针每次走一步//快指针每次走两步while(fast && fast->next)  //等价于fast!=NULL && fast->next!=NULL
//当fast或fast->fast任何一个为空指针(为假)时,就跳出循环{slow = slow->next;fast = fast->next->next;}//此时slow指向得节点刚好就是中间节点return slow;}

3、合并两个有序链表

【思路】

【代码】
typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{//处理链表为空的情况if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}//创建新链表ListNode*newHead = NULL,*newTail = NULL;//创建两个指针分别指向两个链表的头结点ListNode* l1 = list1;ListNode* l2 = list2;//比大小while(l1 && l2){if(l1->val < l2->val){//l1尾插到新链表中if(newHead == NULL){newHead = newTail = l1;}else{newTail->next = l1;newTail = newTail->next;}l1 = l1->next;}else{//l2尾插到新链表if(newHead == NULL){newHead = newTail = l2;}else{newTail->next = l2;newTail = newTail->next;}l2 = l2->next;}}//跳出while循环,只有两种情况:l1为空(l2肯定不为空) 或 l2为空(l1不为)if(l1)  //l1不为空{newTail->next = l1;}if(l2)  //l2不为空{newTail->next = l2;}return newHead;
}

4、链表分割

【思路】

【代码】
class Partition 
{
public:ListNode* partition(ListNode* pHead, int x) { //创建两个非空链表:小链表、大链表//小链表ListNode* lessHead,*lessTail;lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));//大链表 ListNode* greaterHead,*greaterTail;greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));//遍历原链表,与x比较大小// >=x的尾插进入大链表 , <x的尾插进入小链表ListNode* pcur = pHead;while(pcur)  //等价于pcur != NULL{if(pcur->val < x){ //尾插到小链表lessTail->next = pcur;lessTail = lessTail->next;}else { //尾插到大链表greaterTail->next = pcur;greaterTail = greaterTail->next;}pcur = pcur->next;}//将大链表的尾结点的next置为空greaterTail->next = NULL;//让大小链表首尾相连lessTail->next = greaterHead->next;ListNode* ret = lessHead->next;free(lessHead);free(greaterHead);lessHead = greaterHead = NULL;return ret;}
};

5、链表的回文结构

【代码】
class PalindromeList 
{
public:
ListNode* findMidNode(ListNode* phead)
{//使用快慢指针,寻找中间结点ListNode* slow = phead;ListNode* fast = phead;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;
}ListNode* reverseList(ListNode* phead)
{//链表反转ListNode* n1,*n2,*n3;n1 = NULL;n2 = phead;n3 = n2->next;while(n2){n2->next = n1;n1 = n2;n2 = n3;if(n3){n3 = n3->next;}}return n1;
}bool chkPalindrome(ListNode* A) {//1、找中间结点ListNode* mid = findMidNode(A);//2、根据中间结点,将中间结点后的链表反转ListNode* right = reverseList(mid);//3、从原链表的头和反转链表比较结点值 (开始时,left指头,right指尾)ListNode* left = A;while(right){if(left->val != right->val){return false;}left = left->next;right = right->next;}return true;}
};

未完待续...

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

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

相关文章

第十七章:c语言内存函数

1. memcpy使⽤和模拟实现 2. memmove使⽤ 3. memset函数的使⽤ 4. memcmp函数的使⽤ 天行健 君子以自强不息一、memcpy的使用和模拟实现 作用&#xff1a; 1. 函数memcpy从source的位置向后复制num个字节的数据到destination指向的内存位置。 2. 这个函数在遇到‘\0’的时…

MySQL - 进阶篇

一、存储引擎 1. MySQL体系结构 2. 存储引擎简介 3. 存储引擎特点 4. 存储引擎选择 二、索引 1. 索引概述 2. 索引结构 3. 索引分类 4. 索引语法 5. SQL性能分析 6. 索引使用 7. 索引设计原则 三、SQL优化 1. 插入数据 2. 主键优化 3. order by优化 4. group by优化 5. limi…

图像处理案例04

图像处理 问题&#xff1a;把不规则的图片按照参考图摆放 步骤&#xff1a; 1. 用ORB找关键点 2. 关键点匹配 3. 根据上一步匹配的关键点得出单应性矩阵 4. 根据单应性矩阵对不规则进行透视变换 import cv2 import numpy as np import matplotlib.pyplot as pltimgl cv2.imrea…

Hive数仓操作(五)

一、Hive 信息查看 Hive的元数据管理&#xff1a; Hive 将表的元数据&#xff08;如表名、列名、类型等&#xff09;存储在关系型数据库中&#xff0c;通常是 MySQL。元数据的主要表包括&#xff1a; TBLS&#xff1a;存储表的信息&#xff08;表名、类型、ID 等&#xff09;。…

【小程序】微信小程序课程 -4 项目实战

目录 1、 效果图 2、创建项目 2.1 创建小程序端 2.1.1 先创建纯净项目 2.1.2 删除components 2.1.4 删除app.json红色部分 2.1.5 删除index.json红色部分 2.1.6 删除index.wxss全部内容 2.1.7 删除index.wxml全部内容 2.1.8 app.json创建4个页面 2.1.9 app.json添加…

15年408计算机网络

第一题&#xff1a; 解析&#xff1a; 接收方使用POP3向邮件服务器读取邮件&#xff0c;使用的TCP连接&#xff0c;TCP向上层提供的是面向连接的&#xff0c;可靠的数据传输服务。 第二题&#xff1a; 解析&#xff1a;物理层-不归零编码和曼彻斯特编码 编码1&#xff1a;电平在…

GAMES101(作业8)

作业8 题目&#xff1a; 模拟绳子动画&#xff0c;包括基于物理的&#xff0c;和非物理的&#xff0c;应该修改的函数是:rope.cpp 中的void Rope::simulateEuler(... Rope::rope(...)&#xff0c;&#xff0c;void Rope::simulateVerlet(...) 代码框架&#xff1a; main:负…

centos磁盘逻辑卷LVM创建

centos磁盘逻辑卷LVM创建 一、磁盘逻辑卷LVM说明二、centos磁盘使用情况三、LVM安装指南1.LVM工具安装1. yum list lvm2. yum search lvm3. yum search pvcreate4. yum list lvm25. yum install lvm2 2.创建物理卷2.1磁盘情况查看2.2创建物理卷&#xff08;PV&#xff09; 3.创…

使用Postman工具接口测试

文章目录 一、接口1.1 接口的概念1.2 接口的类型 二、接口测试2.1 概念2.2 原理2.3 特点 三、HTTP协议3.1 http协议简介3.2 URL格式3.3 HTTP请求3.3.1 请求行3.3.2 请求头3.3.3 请求体 3.4 HTTP响应3.4.1 状态行3.4.2 响应头3.4.3 响应体 3.4 传统风格接口3.5 RESTful风格接口 …

Race Karts Pack 全管线 卡丁车赛车模型素材

是8辆高细节、可定制的赛车,内部有纹理。经过优化,可在手机游戏中使用。Unity车辆系统已实施-准备驾驶。 此套装包含8种不同的车辆,每种车辆有8-10种颜色变化,总共有75种车辆变化! 技术细节: -每辆卡丁车模型使用4种材料(车身、玻璃、车轮和BrakeFlare) 纹理大小: -车…

基于单片机的可调式中文电子日历系统

** 文章目录 前言概要功能设计软件设计效果图 程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们…

如何在O2OA中使用ElementUI组件进行审批流程工作表单设计

本文主要介绍如何在O2OA中进行审批流程表单或者工作流表单设计&#xff0c;O2OA主要采用拖拽可视化开发的方式完成流程表单的设计和配置&#xff0c;不需要过多的代码编写&#xff0c;业务人员可以直接进行修改操作。 在流程表单设计界面&#xff0c;可以在左边的工具栏找到Ele…

文心一言 VS 讯飞星火 VS chatgpt (357)-- 算法导论24.2 3题

三、上面描述的 PERT 图的公式有一点不太自然。在一个更自然的结构下&#xff0c;图中的结点代表要执行的工作&#xff0c;边代表工作之间的次序限制&#xff0c;即边 (u&#xff0c;v) 表示工作 u 必须在工作 v 之前执行。在这种结构的图中&#xff0c;我们将权重赋给结点&…

httpsok-v1.17.0-SSL通配符证书自动续签

&#x1f525;httpsok-v1.17.0-SSL通配符证书自动续签 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具&#xff0c;基于全新的设计理念&#xff0c;专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业&#xff0c;稳定、安全、可靠。 一行命令&#xff0c;一分钟轻…

LQR算法核心思想

本章以倒立摆为解决目的 什么是线性二次型控制器&#xff08;LQR&#xff09; 开环系统 即状态变量的倒数 系统的状态空间矩阵A * 系统状态变量x A状态矩阵&#xff1a;描述系统本身物理特性的一个矩阵&#xff0c;它是由系统本身的机械结构、物理结构决定的&#xff0c;无法…

【漏洞复现】VEXUS多语言货币交易所存在未授权访问漏洞

漏洞描述 java后端,非常完整的一套交易所,UI前端做的也很漂亮,新增了交易跟单功能,前端pc+wap都是uniapp纯源码,前端源码node_modules环境已经安装好了,拿去直接编译就可以. 后端 前端 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共…

ARM 服务器上安装 OpenEuler (欧拉)

系统介绍 在 2019 年 7 月 19 日&#xff0c;华为宣布要在年底正式开源 openEuler 操作系统&#xff1b;在半年后的 12 月 31 日&#xff0c;华为正式开源了 openEuler 操作系统&#xff0c;邀请社区开发者共同来贡献。 一年后&#xff0c;截止到 2020 年12 月 25日&#xff…

第167天:应急响应-日志自动提取分析项目_ELK_Logkit_LogonTracer_Anolog等

目录 案例一&#xff1a; 日志自动提取-七牛Logkit&观星应急工具 Logkit 观星 案例二&#xff1a;日志自动分析-Web-360 星图&Goaccess&ALB&Anolog 360 星图 GoAccess ALB Anolog f8x 案例一&#xff1a; 日志自动提取-七牛Logkit&观星应急工具 …

Webpack 特性探讨:CDN、分包、Tree Shaking 与热更新

文章目录 前言包准备CDN 集成代码分包Tree Shaking原理实现条件&#xff1a;解决 treeShaking 无效方案&#xff1a;示例代码&#xff1a; 热更新&#xff08;HMR&#xff09; 前言 Webpack 作为现代前端开发中的核心构建工具&#xff0c;提供了丰富的特性来帮助开发者优化和打…

介绍GPT-o1:一系列解决困难问题( science, coding, and math )的推理模型

openai o1介绍 一、官方技术报告要点剖析实验1 benchmark分析实验2:和phd比赛技术细节&#xff1a;Chain of Thought的使用人类偏好评估Human preference evaluationsatety技术细节&#xff1a;隐藏思维链为监控模型提供了机会:)openai的几点conclusion 二、官方介绍剖析 Intro…