森林顺序结构(递归,层次)遍历求高度
对于顺序结构我们利用类的封装要比结点更好更方便一点,因为再顺序结构中,我们需要用到数组,如果每一个结点一个数组就有点麻烦
1. forest类中私有成员函数
我们设置一个 数组array,和他的长度
private:
int Max;
char* array;
2.forest的构造函数
forest(int Max)
{
if (Max > 0)
{
this->Max = Max;
array = new char[Max + 1];
memset(array,' ',(Max + 1)); //cstring中
}
}
memset 函数是将数组全部初始化为空(‘ ’) ,这个函数再cstring中
3.析构函数
~forest()
{
delete[]array;
}
4.构造森林
void build(int index = 1)
{
char data;
data = cin.get(); // cin.get(data);
if (data == '#'||index>Max) return;
array[index] = data;
build(2 * index);
build(2 * index + 1);
}
这个函数与之前的构造函数完全不同 ! ! !
我们建立森林的关键是要弄清楚每个点都是谁的儿子,谁的爹,谁的大胸弟
在这个函数中我们要构造这样的关系
如果我们输入了 # ,或者下标大于Max,这个构造函数就结束
如果不是就把他赋值给 array[index]
然后构造他的左孩子 build(2 * index) ,左孩子的下标是他爹的二倍
再构造他的大胸弟,下标是他的 二倍 + 1
5.递归遍历求高度
int high(int i = 1)
{
if (i> Max || array[i] == ' ') return 0;
return max(high(2 * i) + 1, high(2 * i + 1)); //在头文件 cstdlib 中
}
如果下标为 i 时他对应的值为空(‘ ’)或者大于Max, 程序结束
之后要返回 左孩子结点+1 和 兄弟结点 的最大值
在森林转为二叉树的逻辑中,新的二叉树中,只要结点有左孩子,就要给他的层次 +1
但右兄弟就不用,不过还是要遍历右兄弟,因为右兄弟的后继结点中可能也有左孩子
这个自己画个图就能好理解一点
6.层次遍历求高度
int dep(int i = 1)
{
queue<int> Queue;
Queue.push(i);
int height = 0;
while (!Queue.empty())
{
height++;
int len = Queue.size();
for (int j = 1; j <= len; j++)
{
int index = Queue.front();
Queue.pop();
while (array[index] != ' ')
{
if (array[2 * index] != ' ') Queue.push(2 * index);
index = 2 * index + 1;
}
}
}
return height;
}
我们要在这里面建立一个队列,用来储存 根结点 和 所有有左孩子的结点
在之后的循环中,我们要看着些在队列中的结点是否还有左孩子
有的话他的左孩子继续入队,再遍历他的右胸弟
只要队列中不空,每经历一次循环森林的层次就 +1
7.主函数
int main()
{
forest a(200);
a.build();
cout<<"森林顺序递归遍历求高度"<<endl;
cout<<a.high()<<endl;
cout<<"森林顺序层次遍历求高度"<<endl;
cout<<a.dep();
}
8.输出结果
ABEK##F##CG##DH#I#J###L#MN###