13 二叉树:建立存储结构(前序输入次序) &&二叉树专题

2023-10-27

目录

首先讲讲指针的引用 *&

然后我们再复习一下typedef的用法。

然后我们来创建二叉树

二叉树的建立

首先二叉树的存储结构(实际用代码体现)分为顺序存储和链式存储两种,但一般情况我们都用链式存储结构。

部分内容转自指针的引用 *&_MAGDB的博客-CSDN博客_指针的引用

首先讲讲指针的引用 *&

以下代码
 

void shit(student *p)
{
p->data=0;
p=p->next;
}

void shit2(student &*p)
{
p->data=0;
p=p->next;
}

请问shit函数和shit2函数有什么区别呢? 

对于p->data这一步两个函数都可以修改实参的data值。

但是重点来了

对于p=p->next;这一步,shit不可以让实参中的p指向下一位,而shit2可以改变实参的下一位。

以下为转载。

注意:
能否理解的重点是
如果不是指针引用
指针的指向改变并不能影响原指针的指向
指针指向的值的改变可以影响到原值

也就是说
如果不是指针引用,
形参指针指向改变对实参指针指向没有影响,
形参指针指向值大小改变,实参指针指向值大小随之改变

然后我们再复习一下typedef的用法

//以下代码run under c language

typedef struct tagPOINT
{
    int x;
    int y;
}POINT;
//那么POINT a相当于struct tagPOINT a;

typedef struct tagPOINT
{
    int x;
    int y;
}POINT,* k;
//那么struct tagPOINT * a相当于k a;

然后我们来创建二叉树

struct student
{
	char data;
	student* left;
	student* right;
};

我习惯用student来包装所有目标物,大家习惯就好。

书上一般都是先告诉你遍历的种类,然后再教你如何建立二叉树。

因为下面的建立需要用的遍历的知识。但其实你不知道遍历也可以。我觉得应该先写如何建立二叉树,然后再来介绍遍历的种类。

下面是用的先序遍历来建立二叉链表

//此方法是先序遍历顺序建立二叉链表
void creat(student *&T)
{
	char ch;
	cin >> ch;
	if (ch == '#')
	{
		T = NULL;
	}//但凡输入了#号 就代表这是个空树
	else
	{
		T = new student;
		T->data=ch;
		creat(T->left);
		creat(T->right);
	}
}

现在举一个例子。

例如我们要实现一个二叉树如图所示

 那我们用下面这段代码的时候

 应该怎么输入呢?

struct student
{
	char data;
	student* left;
	student* right;
};
//此方法是先序遍历顺序建立二叉链表
void creat(student *&T)
{
	char ch;
	cin >> ch;
	if (ch == '#')
	{
		T = NULL;
	}//但凡输入了#号 就代表这是个空树
	else
	{
		T = new student;
		T->data=ch;
		creat(T->left);
		creat(T->right);
	}
}

输入:

ABC##DE#G##F###

-----------------

为什么要这样输入呢?为什么输入顺序是这样的呢?建议你去看B站视频看完应该就能够理解了。

【纯干货】三分钟教会你遍历二叉树!学不会举报我!!_哔哩哔哩_bilibili

下面例题一道

13 二叉树:建立存储结构(前序输入次序)

作者: 冯向阳时间限制: 1S章节: DS:树

截止日期: 2022-06-30 23:55:00

问题描述 :

目的:使用C++模板设计并逐步完善二叉树的抽象数据类型(ADT)。

内容:(1)请参照链表的ADT模板,设计二叉树并逐步完善的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考教材、课件,以及网盘中的链表ADT原型文件,自行设计二叉树的ADT。)

注意:二叉树ADT的基本操作的算法设计很多要用到递归的程序设计方法。

(2)基本操作1:二叉树的二叉链表存储形式的建立,完成后将其加入到二叉树的ADT基本操作集中。

要求设计一个递归算法,将二叉树转化为二叉链表的存储形式。

初始条件:definition给出二叉树T的定义(先序序列。无孩子或指针为空的情形,算法通过特殊分隔符识别(输入)),至少有1个根结点。

输出:按definition构造二叉树的二叉链表。

注意:由于测试数据的显示需建立在二叉树的遍历基础上。因此,请在设计好二叉树的三种遍历算法之后(基本操作2),再进行测试。

参考函数代码:

//建立二叉树的存储结构 (外壳) 

template<class ElemType>

void CreateTree(BinaryTree<ElemType> &T, ElemType &str, ElemType &empty){

    ElemType tmp;

    vector<ElemType> t;

    

    stringstream input_T(str);

    while(input_T >> tmp){

         t.push_back(tmp);

    }

    BinaryTreeNode<ElemType> *root;

    int num = 0;

    root = T.CreateBinaryTree(t, empty, num);

    T.SetRoot(root);    

}

//建立二叉树的存储结构 (递归部分,成员函数)

template<class ElemType>

BinaryTreeNode<ElemType>* BinaryTree<ElemType>::CreateBinaryTree(vector<ElemType> &x, ElemType &empty, int &n){

        ElemType ch = x[n];

        n++;

        if (ch == empty)

        {

            return NULL;

        }

        else

        {   

            BinaryTreeNode<ElemType> *Node = new BinaryTreeNode<ElemType>;

            Node->data = ch;

            Node->LChild = CreateBinaryTree(x, empty, n);

            Node->RChild = CreateBinaryTree(x, empty, n);

            return Node;

        }

}

二叉树ADT原型参考如下:

/* 二叉表的结点定义 */
template<class ElemType>
struct BinaryTreeNode
{
       ElemType data;
       BinaryTreeNode<ElemType> *LChild, *RChild;
       BinaryTreeNode() : LChild(NULL), RChild(NULL){} //构造函数1,用于构造根结点
       BinaryTreeNode(const ElemType &item, BinaryTreeNode<ElemType> *Lptr = NULL, BinaryTreeNode<ElemType> *Rptr = NULL) //构造函数2,用于构造其他结点  
       //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
       {
           LChild = Lptr;
           RChild = Rptr;
           data = item;
       }
      
       ElemType getData(){ return data;}  //取得结点中的数据
       void SetLChild( BinaryTreeNode<ElemType> *link ){ LChild = link; }  //修改结点的左孩子域
       void SetRChild( BinaryTreeNode<ElemType> *link ){ RChild = link; }  //修改结点的右孩子域
       void SetData( ElemType value ){ data = value; }   //修改结点的data域            
       BinaryTreeNode<ElemType> * GetLChild() const{ return LChild;} //获取左孩子结点
       BinaryTreeNode<ElemType> * GetRChild() const{ return RChild;} //获取左孩子结点

};

//二叉树 

template<class ElemType>

class BinaryTree{

   private:

      BinaryTreeNode<ElemType> *root;   // 头指针

      void BinaryTreeDestroy_Cursive( BinaryTreeNode<ElemType> *T ); //销毁树(递归准备,private)

            

   public:

      //无参数的构造函数

      BinaryTree():root(NULL){}

      //带参数的构造函数

      BinaryTree(const ElemType &item){root = new BinaryTreeNode<ElemType>(item);}

      //生成树

      void makeBinaryTree( const ElemType &item, BinaryTree &left, BinaryTree &right); 

      //拷贝构造函数

      //LinkQueue(LinkQueueList<ElemType> &Queue);

      //析构函数

      ~BinaryTree(){BinaryTreeDestroy();}

      //重载函数:赋值

      //LinkList<ElemType>& operator=(LinkList<ElemType> &List);

      //销毁树 

      void BinaryTreeDestroy();

      //销毁子树 

      void ChildDestroy(int flag);

      //返回二叉树结点的个数

      int BinaryTreeSize( BinaryTreeNode<ElemType> *T ) const;

      //判断二叉树是否为空

      bool BinaryTreeisEmpty() const{return root == NULL;}

      //获取根结点元素值 

      ElemType GetRootData() const{ return root->data;}

      //bool Location(ElemType &x, BinaryTreeNode<ElemType> * &location);

      //设置根结点 

      void SetRoot(BinaryTreeNode<ElemType> * p){ root = p;}

      //获取根结点 

      BinaryTreeNode<ElemType> * GetRoot() const{ return root;}

      //前序遍历 

      bool PreOrderTraverse( BinaryTreeNode<ElemType> *T, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num ) const;  //前序遍历(递归)//num的初始值为0,作用为控制输出格式(最后1个结点后不加“,”)

      //中序遍历 

      bool InOrderTraverse( BinaryTreeNode<ElemType> *T, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num ) const;  //中序遍历(递归)

      //后序遍历 

      bool PostOrderTraverse( BinaryTreeNode<ElemType> *T, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num ) const;  //后序遍历(递归)

      //建立二叉树的存储结构

      BinaryTreeNode<ElemType>* CreateBinaryTree(vector<ElemType> &x, ElemType &empty, int &n);

};

输入说明 :

第一行:表示无孩子或指针为空的特殊分隔符

第二行:二叉树的先序序列(结点元素之间以空格分隔)

输出说明 :

第一行:二叉树先序遍历结果

第二行:二叉树中序遍历结果

第三行:二叉树后序遍历结果

输入范例 :

null
A B null C D null null E null null F null G null H null null

输出范例 :

A,B,C,D,E,F,G,H
B,D,C,E,A,F,G,H
D,E,C,B,H,G,F,A

#include<iostream>
using namespace std;
bool m = 0;
bool m1 = 0;
bool m2 = 0;
struct student
{
	string data;
	student* left;
	student* right;
};
//此方法是先序遍历顺序建立二叉链表---即二叉树的存储结构(二叉树的实际样子)
void creat(student *&T,string kk)
{
	string ch;
	cin >> ch;
	if (ch == kk)
	{
		T = NULL;
	}//但凡输入了#号 该节点下一位停止
	else
	{
		T = new student;
		T->data=ch;
		creat(T->left,kk);
		creat(T->right,kk);
	}
}
//用递归来遍历
void prescan(student *T)//先序遍历
{
	
	if (T == NULL)
	{
	
		return;
	}
	else
	{
		if (m == 1)
		{
			cout << ',';
		}
		cout << T->data;
		m = 1;
		prescan(T->left);
		prescan(T->right);
	}

}

void midscan(student* T)//中序遍历
{
	if (T == NULL)
	{
		return;
	}
	else
	{

		midscan(T->left);
		if (m1 == 1)
		{
			cout << ',';
		}
		cout << T->data;
		m1 = 1;
		midscan(T->right);
	}
	
}

void lastscan(student* T)//后序遍历二叉树
{
	if (T == NULL)
	{

		return;
	}
	else
	{
		lastscan(T->left);
		lastscan(T->right);
		if (m2 == 1)
		{
			cout << ',';
		}
		cout << T->data;
		m2 = 1;
	

	
	}
	
}

void specialscan()//非递归遍历 我现在还不会 会了补上
{
}
int caculate(student *T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		return 1 + caculate(T->left) + caculate(T->right);
	}
}

int main()
{
	student *head;
	string kk;
	cin >> kk;

	creat(head,kk);
	prescan(head);
	cout << endl;
	midscan(head);
	cout << endl;
	lastscan(head);
	cout << endl;
	return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

13 二叉树:建立存储结构(前序输入次序) &&二叉树专题 的相关文章

随机推荐

  • Java中的静态成员方法

    用static修饰的变量 方法叫静态成员 方法 属于整个类所有 而不是某个对象所有 即被类的所有对象所共享 静态成员可以使用类名直接访问 也可以使用对象名进行访问 Java中静态方法与非静态方法的区别 首先 两者本质上的区别是 静态方法是在
  • 2021-06-01 通过类去实现装饰器__call__.

    1 含有 init 的类 class MyClass a cherry def init self age sex self age age self sex sex def say self print hello obj MyClass
  • Quartz的MisFire机制解析

    在上一篇 Quartz的负载均衡如何实现 文章中说过Quartz的线程模型 提到了MisFire任务是由MisfireHandler线程专门进行处理的 本文主要是来了解下该部分功能是如何实现的 源码分析 MisfireHandler线程定义
  • java 上传方法_Java实现文件上传的方法

    本文实例为大家分享了java实现文件上传的具体代码 具体内容如下 1 java代码 package com github reston servlet import java io file import java io fileoutpu
  • 添加高斯噪声

    coding utf 8 import cv2 as cv import numpy as np import sys def add noise image mean 0 val 0 01 size image shape image i
  • 用本机电脑搭建网站(域名、DNS解析)

    最近又准备瞎捣鼓一下个人网站 本来呢 如果是自己玩玩的话 用花生壳或者NAT123这样的动态DNS解析就可以了 但是最近花生壳这个吊玩意不知道怎么又没办法解析了 而且这货给的域名用的是我的手机号 如此一来个人隐私也暴露了 所以今天我就来研究
  • 吴恩达Coursera深度学习课程 deeplearning.ai (5-2) 自然语言处理与词嵌入--编程作业(二):Emojify表情包

    Part 2 Emojify 欢迎来到本周的第二个作业 你将利用词向量构建一个表情包 你有没有想过让你的短信更具表现力 emojifier APP将帮助你做到这一点 所以不是写下 Congratulations on the promoti
  • java的继承(一)

    程序中的继承 特点 利于代码复用 缩短开发周期 关键字 class Dog extends Animal 方法重写 与方法重载 方法重写 方法和父类方法参数完全一样 返回值相同 访问修饰符权限 gt 父类方法 重写方法 我理解为重写参数作用
  • buuctf[MRCTF2020]千层套路

    buuctf MRCTF2020 千层套路 题目描述 题目分析 解题过程 题目描述 题目给了一个以四位数字做文件名的压缩文件 题目分析 发现题目给的压缩文件名 就是解压这个压缩文件的密码 既然是千层套路 类似的操作可能要进行一千次 解题过程
  • div失去焦点事件onblur()无效

    初学js事件 想做一个点击时变红 取消聚焦时变白的div 于是我这样写代码 div style width 100px height 50px border 1px solid div
  • 谷歌Chrome浏览器开发者工具教程—基础功能篇

    Chrome F12开发者工具 是非常实用的开发辅助工具 对于前端开发者简直就是神器 但苦于开发者工具是英文界面 且没有中文 这让很多朋友都不知道怎么用 下载吧小编为大家带来Chrome开发者工具基础功能和高级性能分析器 Timeline
  • 背包问题的动态规划算法和fptas

    背包问题 instance 给定n个item i 1 2 n i 1 2 dots n weights w1 w2 wn Z w 1 w 2 dots w n in Z values v1 v2 vn Z v 1 v 2 dots v n
  • 搭建CentOS在线yum源镜像服务器

    说明 操作系统 CentOS 6 7 Nginx版本 1 8 0 rsync版本 3 0 6 IP地址和端口 192 168 3 100 8080 目标 同步CentOS镜像站点的内容到此服务器 通过配置http服务器 提供yum服务 一
  • Python——math库常用的数学函数

    在使用math库前 要用import导入该库 上图为math库中常用的一些数学函数 下面给出具体实例 例1 import math a eval input 请输入一个负数 print a math fabs a 输出结果 例2 impor
  • 【LeetCode刷题】237 删除链表中的节点

    题目 请编写一个函数 用于 删除单链表中某个特定节点 在设计函数时需要注意 你无法访问链表的头节点 head 只能直接访问 要被删除的节点 题目数据保证需要删除的节点 不是末尾节点 示例 这题其实真的简单 只能直接访问到给定要删除的节点 本
  • 设置Tab键为4个空格 Java开发手册规范之tab键设置

    设置Tab键为4个空格 在阿里的Java开发手册 一 编程规约 三 代码格式 第5条提到 强制 采用4个空格缩进 禁止使用tab字符 IDEA中勿勾选 Use tab character eclipse中必选 insert spaces f
  • [JAVEee]SpringBoot项目的创建

    SpringBoot可以更好的开发Spring项目 本文章将使用idea社区版来演示创建项目的过程与注意事项 SpringBoot的优点 SpringBoot中内置快速添加依赖的功能 能够便捷的集成各种框架 帮助开发 内置运行容器 无需配置
  • Linux top里面%CPU和us%的解释

    有的同学会把 CPU和us 搞晕 也就是下图所示在top的时候查看cpu的信息 这时有的同学会问 这两个CPU到底哪个是对的 其实都是对的 只是表达的意思不一样 官方解释如下 Cpu s 34 0 us 用户空间占用CPU百分比 CPU 上
  • 2023华为OD机试真题【最小调整顺序次数】

    问题描述 给定一个队列 但是这个队列比较特殊 可以从头部添加数据 也可以从尾部添加数据 但是只能从头部删除数据 输入一个数字n 会依次添加数字1 n 也就是添加n次 但是在添加数据的过程中 也会删除数据 要求删除必须按照1 n按照顺序进行删
  • 13 二叉树:建立存储结构(前序输入次序) &&二叉树专题

    目录 首先讲讲指针的引用 然后我们再复习一下typedef的用法 然后我们来创建二叉树 二叉树的建立 首先二叉树的存储结构 实际用代码体现 分为顺序存储和链式存储两种 但一般情况我们都用链式存储结构 部分内容转自指针的引用 MAGDB的博客