【推荐】二叉树的递归与非递归遍历实现

二叉树的递归和非递归遍历 参考: 阅读详情

  对于二叉树,有前序、中序以及后序三种遍历方法。因为树的定义本身就 是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁。

而对于树的遍历若采用非递归的方法,就要采用栈去模拟实现。

在三种遍历 中,前序和中序遍历的非递归算法都很容易实现,非递归后序遍历实现起来相对来说要难一点。

一.前序遍历

   前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。

   1. 递归实现

void preOrder1(BinTree *root)     //递归前序遍历 
{
    if(root!=NULL)
    {
         cout<<root->data<<" ";
         preOrder1(root->lchild);
         preOrder1(root->rchild);
     }
 }

    2.非递归实现  

           根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。

即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;

当访问其左子树完时,再访问它的右子树,因此其处理过程如下:

 对于任一结点P:

     1) 访问结点P,并将结点P入栈;

     2) 判断结点P的左孩子是否为空,

      若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);

      若不为空,则将P的左孩子置为当前的结点P;

     3) 直到P为NULL并且栈为空,则遍历结束。

void preOrder2(BinTree *root)     //非递归前序遍历 
{
    stack<BinTree*> s;
    BinTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->rchild;
        }
    }
}

 

二.中序遍历

  中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。

  1. 递归实现

 void inOrder1(BinTree *root)      //递归中序遍历
 {
     if(root!=NULL)
    {
         inOrder1(root->lchild);
         cout<<root->data<<" ";
         inOrder1(root->rchild);
     }
}

  2.非递归实现

  根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,然后按相同的规则访问其右子树。因此其处理过程如下:

  对于任一结点P,

   1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;

   2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;

   3)直到P为NULL并且栈为空则遍历结束。

  void inOrder2(BinTree *root)      //非递归中序遍历
  {
      stack<BinTree*> s;
      BinTree *p=root;
      while(p != NULL || !s.empty())
      {
         //左节点入栈
          while(p != NULL)
          {
              s.push(p);
             p=p->lchild;
         }
        //处理根节点
         if(!s.empty())
         {
             p=s.top();
             cout<<p->data<<" ";
             s.pop();
             //下次处理右节点
             p=p->rchild;
         }
     }    
 } 

 

三.后序遍历

       后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。

       1. 递归实现

 void postOrder1(BinTree *root)    //递归后序遍历
 {
     if(root!=NULL)
     {
         postOrder1(root->lchild);
         postOrder1(root->rchild);
         cout<<root->data<<" ";
     }    
 }

  2. 非递归实现

  后序遍历的非递归实现是三种遍历方式中最难的一种。因为在后序遍历中,要保证左孩子和右孩子都已被访问并且左孩子在右孩子前访问才能访问根结点,这就为流程的控制带来了难题。下面介绍两种思路。

      第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,此时该结点出现在栈顶,但是此时不能将其出栈并访问, 因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就 保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是 否是第一次出现在栈顶。

 

  void postOrder2(BinTree *root)    //非递归后序遍历
 {
     stack<BTNode*> s;
     BinTree *p=root;
     BTNode *temp;
     while(p!=NULL||!s.empty())
     {
         while(p!=NULL)              //沿左子树一直往下搜索,直至出现没有左子树的结点 
         {
             BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
             btn->btnode=p;
             btn->isFirst=true;
             s.push(btn);
             p=p->lchild;
         }
         if(!s.empty())
         {
             temp=s.top();
             s.pop();
             if(temp->isFirst==true)     //表示是第一次出现在栈顶 
              {
                 temp->isFirst=false;
                 s.push(temp);
                 p=temp->btnode->rchild;    
             }
             else                        //第二次出现在栈顶 
              {
                 cout<<temp->btnode->data<<" ";
                 p=NULL;
             }
         }
     }    
 }

  【推荐】第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存 在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了 每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

 void postOrder3(BinTree *root)     //非递归后序遍历
 {
     stack<BinTree*> s;
     BinTree *cur;                      //当前结点 
     BinTree *pre=NULL;                 //前一次访问的结点 
     s.push(root);
     while(!s.empty())
     {
         cur=s.top();
         if((cur->lchild==NULL&&cur->rchild==NULL)||
            (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
         {
             cout<<cur->data<<" ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过 
               s.pop();
             pre=cur; 
         }
         else
         {
             if(cur->rchild!=NULL)
                 s.push(cur->rchild);
             if(cur->lchild!=NULL)    
                 s.push(cur->lchild);
         }
     }    
 }

 

四.整个程序完整的代码

 

  /*二叉树的遍历* */ 
 #include <iostream>
 #include<string.h>
 #include<stack> 
 using namespace std;
 
 typedef struct node
 {
     char data;
     struct node *lchild,*rchild;
 }BinTree;
 
 typedef struct node1
 {
     BinTree *btnode;
     bool isFirst;
 }BTNode;
 
 
 void creatBinTree(char *s,BinTree *&root)  //创建二叉树,s为形如A(B,C(D,E))形式的字符串 
 {
     int i;
     bool isRight=false;
     stack<BinTree*> s1;          //存放结点 
     stack<char> s2;              //存放分隔符
     BinTree *p,*temp;
     root->data=s[0];
     root->lchild=NULL;
     root->rchild=NULL;
     s1.push(root);
     i=1;
     while(i<strlen(s))
     {
         if(s[i]=='(')
         {
             s2.push(s[i]);
             isRight=false;
         }    
         else if(s[i]==',')    
         {
             isRight=true;
         }
         else if(s[i]==')')
         {
             s1.pop();
             s2.pop();
         }
         else if(isalpha(s[i]))
         {
             p=(BinTree *)malloc(sizeof(BinTree));
             p->data=s[i];
             p->lchild=NULL;
             p->rchild=NULL;
             temp=s1.top();
             if(isRight==true)    
             {
                 temp->rchild=p;
                 cout<<temp->data<<"的右孩子是"<<s[i]<<endl;
             }
             else
             {
                 temp->lchild=p;
                 cout<<temp->data<<"的左孩子是"<<s[i]<<endl;
             }
             if(s[i+1]=='(')
                 s1.push(p);
         }
         i++;
     }    
 }
 
 void display(BinTree *root)        //显示树形结构 
 {
     if(root!=NULL)
     {
         cout<<root->data;
         if(root->lchild!=NULL)
         {
             cout<<'(';
             display(root->lchild);
         }
         if(root->rchild!=NULL)
         {
             cout<<',';
             display(root->rchild);
             cout<<')';
         }
     }
 }
 
 void preOrder1(BinTree *root)     //递归前序遍历 
 {
     if(root!=NULL)
     {
         cout<<root->data<<" ";
         preOrder1(root->lchild);
         preOrder1(root->rchild);
     }
 }
 
 void inOrder1(BinTree *root)      //递归中序遍历
 {
     if(root!=NULL)
     {
         inOrder1(root->lchild);
         cout<<root->data<<" ";
         inOrder1(root->rchild);
     }
 } 
 
 void postOrder1(BinTree *root)    //递归后序遍历
 {
     if(root!=NULL)
     {
         postOrder1(root->lchild);
         postOrder1(root->rchild);
         cout<<root->data<<" ";
     }    
 } 
 
 void preOrder2(BinTree *root)     //非递归前序遍历 
 {
     stack<BinTree*> s;
     BinTree *p=root;
     while(p!=NULL||!s.empty())
     {
         while(p!=NULL)
         {
             cout<<p->data<<" ";
             s.push(p);
             p=p->lchild;
         }
         if(!s.empty())
         {
             p=s.top();
             s.pop();
             p=p->rchild;
         }
     }
 }
 
 void inOrder2(BinTree *root)      //非递归中序遍历
 {
     stack<BinTree*> s;
     BinTree *p=root;
     while(p!=NULL||!s.empty())
     {
         while(p!=NULL)
         {
             s.push(p);
             p=p->lchild;
         }
         if(!s.empty())
         {
             p=s.top();
             cout<<p->data<<" ";
             s.pop();
             p=p->rchild;
         }
     }    
 } 
 
 void postOrder2(BinTree *root)    //非递归后序遍历
 {
     stack<BTNode*> s;
     BinTree *p=root;
     BTNode *temp;
     while(p!=NULL||!s.empty())
     {
         while(p!=NULL)              //沿左子树一直往下搜索,直至出现没有左子树的结点 
          {
             BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
             btn->btnode=p;
             btn->isFirst=true;
             s.push(btn);
             p=p->lchild;
         }
         if(!s.empty())
         {
             temp=s.top();
             s.pop();
             if(temp->isFirst==true)     //表示是第一次出现在栈顶 
              {
                 temp->isFirst=false;
                 s.push(temp);
                 p=temp->btnode->rchild;    
             }
             else                        //第二次出现在栈顶 
              {
                 cout<<temp->btnode->data<<" ";
                 p=NULL;
             }
         }
     }    
 } 
 
 void postOrder3(BinTree *root)     //非递归后序遍历
 {
     stack<BinTree*> s;
     BinTree *cur;                      //当前结点 
     BinTree *pre=NULL;                 //前一次访问的结点 
     s.push(root);
     while(!s.empty())
     {
         cur=s.top();
         if((cur->lchild==NULL&&cur->rchild==NULL)||
            (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
         {
             cout<<cur->data<<" ";  //如果当前结点没有孩子结点或者孩子节点都已被访问过 
               s.pop();
             pre=cur; 
         }
         else
         {
             if(cur->rchild!=NULL)
                 s.push(cur->rchild);
             if(cur->lchild!=NULL)    
                 s.push(cur->lchild);
         }
     }    
 }
 
 
 int main(int argc, char *argv[])
 {
     char s[100];
     while(scanf("%s",s)==1)
     {
         BinTree *root=(BinTree *)malloc(sizeof(BinTree));
         creatBinTree(s,root);
         display(root);
         cout<<endl;
         preOrder2(root);
         cout<<endl; 
         inOrder2(root);
         cout<<endl;
         postOrder2(root);
         cout<<endl;
         postOrder3(root);
         cout<<endl;
     }
     return 0;
 }
二叉树按层遍历 这学期学数据结构,觉得写代码好麻烦,不过它让代码的结构改善很多,再难还是要学的..对于二叉树,遍历方法有先序遍历,中序遍历,后续遍历,按层遍历.这里要讲的是按层遍历.有两种方法,第一种是递归,时间效率较低,另一种就是是充分运用了队列的性质,省去了了重复遍历的时间.(偷了个懒,,队列直接用了STL系列函数) 代码如下: #include #include #include using names 阅读详情

相关推荐

AI大模型驱动Web UI自动化测试:Playwright与RobotFramework智能整合实践

Web自动化测试是软件质量保障的关键环节,其核心原理是通过脚本模拟用户操作,对Web应用界面进行功能验证。传统方法依赖固定的元素定位和脚本逻辑,在应对频繁的UI变更时面临维护成本高、脚本脆弱的挑战。随着AI大模型技术的发展,其强大的自然语言理解和代码生成能力为自动化测试带来了新的技术价值。通过将大模型的意图理解与代码生成能力,与Playwright强大的浏览器自动化执行引擎以及RobotFramework灵活的关键字驱动框架相结合,可以构建出能够理解自然语言指令、动态生成稳定操作脚本的智能测试系统。这种融合

weixin_28718769的博客 412

二叉树遍历输出的递归和非递归实现

根据二叉树遍历操作的递归定义,可以很容易的写出在二叉树

cherish_xmm的专栏 700

Ansys CFX Pre 中 RGP 表的高级配置与优化策略

本文深入探讨了Ansys CFX Pre中RGP表的高级配置与优化策略,旨在帮助用户将仿真从“能用”提升至“精准好用”。文章重点解析了如何根据具体仿真场景,科学设定温度压力范围、选择流体类型,并针对相变等复杂工况实施网格加密与分离建表等关键优化技术,以显著提升计算精度与稳定性。

weixin_29216957的博客 1180

4.2 二叉树递归和非递归遍历(结合栈)

一、注意点 1、<stack>头文件 入栈,s.push(x); 出栈,s.pop(); (出栈操作只是删除栈顶元素,并不返回该元素) 访问栈顶,s.top() 判断栈空,s.empty(),当栈空时,返回true。 访问栈中的元素个数,s.size() stack<BinTree*> s; /...

justlikeatree的博客 272

MNE-python 进行源定位教程(一)配置环境

根据MNE官网提供的教程进行复现,遇到各种问题的记录。 配置环境 python3.8 + Anaconda + pycharm MNE-Python 是一个开源 Python 模块,用于处理、分析和可视化功能性神经影像数据(EEG、MEG、sEEG、ECoG 和 fNIRS)。 根据官方建议,将MNE-python安装在anaconda的虚拟环境中。 1. 安装Anaconda 过程点击这里 2. 配置pycharm 2.1 导入MNE-python工具包 在pycharm的菜单栏里打开VCS-Create

zQIANYUN的博客 3173

Vue3 - H5实现省市区三四级联动组件,选择地址自定义省市区三级联动插件,弹框式多级联动选择器区域选择,vue3实现省市区三级联动地址选择组件(支持接口数据懒加载,样式精美漂亮,附带详细示例源码)

vue3实现省市区三级联动地址选择组件(附address文件),vue3实现省市区三级联动, 实现省、市、县地区三级联动功能,vue3省市区选择器,VUE3 h5如何实现省市区街道的四级联动选择,vue实现省市区选择联动,vue3城市三级联动(自定义组件)_VUE三级联动,插件省市区联动,vue如何实现省市区选择器,vue3怎样实现省市区地址三级联动,vue四级联动,vue3级联选择器,vue3实现选择省市区镇(街道)四级级联选择,包含三级级联选择,省市区街道三级四级联动选择器,VUE3自定义多列选择器省市

🏆 前端领域优质创作者 3068

二叉树的遍历

一、前序遍历 1.递归算法void preOrder1(BinTree *root) //递归前序遍历 { if(root!=NULL) { cout<<root->data<<" "; preOrder1(root->lchild); preOrder1(root->rchild); } }2.非递归算法 1)访

Lethe_Allofyou的博客 440

100天精通Oracle-实战系列(第14天)Veritas NetBackup(NBU) 配合 RMAN 脚本备份 Oracle 数据库

100天精通Oracle-实战系列(第14天)Veritas NetBackup(NBU) 配合 RMAN 脚本备份 Oracle 数据库

LuciferLiu_DBA 1993

二叉树几种遍历算法

"font-size:14px;">/*二叉树的遍历*/      #include    #include    #include    using namespace std;      typedef struct node   {       char data;       struct node *lchild,*rchild;   }BinTree;     

augustusking的专栏 388

AutoSar实战营 - 总目录

欢迎大家来学习《AutoSar实战营》专栏,该篇为总目录,方便以后大家直接进入需要学习的文章。 ~正所谓独乐乐不如众乐乐 - - ~1, AutoSar之DaVinci开发环境2,BswM模块之Ecu State Handling1)读写DID功能 《AutoSar实战》读写DID之一:CDD准备 《AutoSar实战》读写DID之二:工具链配置 《AutoSar实战》读写DID之三:代码实现2)功能寻址 《AutoSar实战》禁止功能寻址

weixin_48498880的博客 3626

【WorkBuddy专栏27】WorkBuddy 和 CodeBuddy 到底什么关系——一篇文章终结所有混淆

WorkBuddy 和 CodeBuddy 到底什么关系——一篇文章终结所有混淆

AI人人懂 2641

二叉树的递归+非递归遍历

/* * 二叉树的遍历 2011.8.25 * 作者:海子 * 出处:http://www.cnblogs.com/dolphin0520/ */ /*二叉树的非递归遍历 二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。 对于二叉树,有前序、中序以及后序三种遍历方法。因为树的定义本身就是递归定义, 因此采用递归的方法去...

weixin_30612769的博客 128

绘制Winform动态折线图,LiveCharts如何打造数据可视化神器?

在C# Winform应用程序中,使用LiveCharts库来创建动态、美观的折线图不仅能够提升用户体验,还能直观展示数据趋势。下面,我们将通过一个详尽的示例,展示如何在Winform项目中集成LiveCharts并绘制折线图。:在Visual Studio中,选择“文件” > “新建” > “项目”,然后选择“Windows Forms 应用(.NET)”模板。LiveCharts的强大之处在于其高度的可定制性,你可以根据需求调整颜色、动画效果、交互方式等,让图表更加符合你的应用需求。

java专栏 1683

【数据结构】二叉树遍历(递归遍历和非递归遍历)

学而不思则罔,思而不学则殆 【数据结构】二叉树遍历二叉树递归遍历递归前序遍历递归中序遍历递归后序遍历二叉树相关学习的网站 二叉树 定义:每个节点最多有两个子树的数成为二叉树 递归遍历 public class TreeNode { TreeNode left; TreeNode right; char values; public TreeNode(char values) { this.values = values; } } 递归前序遍历

珍心 1879

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

二叉树中序遍历(多种方式实现,C语言详解版)

遍历二叉树的方式有很多种,比如本文要详细讲解的中序遍历,以及层次遍历、先序遍历和后序遍历。二叉树的中序遍历,指的是从根结点出发,按照以下步骤访问二叉树举个简单的例子,下图是一棵二叉树:图 1 二叉树中序遍历这棵二叉树的过程是:进入结点 1 的左子树,访问左子树中的结点;进入结点 2 的左子树,访问左子树中的结点;试图进入结点 4 的左子树,但该结点没有左子树;访问结点 4;试图进入结点 4 的右子树,但该结点没有右子树;访问结点 2;

数据结构和算法教程(C语言版) 1606

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

JavaScript实现二叉树前中后序遍历,程序员必学

疯狂编程学习效果可视化写博客阅读优秀代码心态调整题大厂面试还是很注重算法题的,尤其是字节跳动,算法是问的比较多的,关于算法,推荐《LeetCode》和《算法的乐趣》,这两本我也有电子版,字节跳动、阿里、美团等大厂面试题(含答案+解析)、学习笔记、Xmind思维导图均可以分享给大家学习。

m0_60452141的博客 743

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

day13——二叉树的理论基础,构建,遍历

二叉树的构建,以及二叉树的3种遍历方式且1分别采用递归遍历和迭代遍历

cyz322649的博客 843

二叉树的三种遍历方式,含demo(递归与非递归)

看完美团、字节、腾讯这三家的一二三面试问题,是不是感觉问的特别多,可能咱们真的又得开启面试造火箭、工作拧螺丝的模式去准备下一次的面试了。开篇有提及我可是足足背下了Java互联网工程师面试1000题,多少还是有点用的呢,换汤不换药,不管面试官怎么问你,抓住本质即可!能读到此处的都是真爱Java互联网工程师面试1000题。

q16974058的博客 659

JAVA-二叉树的四种遍历

选:A提升难度:根据已知条件去构建这颗二叉树:3.设一课二叉树的中序遍历序列:badce,后序遍历序列:bdeca,则二叉树前序遍历序列为()选:D4.某二叉树的后序遍历序列与中序遍历序列相同,均为ABCDEF,则按层次输出同一层从左到右的序列为()同理一样,选A四、代码实现首先有一个二叉树的类。

Lizhihao_的博客 1592

Java代码实现二叉树前序中序后序层序遍历

Java代码实现二叉树前序中序后序层序遍历 Node结点类 public class Node { // 左子结点 public Node left; // 右子结点 public Node right; // 结点的值 public String value; public Node(String value) { this.value = value; } @Override public String

Wxc的Blog 328

二叉树及其三种序的递归实现

一,递归序和递归理解 #include<iostream> //递归的基础样例,用来理解递归。 struct TreeNode { int value; TreeNode* left; TreeNode* right; }; void f(TreeNode* root) { if (root == NULL) return; //1 //当到达该节点时的操作。 f(root->left); //去遍历根节点的左子树。 //2 //遍历完左子树后进行的操作 f(ro

2401_86679269的博客 850

数据结构——二叉树(相关术语、性质、遍历过程)

因为之前发过一遍,我就不复制粘贴了(要不然内容太多太乱,看不过去)。另外,我觉得下面这个博主写的超赞,可以看一下。

m0_75017568的博客 733

树的前、中、后、层序遍历的模板以及使用场景推荐

介绍下树的前、中、后遍历以及层序遍历,以及使用场景推荐。 前、中、后遍历 递归式 // 以前序举例,此例可输出二叉树的前序遍历。实际使用中可将result.add(root.val)灵活变动为其他语句。 class Solution { ArrayList<Integer> preOrderReverse(TreeNode root) { ArrayList<Integer> result = new ArrayList<Integer>();

weixin_44554795的博客 504

[LeetCode]94. 二叉树的中序遍历(java实现)二叉树遍历模板题

[LeetCode]94. (java实现)1. 题目2. 读题(需要重点注意的东西)3. 解法4. 可能有帮助的前置习题5. 所用到的数据结构与算法思想6. 总结 1. 题目 2. 读题(需要重点注意的东西) 思路: 3. 解法 ---------------------------------------------------解法---------------------------------------------------: 可能存在的问题: 4. 可能有帮助的前置习题 5. 所用到的数据

cloud的博客 518

二叉树的中序、前序和后序遍历(C++)

二叉树的中序、前序和后序遍历(C++)

weixin_44810568的博客 968
上一篇: redis cluster 性能探讨
下一篇: 环形加油站问题
大树叶
博客等级 码龄12年 1171粉丝 664原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值