实验四 二叉树的应用(BST)
[问题描述]
给定一个键值互不相同的非负整数序列,构造一颗树既是CBT,也是BST。请你输出这个BST的层次遍历序列。
[输入形式]
每个输入文件的第一行为一个正整数N(≤20),即二叉树中结点的总数。第二行给出了N个不同的非负键值序列。
注意:每一行中的所有数字都用一个空格隔开,并且不大于50。
[输出形式]
相应完全搜索二叉树的层次遍历序列输出在一行中。一行中的所有数字必须由一个空格隔开,并且行首和行尾不得有多余的空格。
问题分析
要处理的对象(数据):
通过键盘输入的一组整数,以数组的形式,存储到计算机中
要实现的功能:
先接收一个键盘输入的代表该组整数个数的数字,再依次接收该组整数
处理后的结果如何显示:
将得到的BST树的层次遍历输出在屏幕上
输入样例
【求解方法】
由于题目中要求创建的BST树为完全二叉树,则根据所给的结点即可知道树的高度,
并且,BST树的中序遍历为从小到大的一组整数,则我们只需根据中序遍历,按BST
树的左右子树规律来将从小到大排好序的数组利用递归算法插入到一个空的完全二叉树中,由于使用的是数组,层次遍历即用循环输出数组从小到大对应节点储存的的值。
【样例求解过程】
1.输入该组整数的整数个数:10
2.输入该组整数:1 2 3 4 5 6 7 8 9 0
3.整数存入数组: a[5]={1,2,3,4,5,6,7,8,9,0}
4.数组从小到大排序: a[5]={0,1,2,3,4,5,6,7,8,9}
5.利用递归将数组分别将左右结点插入树中:
6.输出层次遍历:6 3 8 1 5 7 9 0 2 4
抽象数据类型设计
数据对象: 一组整数
数据关系: 从键盘输入一个代表该组整数个数的数字后换行,再输入一组整数,
以换行符结束输入,按照输入的先后次序,满足线性特征
【节点ADT的表示】
ADT IntegerSet{
数据对象: D = {ai | ai ∈ 整数 ,i = 1 ,2 , ···, n, n>=0}
数据关系: R = {<ai ,ai+1> | ai-1 ,ai ∈ D}
基本操作:
BSTNode() // 操作功能:初始化节点
BSTNode(int e,int l,int r) // 操作功能:构建一个非空节点
int getData()// 操作功能:返回结点元素的值
int left() // 操作功能:返回左子树数组下标
void setLeft(int i)// 操作功能:创建左子树下标
int right() // 操作功能:返回右子树数组下标
void setRight(int i)// 操作功能:创建右子树下标
void setElement(int e)// 操作功能:给当前结点储存的值赋值
}
【树ADT的表示】
ADT IntegerSet{
数据对象: D = {ai | ai ∈ 整数 ,i = 1 ,2 , ···, n, n>=0}
数据关系: R = {<ai ,ai+1> | ai-1 ,ai ∈ D}
基本操作:
getRoot() // 操作功能:获得根节点的值
void setnodecount(int a) // 操作功能:赋值节点个数
void creat(int index,const int a[]) // 操作功能: 根据中序遍历创建二叉树
void cprintf() // 操作功能:按层次遍历输出二叉树
}
物理数据对象设计
物理存储方式: 整型
算法思想的设计:
准备一个能够存储一组整数的存储空间。
利用递归,将从小到大排好序的数组利用递归算法插入到一个空的完全二叉树中,
然后将这个二叉树按层次输出。
关键功能的算法步骤:
递归算法插入到一个空的完全二叉树中:
void creat(int index,const int a[]) //a为传入的从小到大排序的数组
{
if(index*2 <= nodeCount) creat(index*2,a); //创建左子树
nodeArray[index].setElement(a[pos++]);
if(index*2+1 <= nodeCount) creat(index*2+1,a); //创建右子树
}
时间复杂度为: O(n)
空间复杂度为: θ(1)
实验代码:
【结点ADT的实现】
#include <iostream>
#include<algorithm>
class BSTNode{
private:
int data; //二叉树节点存储的值
int lc; //左孩子指针
int rc; //右孩子指针
public:
//初始化节点
BSTNode() {
data=0;
lc=rc=0;
}
//构建一个非空节点
BSTNode(int e,int l,int r){
data=e;lc=l;rc=r;
}
//返回结点元素的值
int getData(){
return data;
}
int left() { return lc; }
void setLeft(int i) { lc = 2*i+1; }
int right() { return rc; }
void setRight(int i) { rc = 2*i+2; }
void setElement(int e) { data = e; }
};
【树ADT的实现】
#include "BSTNode.h"
using namespace std;
class BST:public BSTNode{
public:
int root; //BST树根节点
int nodeCount; //结点数
int pos=1;
BSTNode nodeArray[1000];//用数组存储节点
int getRoot() {return root;}
void setnodecount(int a) {
nodeCount=a;
}
void creat(int index,const int a[]) //a为传入的从小到大排序的数组
{
if(index*2 <= nodeCount) creat(index*2,a); //创建左子树
nodeArray[index].setElement(a[pos++]);
if(index*2+1 <= nodeCount) creat(index*2+1,a); //创建右子树
}
void cprintf()
{
for(int i=1;i<=nodeCount;i++)
{
cout<<nodeArray[i].getData()<<" ";
}
}
};
【主函数的实现】
#include "BST.h"
using namespace std;
int main()
{
int n;
BST tree;
cin>>n;
int a[1000];
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+n+1);
//构建BST
tree.setnodecount(n);
tree.creat(1,a);
tree.cprintf();
return 0;
}