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

目录

首先讲讲指针的引用 *&

然后我们再复习一下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);
	}
}

现在举一个例子。

例如我们要实现一个二叉树如图所示13 二叉树:建立存储结构(前序输入次序) &&二叉树专题_第1张图片

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

 应该怎么输入呢?

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

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

    ElemType tmp;

    vector t;

    

    stringstream input_T(str);

    while(input_T >> tmp){

         t.push_back(tmp);

    }

    BinaryTreeNode *root;

    int num = 0;

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

    T.SetRoot(root);    

}

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

template

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

        ElemType ch = x[n];

        n++;

        if (ch == empty)

        {

            return NULL;

        }

        else

        {   

            BinaryTreeNode *Node = new BinaryTreeNode;

            Node->data = ch;

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

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

            return Node;

        }

}

二叉树ADT原型参考如下:

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

};

//二叉树 

template

class BinaryTree{

   private:

      BinaryTreeNode *root;   // 头指针

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

            

   public:

      //无参数的构造函数

      BinaryTree():root(NULL){}

      //带参数的构造函数

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

      //生成树

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

      //拷贝构造函数

      //LinkQueue(LinkQueueList &Queue);

      //析构函数

      ~BinaryTree(){BinaryTreeDestroy();}

      //重载函数:赋值

      //LinkList& operator=(LinkList &List);

      //销毁树 

      void BinaryTreeDestroy();

      //销毁子树 

      void ChildDestroy(int flag);

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

      int BinaryTreeSize( BinaryTreeNode *T ) const;

      //判断二叉树是否为空

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

      //获取根结点元素值 

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

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

      //设置根结点 

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

      //获取根结点 

      BinaryTreeNode * GetRoot() const{ return root;}

      //前序遍历 

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

      //中序遍历 

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

      //后序遍历 

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

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

      BinaryTreeNode* CreateBinaryTree(vector &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
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;
}

你可能感兴趣的:(东华大学数据结构OJ,c++)