广州大学学生实验报告
开课实验室:计算机科学与工程实验(电子楼417) 2018年05月16日
学院 |
计算机科学与教育软件学院 |
年级、专业、班 |
网络161 |
姓名 |
卟咚君 |
学号 |
1606100*** |
|
实验课程名称 |
数据结构实验 |
成绩 |
|
|||||
实验项目名称 |
实验二 树和二叉树的实现 |
指导老师 |
** |
|||||
一、实验类型: 验证性 实验目的:理解并运用树的操作方法 教学重点:多元树或二叉树的表示及遍历。 二、使用仪器、器材 微机一台 操作系统:WinXP 编程软件:C++ 三、实验内容及原理 (1)自己选择存储方式、自己设计输入输出方式,在实验报告中清晰说明。 (2)输入一棵二叉树进行多种遍历。树的高度(设空树高度为-1)不小于4,包含了儿子数为0、1、2的结点。选做:二叉树的总结点(或叶片)数目的统计。 思路:定义一个class BinTreeNode为二叉树的结点; 定义一个class BinaryTree 为二叉树; 在BinaryTree中的build_BinaryTree()函数进行建树,输入n个结点,按照搜索二叉树的方式逐个插入每个结点的值(Insert(const Type item)),输出的时候按照树逆时针90度的方式输出,前序遍历,中序遍历,后序遍历都采用了递归的方式实现。另外,存储的方式为每一个结点都有一个左儿子结点和右儿子结点的指针,初始化时为NULL,安装不断的插入时更新。前序遍历,中序遍历,后序遍历都主要是递归实现的。比如说,前序遍历,每一次都先输出当前结点的值,然后递归访问左儿子的结点,当左儿子的结点递归访问结束的时候,再递归访问右儿子结点。在二叉树的类中,还实现了二叉树结点的总数的计数,二叉树叶子结点的计数,二叉树的高度计数。以高度为例,一个结点子树的高度等于他的儿子结点的子树中的最大的高度+1,采用递归的方式实现。
源代码: #include #include #include #include using namespace std; const int INF = int(1e9) + 7; template<typename Type> class BinTreeNode{ //二叉树的结点 public: BinTreeNode() :left(NULL), right(NULL){} BinTreeNode(Type item, BinTreeNode<Type> *m_left = NULL, BinTreeNode<Type> *m_right = NULL) :data(item), left(m_left), right(m_right){} Type GetData() const; //获得该结点的data BinTreeNode<Type> *GetLeft() const; //获得左儿子的结点 BinTreeNode<Type> *GetRight() const; //获得右儿子的结点 void SetData(const Type data); //设置该结点的data void SetLeft(const BinTreeNode<Type> *m_left); //设置该结点的左儿子结点 void SetRight(const BinTreeNode<Type> *m_right); //设置该结点的右儿子结点 void InOrder(); //中序遍历 void PreOrder(); //前序遍历 void PostOrder(); //后序遍历 int Size(); //返回结点总数 int Height(); //返回二叉树的高度 int LeavesSize(); //返回二叉树的叶子结点的总数 void Destroy(){ //销毁二叉树 if (this != NULL){ this->left->Destroy(); this->right->Destroy(); delete this; } } BinTreeNode<Type> *left, *right; Type data; }; template<typename Type> Type BinTreeNode<Type>::GetData() const{ //返回该结点的数值 return this != NULL ? data : INF; } template<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::GetLeft() const{ //返回该结点的左儿子的结点指针 return this != NULL ? left : NULL; } template<typename Type> BinTreeNode<Type>* BinTreeNode<Type>::GetRight() const{ //返回该结点的右儿子的结点指针 return this != NULL ? right : NULL; } template<typename Type> void BinTreeNode<Type>::SetData(const Type m_data){ //设置该结点的data if (this != NULL){ data = m_data; } } template<typename Type> void BinTreeNode<Type>::SetLeft(const BinTreeNode<Type> *m_left){ //设置该结点的左儿子结点 if (this != NULL){ left = m_left; } } template<typename Type> void BinTreeNode<Type>::SetRight(const BinTreeNode<Type> *m_right){ //设置该结点的右儿子结点 if (this != NULL){ right = m_right; } } template<typename Type> void BinTreeNode<Type>::InOrder(){ //中序遍历 if (this != NULL){ this->left->InOrder(); cout << "--->" << this->data; this->right->InOrder(); } } template<typename Type> void BinTreeNode<Type>::PreOrder(){ //前序遍历 if (this != NULL){ cout << "--->" << this->data; this->left->PreOrder(); this->right->PreOrder(); } } template<typename Type> void BinTreeNode<Type>::PostOrder(){ //后序遍历 if (this != NULL){ this->left->PostOrder(); this->right->PostOrder(); cout << "--->" << this->data; } } template<typename Type> int BinTreeNode<Type>::Size(){ //返回以该结点为树根的树的结点总数 if (this == NULL){ return 0; } return 1 + this->left->Size() + this->right->Size();//左儿子树的结点总数加右儿子结点总数再加上本身 }
template<typename Type> int BinTreeNode<Type>::Height(){ //返回以该结点为树根的树的高度 if (this == NULL){ return -1; } int lheight, rheight; lheight = this->left->Height(); rheight = this->right->Height(); return 1 + max(lheight,rheight);//(左儿子树的高度,右儿子结点高度)的最大值再加上本身 } template<typename Type> int BinTreeNode<Type>::LeavesSize(){ //返回以该结点为树根的树的结点总数 if (this == NULL){ return 0; } if (this->left == NULL&&this->right == NULL){ return 1; } return this->left->LeavesSize() + this->right->LeavesSize();//左儿子树的结点总数加右儿子结点总数再加上本身 } template<typename Type> class BinaryTree{ //二叉树 public: BinaryTree() :root(NULL){} BinaryTree(BinTreeNode<Type> *m_root) :root(m_root){} //以m_root为二叉树的树根建立二叉树 virtual ~BinaryTree(){ root->Destroy(); } virtual bool IsEmpty(){ //is empty? return root == NULL; } BinTreeNode<Type> *GetLeft(BinTreeNode<Type> *current); //返回左儿子的结点指针 BinTreeNode<Type> *GetRight(BinTreeNode<Type> *current);//返回右儿子的结点指针 BinTreeNode<Type> *GetParent(BinTreeNode<Type> * m_root,BinTreeNode<Type> *current);//返回父亲的结点指针 const BinTreeNode<Type> *GetRoot() const; //返回二叉树的树根 bool Insert(const Type item); //插入一个新的结点 BinTreeNode<Type> *Find(const Type item) const; //在二叉树中返回数值为item的结点指针 void InOrder(); //中序遍历 void PreOrder(); //前序遍历 void PostOrder(); //后序遍历 int Size(); //返回树的结点总数 int Height(); //返回树的高度 int LeavesSize(); //返回叶子结点的数目 void build_BinaryTree(); //建树 friend ostream& operator<< <Type>(ostream&, BinaryTree<Type>&); //output the data
private: Type m_stop; //just using for input the data; BinTreeNode<Type> *root; //二叉树的树根 void Print(BinTreeNode<Type> *start, int n = 0); //输出以start为树根的二叉树 }; template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetLeft(BinTreeNode<Type> *current){ //返回current结点的左儿子结点 return m_proot&¤t ? current->left : NULL; }
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetRight(BinTreeNode<Type> *current){ //返回current结点的右儿子结点 return m_proot&¤t ? current->right : NULL; }
template<typename Type> const BinTreeNode<Type>* BinaryTree<Type>::GetRoot() const{ //返回二叉树的树根 return root; }
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::GetParent(BinTreeNode<Type> *m_root, BinTreeNode<Type> *current){ //从m_root开始查找,返回current结点的父亲结点 if (m_root== NULL || current == NULL){ return NULL; } if (m_root->left == current || m_root->right == current){ return m_root; } BinTreeNode<Type> *pmove; if ((pmove = GetParent(m_root->left, current)) != NULL){ //从m_root的左儿子结点开始查找,返回current结点的父亲结点 return pmove; } else{ return GetParent(m_root->right, current); //从m_root的右儿子结点开始查找,返回current结点的父亲结点 } } template<typename Type> bool BinaryTree<Type>::Insert(const Type item){ //以搜索二叉树的方式插入数值item,采用递归的方式 BinTreeNode<Type> *start = root, *newnode = new BinTreeNode<Type>(item); if (root == NULL){ //二叉树为空,直接插入二叉树的树根 root = newnode; return 1; } while (1){ if (item == start->data){ cout << "这个数值" << item << " 已存在!" << endl; return 0; } if (item if (start->left == NULL){ start->left = newnode; return 1; } start = start->left; //当前结点start指针变成start的左儿子结点指针 } else{ if (start->right == NULL){ //如果item数值大于等于原本结点start数值,则插向start的右儿子 start->right = newnode; return 1; } start = start->right; //当前结点start指针变成start的右儿子结点指针 } } }
template<typename Type> BinTreeNode<Type>* BinaryTree<Type>::Find(const Type item) const{ //查找二叉树数值为item的树结点 BinTreeNode<Type> *start = root; while (start){ if (item == start->data){ return start; } if (item start = start->left; } else{ start = start->right;//如果item大于start的数值data,则item可能存在于start的右子树的结点上 } } return NULL; //该数值item不存在于二叉树中,返回NULL }
template<typename Type> void BinaryTree<Type>::Print(BinTreeNode<Type> *start, int n){ //输出二叉树 if (start == NULL){ for (int i = 0; i<n; i++){ cout << " "; } cout << "NULL" << endl; return; } Print(start->right, n + 1); //输出右子树 for (int i = 0; i<n; i++){ //输出长为n的" "空格 cout << " "; } if (n >= 0){ cout << start->data << "--->" << endl;// 输出该点的数值 } Print(start->left, n + 1); //输出左子树 } template<typename Type> ostream& operator<<(ostream& os, BinaryTree<Type>& out){ //输出二叉树 out.Print(out.root); return os; } template<typename Type> void BinaryTree<Type>::build_BinaryTree(){ cout << "请输入二叉树的结点总数:"; int n, item; cin >> n; cout << "请输入二叉树的" << n << "个结点的数值" << endl; for (int i = 1; i <= n; i++){ cin >> item; Insert(item); } } template<typename Type> void BinaryTree<Type>::InOrder(){ //中序遍历 this->root->InOrder(); }
template<typename Type> void BinaryTree<Type>::PreOrder(){ //前序遍历 this->root->PreOrder(); }
template<typename Type> void BinaryTree<Type>::PostOrder(){ //后序遍历 this->root->PostOrder(); }
template<typename Type> int BinaryTree<Type>::Size(){ //返回二叉树的结点总数 return this->root->Size(); } template<typename Type> int BinaryTree<Type>::Height(){ //返回二叉树的高度 return this->root->Height(); } template<typename Type> int BinaryTree<Type>::LeavesSize(){ //返回二叉树的高度 return this->root->LeavesSize(); } int main(){ BinaryTree<int> btree; btree.build_BinaryTree(); //(1)输入二叉树的结点总数,(2)输入各个结点的data,输入的data按照搜索二叉树的方式插入 cout << btree; //(3)输出一棵二叉树,按照逆时针旋转90度的方式输出 cout << "二叉树的前序遍历为:"; btree.PreOrder(); //(4)输出二叉树的前序遍历 cout << endl; cout << "二叉树的中序遍历为:"; btree.InOrder(); //(5)输出二叉树的中序遍历 cout << endl; cout << "二叉树的后序遍历为:"; //(6)输出二叉树的后序遍历 btree.PostOrder(); cout << endl; cout << "二叉树的结点总数为:"; cout << btree.Size() << endl; //(7)输出二叉树的结点总数为 cout << "二叉树的叶子结点总数为:"; cout << btree.LeavesSize() << endl; //(8)输出二叉树的叶子结点的总数为 cout << "二叉树的结点高度为:"; cout << btree.Height() << endl; //(9)输出二叉树的高度为为 cout << "选择插入一个数值请输入任意非零数,跳过则请输入0:"; int flag, item; cin >> flag; while (flag){ cout << "请输入要插入的一个数值:"; cin >> item; btree.Insert(item); //(10)选择向二叉树插入一个数值 cout << btree; cout << "选择插入一个数值请输入任意非零数,跳过则请输入0:"; cin >> flag; } return 0; } 实验过程原始数据记录
|
||||||||
通过定义一个class树结点,和一个class二叉树,在二叉树中封装了树的一些基本操作,可以进行二叉树的建树,新的结点的插入,前序遍历,中序遍历,后序遍历等基本操作。自己设置的输入方式为,先输入一棵树的结点总数n,然后输入每一个结点的数值,进行初始化建立一棵二叉树。插入的方式按照搜索二叉树的方式插入,每插入一个新的结点,都保证一棵树结点的左儿子结点的数值比父亲结点的数值小,右儿子的结点的数值比父亲结点的数值大。设置的输出方式参考了参考了老师讲的二叉树的凹入表示法,按照一棵二叉树逆时针旋转90度的方式输出,当儿子结点为NULL时,直接输出NULL. 存储的方式为每一个结点都有一个左儿子结点和右儿子结点的指针,初始化时为NULL,安装不断的插入时更新。前序遍历,中序遍历,后序遍历都主要是递归实现的。比如说,前序遍历,每一次都先输出当前结点的值,然后递归访问左儿子的结点,当左儿子的结点递归访问结束的时候,再递归访问右儿子结点。在二叉树的类中,还实现了二叉树结点的总数的计数,二叉树叶子结点的计数,二叉树的高度计数。以高度为例,一个结点子树的高度等于他的儿子结点的子树中的最大的高度+1,采用递归的方式实现。 通过本次实验,更加明白了树的结构,通过自行设置输入输出方式,锻炼了自己的编程能力,尤其是二叉树的输出,更需要不断的调试才能得到一个比较好,形象的二叉树输出。
|
||||||||
//源代码:
#include
#include
#include
#include
using namespace std;
const int INF = int(1e9) + 7;
template class BinTreeNode{ //二叉树的结点
public:
BinTreeNode() :left(NULL), right(NULL){}
BinTreeNode(Type item, BinTreeNode *m_left = NULL, BinTreeNode *m_right = NULL)
:data(item), left(m_left), right(m_right){}
Type GetData() const; //获得该结点的data
BinTreeNode *GetLeft() const; //获得左儿子的结点
BinTreeNode *GetRight() const; //获得右儿子的结点
void SetData(const Type data); //设置该结点的data
void SetLeft(const BinTreeNode *m_left); //设置该结点的左儿子结点
void SetRight(const BinTreeNode *m_right); //设置该结点的右儿子结点
void InOrder(); //中序遍历
void PreOrder(); //前序遍历
void PostOrder(); //后序遍历
int Size(); //返回结点总数
int Height(); //返回二叉树的高度
int LeavesSize(); //返回二叉树的叶子结点的总数
void Destroy(){ //销毁二叉树
if (this != NULL){
this->left->Destroy();
this->right->Destroy();
delete this;
}
}
BinTreeNode *left, *right;
Type data;
};
template Type BinTreeNode::GetData() const{ //返回该结点的数值
return this != NULL ? data : INF;
}
template BinTreeNode* BinTreeNode::GetLeft() const{ //返回该结点的左儿子的结点指针
return this != NULL ? left : NULL;
}
template BinTreeNode* BinTreeNode::GetRight() const{ //返回该结点的右儿子的结点指针
return this != NULL ? right : NULL;
}
template void BinTreeNode::SetData(const Type m_data){ //设置该结点的data
if (this != NULL){
data = m_data;
}
}
template void BinTreeNode::SetLeft(const BinTreeNode *m_left){ //设置该结点的左儿子结点
if (this != NULL){
left = m_left;
}
}
template void BinTreeNode::SetRight(const BinTreeNode *m_right){ //设置该结点的右儿子结点
if (this != NULL){
right = m_right;
}
}
template void BinTreeNode::InOrder(){ //中序遍历
if (this != NULL){
this->left->InOrder();
cout << "--->" << this->data;
this->right->InOrder();
}
}
template void BinTreeNode::PreOrder(){ //前序遍历
if (this != NULL){
cout << "--->" << this->data;
this->left->PreOrder();
this->right->PreOrder();
}
}
template void BinTreeNode::PostOrder(){ //后序遍历
if (this != NULL){
this->left->PostOrder();
this->right->PostOrder();
cout << "--->" << this->data;
}
}
template int BinTreeNode::Size(){ //返回以该结点为树根的树的结点总数
if (this == NULL){
return 0;
}
return 1 + this->left->Size() + this->right->Size();//左儿子树的结点总数加右儿子结点总数再加上本身
}
template int BinTreeNode::Height(){ //返回以该结点为树根的树的高度
if (this == NULL){
return -1;
}
int lheight, rheight;
lheight = this->left->Height();
rheight = this->right->Height();
return 1 + max(lheight,rheight);//(左儿子树的高度,右儿子结点高度)的最大值再加上本身
}
template int BinTreeNode::LeavesSize(){ //返回以该结点为树根的树的结点总数
if (this == NULL){
return 0;
}
if (this->left == NULL&&this->right == NULL){
return 1;
}
return this->left->LeavesSize() + this->right->LeavesSize();//左儿子树的结点总数加右儿子结点总数再加上本身
}
template class BinaryTree{ //二叉树
public:
BinaryTree() :root(NULL){}
BinaryTree(BinTreeNode *m_root) :root(m_root){} //以m_root为二叉树的树根建立二叉树
virtual ~BinaryTree(){
root->Destroy();
}
virtual bool IsEmpty(){ //is empty?
return root == NULL;
}
BinTreeNode *GetLeft(BinTreeNode *current); //返回左儿子的结点指针
BinTreeNode *GetRight(BinTreeNode *current);//返回右儿子的结点指针
BinTreeNode *GetParent(BinTreeNode * m_root,BinTreeNode *current);//返回父亲的结点指针
const BinTreeNode *GetRoot() const; //返回二叉树的树根
bool Insert(const Type item); //插入一个新的结点
BinTreeNode *Find(const Type item) const; //在二叉树中返回数值为item的结点指针
void InOrder(); //中序遍历
void PreOrder(); //前序遍历
void PostOrder(); //后序遍历
int Size(); //返回树的结点总数
int Height(); //返回树的高度
int LeavesSize(); //返回叶子结点的数目
void build_BinaryTree(); //建树
friend ostream& operator<< (ostream&, BinaryTree&); //output the data
private:
Type m_stop; //just using for input the data;
BinTreeNode *root; //二叉树的树根
void Print(BinTreeNode *start, int n = 0); //输出以start为树根的二叉树
};
template BinTreeNode* BinaryTree::GetLeft(BinTreeNode *current){ //返回current结点的左儿子结点
return m_proot&¤t ? current->left : NULL;
}
template BinTreeNode* BinaryTree::GetRight(BinTreeNode *current){ //返回current结点的右儿子结点
return m_proot&¤t ? current->right : NULL;
}
template const BinTreeNode* BinaryTree::GetRoot() const{ //返回二叉树的树根
return root;
}
template BinTreeNode* BinaryTree::GetParent(BinTreeNode *m_root, BinTreeNode *current){ //从m_root开始查找,返回current结点的父亲结点
if (m_root== NULL || current == NULL){
return NULL;
}
if (m_root->left == current || m_root->right == current){
return m_root;
}
BinTreeNode *pmove;
if ((pmove = GetParent(m_root->left, current)) != NULL){ //从m_root的左儿子结点开始查找,返回current结点的父亲结点
return pmove;
}
else{
return GetParent(m_root->right, current); //从m_root的右儿子结点开始查找,返回current结点的父亲结点
}
}
template bool BinaryTree::Insert(const Type item){ //以搜索二叉树的方式插入数值item,采用递归的方式
BinTreeNode *start = root, *newnode = new BinTreeNode(item);
if (root == NULL){ //二叉树为空,直接插入二叉树的树根
root = newnode;
return 1;
}
while (1){
if (item == start->data){
cout << "这个数值" << item << " 已存在!" << endl;
return 0;
}
if (itemdata){ //如果item数值比原本结点start数值小,则插向start的左儿子
if (start->left == NULL){
start->left = newnode;
return 1;
}
start = start->left; //当前结点start指针变成start的左儿子结点指针
}
else{
if (start->right == NULL){ //如果item数值大于等于原本结点start数值,则插向start的右儿子
start->right = newnode;
return 1;
}
start = start->right; //当前结点start指针变成start的右儿子结点指针
}
}
}
template BinTreeNode* BinaryTree::Find(const Type item) const{ //查找二叉树数值为item的树结点
BinTreeNode *start = root;
while (start){
if (item == start->data){
return start;
}
if (itemdata){ //如果item小于start的数值data,则item可能存在于start的左子树的结点上
start = start->left;
}
else{
start = start->right;//如果item大于start的数值data,则item可能存在于start的右子树的结点上
}
}
return NULL; //该数值item不存在于二叉树中,返回NULL
}
template void BinaryTree::Print(BinTreeNode *start, int n){ //输出二叉树
if (start == NULL){
for (int i = 0; iright, n + 1); //输出右子树
for (int i = 0; i= 0){
cout << start->data << "--->" << endl;// 输出该点的数值
}
Print(start->left, n + 1); //输出左子树
}
template ostream& operator<<(ostream& os, BinaryTree& out){ //输出二叉树
out.Print(out.root);
return os;
}
template void BinaryTree::build_BinaryTree(){
cout << "请输入二叉树的结点总数:";
int n, item;
cin >> n;
cout << "请输入二叉树的" << n << "个结点的数值" << endl;
for (int i = 1; i <= n; i++){
cin >> item;
Insert(item);
}
}
template void BinaryTree::InOrder(){ //中序遍历
this->root->InOrder();
}
template void BinaryTree::PreOrder(){ //前序遍历
this->root->PreOrder();
}
template void BinaryTree::PostOrder(){ //后序遍历
this->root->PostOrder();
}
template int BinaryTree::Size(){ //返回二叉树的结点总数
return this->root->Size();
}
template int BinaryTree::Height(){ //返回二叉树的高度
return this->root->Height();
}
template int BinaryTree::LeavesSize(){ //返回二叉树的高度
return this->root->LeavesSize();
}
int main(){
BinaryTree btree;
btree.build_BinaryTree(); //(1)输入二叉树的结点总数,(2)输入各个结点的data,输入的data按照搜索二叉树的方式插入
cout << btree; //(3)输出一棵二叉树,按照逆时针旋转90度的方式输出
cout << "二叉树的前序遍历为:";
btree.PreOrder(); //(4)输出二叉树的前序遍历
cout << endl;
cout << "二叉树的中序遍历为:";
btree.InOrder(); //(5)输出二叉树的中序遍历
cout << endl;
cout << "二叉树的后序遍历为:"; //(6)输出二叉树的后序遍历
btree.PostOrder();
cout << endl;
cout << "二叉树的结点总数为:";
cout << btree.Size() << endl; //(7)输出二叉树的结点总数为
cout << "二叉树的叶子结点总数为:";
cout << btree.LeavesSize() << endl; //(8)输出二叉树的叶子结点的总数为
cout << "二叉树的结点高度为:";
cout << btree.Height() << endl; //(9)输出二叉树的高度为为
cout << "选择插入一个数值请输入任意非零数,跳过则请输入0:";
int flag, item;
cin >> flag;
while (flag){
cout << "请输入要插入的一个数值:";
cin >> item;
btree.Insert(item); //(10)选择向二叉树插入一个数值
cout << btree;
cout << "选择插入一个数值请输入任意非零数,跳过则请输入0:";
cin >> flag;
}
return 0;
}