演示程序截图
基本要求
- 构造并实现森林的ADT和二叉树ADT,森林ADT中应包括初始化、插入元素、删除元素,插入边,删除边,转换成二叉树,显示森林及对应的二叉树等基本操作,二叉树ADT中应包括初始化、插入根、插入指定元素的左孩子或右孩子,转换成森林,显示二叉树及对应的森林等基本操作。(基本操作可根据问题需要扩展)
- 森林使用孩子链表表示,二叉树使用二叉链表表示,实现森林和二叉树结构。
问题分析
该程序所应实现的功能如下:
(1)二叉树与森林的初始化
(2)二叉树与森林的插入操作(二叉树插入结点、森林插入结点、插入边)
(3)二叉树指定根结点、森林插入根结点
(4)二叉树与森林的删除操作
(5)二叉树与森林的遍历操作
(6)二叉树与森林的相互转换
(7)二叉树与森林的可视化
程序结构设计
二叉树模块
(1)初始化:void Initialize(int n);
(2)查找指定元素所在的位置:binaryTreeNode* find(int element);
(3)插入结点:void InsertNode(int pos,int father,int node);
(4)删除结点:void erase(binaryTreeNode *t);
(5)改变根节点:void ChangeRoot(binaryTreeNode *t);
(6)前序遍历:int preOrder(binaryTreeNode *t);
(7)可视化:void Visualition();
二叉树与森林的转换模块
(1)树转二叉树
binaryTreeNode* ForestToBinaryTree(int root);
(2)森林转二叉树
void Transform(linkedBinaryTree& change1);
(3)二叉树转森林
void BiNodeToFNode(binaryTreeNode *t,Forest &f);
void BTreeToForest(Forest &t);
设计思路
二叉树模块
(1)初始化:void Initialize(int n);
首先指定二叉树初始状态结点的个数并指定根结点,然后申请一个二叉树结点数组用于后续的结点插入,最后输入结点信息并执行插入操作。
(2)查找指定元素所在的位置:binaryTreeNode* find(int element);
输入要查找的元素信息,然后从二叉树的根结点开始执行层次遍历,逐层查找指定元素,找到则返回对应的二叉树结点指针,找不到则返回空指针。
(3)插入结点:void InsertNode(int pos,int father,int node);
首先查找到father所对应的结点位置,然后根据pos和node中的信息来插入左/右孩子。
(4)删除结点:void erase(binaryTreeNode *t);
通过后序遍历来删除二叉树结点,首先递归删除左子树,然后递归删除右子树,最后释放父节点的空间。
(5)改变根节点(重置二叉树):void ChangeRoot(binaryTreeNode *t);
删除当前根节点,然后重置根节点为t。
(6)前序遍历:int preOrder(binaryTreeNode *t);
利用递归的思想,首先访问父节点t,然后前序遍历左子树,最后前序遍历右子树。
(7)可视化:void Visualition();
利用Graphviz扩展库,通过C++读写dot语言文件来实现可视化操作,具体操作是层次遍历二叉树并在遍历的同时申请dot结点,然后根据二叉树的结构来连接各dot结点,最后调用命令行编译dot文件生成图像。
森林模块
(1)初始化:void Initialize(int m,int n);
首先指定森林根节点的数目以及结点总数,然后输入并存储根节点,最后根据输入信息将各结点插入到对应的树中。
(2)插入结点:void InsertNode(int father,int node);
若插入的是根结点,则直接将node存入根结点数组即可,若插入的是子结点,则找到将node结点插入到father对应的链表中即可,注意插入操作要保证链表有序。
(3)插入边:int InsertEdge(int a,int b);
首先遍历森林的根结点数组,若a、b都存在,则在a所对应的链表中插入b并在根结点数组中删除b。
(4)删除结点:bool EraseNode(int father,int node);
将该结点所对应的链表元素全部设为根结点然后清空该链表,若删除的是根结点,则还要将该节点从根结点数组中删除。
(5)遍历树:int ShowLevel(int root);
利用层次遍历,从每棵树的根结点开始逐层扩展并访问树中各结点。
(6)遍历森林:void ShowForest();
首先将所有树的根节点按照从小到大的顺序排序,然后依次遍历森林中的每一棵树。
(7)可视化:void Visualition();
利用Graphviz扩展库,通过C++读写dot语言文件来实现可视化操作,具体操作是层次遍历二叉树并在遍历的同时申请dot结点,然后根据森林的结构来连接各dot结点,最后调用命令行编译dot文件生成图像。
二叉树与森林的转换模块
(1)树转二叉树
binaryTreeNode* ForestToBinaryTree(int root);
从根结点root开始,将与root相连的第一个元素作为root的左孩子,然后递归转换左子树,并将root左孩子的兄弟作为root的右子树,再对右子树进行递归转换。
(2)森林转二叉树
void Transform(linkedBinaryTree& change1);
首先对所有的根结点进行排序,然后对森林中的每一棵树进行转换并按照顺序连接即可。
(3)二叉树转树
void BiNodeToFNode(binaryTreeNode *t,Forest &f);
对于结点t,若结点t的左孩子存在,则将这个左孩子的右子树改为结点t的右子树,再对该右子树进行递归转换,右子树转换完毕后,将结点t向左移动再次进行相同操作,直至结点t指向的为空指针。
(4)二叉树转森林
void BTreeToForest(Forest &t);
从二叉树的根结点开始,沿着右孩子指针将二叉树分离即得到森林的根结点,再对分离后的根结点依次执行上述的二叉树转树操作,即可转换成森林。
代码实现
核心代码如下:
#ifndef FORESTANDBTREE_H
#define FORESTANDBTREE_H
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
void AppendInt(string &s,int &a){
char buf[10];
itoa(a,buf,10);
s+=buf;
}
string BNodeInfo(int e){
string father="";
string element="";
AppendInt(element,e);
father+=element;
father+="[label=\"<f0>|<f1>";
father+=element;
father+="|<f2>\"]";
return father;
}
struct binaryTreeNode
{
int element;
binaryTreeNode *leftChild,
*rightChild;
binaryTreeNode() {leftChild = rightChild = NULL;}
binaryTreeNode(int& theElement):element(theElement)
{
leftChild = rightChild = NULL;
}
binaryTreeNode(int& theElement,
binaryTreeNode *theLeftChild,
binaryTreeNode *theRightChild)
:element(theElement)
{
leftChild = theLeftChild;
rightChild = theRightChild;
}
};
struct ForestNode
{
int element;
ForestNode *next;
ForestNode() {element=0;next=NULL;}
ForestNode(int& theElement):element(theElement)
{
next=NULL;
}
ForestNode(int& theElement,ForestNode *thenext)
:element(theElement)
{
next=thenext;
}
};
class chain
{
public:
friend class Forest;
chain(){firstnode=NULL;csize=0;}
~chain();
int size(){return csize;}
void insert(int key);
bool erase(int key);
private:
ForestNode* firstnode;
int csize;
};
chain::~chain()
{
while(firstnode!=NULL)
{
ForestNode *p=firstnode->next;
delete firstnode;
firstnode=p;
}
}
void chain::insert(int key)
{
ForestNode *p=firstnode;
ForestNode *q=NULL;
while(p!=NULL&&p->element<key)
{
q=p;
p=p->next;
}
if(p!=NULL&&p->element==key){}
else
{
ForestNode *t=new ForestNode(key,p);
if(q==NULL)
firstnode=t;
else
q->next=t;
csize++;
}
}
bool chain::erase(int key)
{
ForestNode *p=firstnode;
ForestNode *q=NULL;
while(p!=NULL&&p->element<key)
{
q=p;
p=p->next;
}
if(p!=NULL&&p->element==key)
{
if(q==NULL)
firstnode=p->next;
else
q->next=p->next;
delete p;
csize--;
return true;
}
else{return false;}
}
class linkedBinaryTree;
class Forest
{
public:
friend class linkedBinaryTree;
Forest(int n);
Forest(){NodeSize=0;tree=new chain[5500];}
~Forest(){}
void Initialize(int m,int n);
void InsertNode(int father,int node);
int InsertEdge(int a,int b);
bool EraseNode(int father,int node);
binaryTreeNode* ForestToBinaryTree(int root);
void Transform(linkedBinaryTree& change1);
void ShowForest();
int ShowLevel(int root);
void Visualition();
protected:
chain *tree;
vector<int> root;
int NodeSize;
};
class linkedBinaryTree
{
public:
friend class Forest;
linkedBinaryTree() {root = NULL;}
~linkedBinaryTree(){erase(root);root = NULL;};
bool empty() const {return root == NULL;}
int preOrder(binaryTreeNode *t);
void erase(binaryTreeNode *t);
void InsertNode(int pos,int father,int node);
void Initialize(int n);
binaryTreeNode* find(int element);
int PreOrder(){return preOrder(root);}
void levelorder(binaryTreeNode *t);
void LevelOrder(){levelorder(root);cout<<endl;}
void ChangeRoot(binaryTreeNode *t){erase(root);root=t;};
void BiNodeToFNode(binaryTreeNode *t,Forest &f);
void BTreeToForest(Forest &t);
void Visualition();
protected:
binaryTreeNode *root;
};
void linkedBinaryTree::Visualition(){
freopen("binarytree.dot","w",stdout);
cout<<"digraph G{"<<endl;
cout<<"label=\"Binary Tree\";"<<endl;
cout<<"node[shape=record];"<<endl;
queue<binaryTreeNode *> q;
binaryTreeNode *tmp=root;
q.push(tmp);
while(!q.empty()){
binaryTreeNode *t=q.front();
q.pop();
string father=BNodeInfo(t->element);
cout<<father<<";"<<endl;
if(t->leftChild!=NULL){
string left=BNodeInfo(t->leftChild->element);
cout<<left<<";"<<endl;
cout<<t->element<<":f0:sw->"<<t->leftChild->element<<":f1;"<<endl;
q.push(t->leftChild);
}
if(t->rightChild!=NULL){
string right=BNodeInfo(t->rightChild->element);
cout<<right<<";"<<endl;
cout<<t->element<<":f2:se->"<<t->rightChild->element<<":f1;"<<endl;
q.push(t->rightChild);
}
}
cout<<"}"<<endl;
fclose(stdout);
string s = "";
s += "dot -Tpng ";
s += "binarytree.dot";
s += " -o ";
s+="binarytree.png";
const char* cmd = s.data();
system(cmd);
freopen("CON","w",stdout);
}
void linkedBinaryTree::levelorder(binaryTreeNode *t){
queue<binaryTreeNode *> q;
q.push(t);
while(!q.empty()){
binaryTreeNode *p=q.front();
cout<<p->element<<" ";
q.pop();
if(p->leftChild!=NULL)
q.push(p->leftChild);
if(p->rightChild!=NULL)
q.push(p->rightChild);
}
}
binaryTreeNode* linkedBinaryTree::find(int element){
queue<binaryTreeNode*> q;
binaryTreeNode* tmp=root;
q.push(tmp);
while(!q.empty()){
binaryTreeNode* t=q.front();
q.pop();
if(t->element==element)
return t;
if(t->leftChild!=NULL)
q.push(t->leftChild);
if(t->rightChild!=NULL)
q.push(t->rightChild);
}
return NULL;
}
void linkedBinaryTree::Initialize(int n){
int rr;
cin>>rr;
binaryTreeNode* nodes[n+10];
for(int i=1;i<=n;i++){
nodes[i]=new binaryTreeNode(i);
}
int A,l,r;
for(int i=0;i<n;i++){
cin>>A>>l>>r;
if(l!=-1)
nodes[A]->leftChild=nodes[l];
if(r!=-1)
nodes[A]->rightChild=nodes[r];
}
root=nodes[rr];
}
void linkedBinaryTree::InsertNode(int pos,int father,int node){
queue<binaryTreeNode*> q;
binaryTreeNode* tmp=root;
q.push(tmp);
while(!q.empty()){
binaryTreeNode* t=q.front();
q.pop();
if(t->element==father){
if(pos==0){
t->rightChild=new binaryTreeNode(node);
}
else{
t->leftChild=new binaryTreeNode(node);
}
return;
}
if(t->leftChild!=NULL)
q.push(t->leftChild);
if(t->rightChild!=NULL)
q.push(t->rightChild);
}
}
void linkedBinaryTree::erase(binaryTreeNode *t)
{
if (t != NULL)
{
erase(t->leftChild);
erase(t->rightChild);
delete t;
}
}
int linkedBinaryTree::preOrder(binaryTreeNode *t)
{
int sum=0;
if (t != NULL)
{
sum^=t->element;
sum^=preOrder(t->leftChild);
sum^=preOrder(t->rightChild);
}
return sum;
}
void linkedBinaryTree::BiNodeToFNode(binaryTreeNode *t,Forest &f)
{
binaryTreeNode* r=t;
binaryTreeNode* p=r;
while(r!=NULL){
int father=r->element;
p=r->leftChild;
while(p!=NULL){
f.tree[father].insert(p->element);
p=p->rightChild;
BiNodeToFNode(p,f);
}
r=r->leftChild;
}
}
void linkedBinaryTree::BTreeToForest(Forest &t)
{
vector<binaryTreeNode*> ROOT;
binaryTreeNode *tmp=root;
while(tmp!=NULL){
binaryTreeNode *rroot=new binaryTreeNode(tmp->element);
rroot->leftChild=tmp->leftChild;
ROOT.push_back(rroot);
tmp=tmp->rightChild;
}
int size=ROOT.size();
for(int i=0;i<size;i++){
t.root.push_back(ROOT[i]->element);
binaryTreeNode* r=ROOT[i];
BiNodeToFNode(r,t);
}
}
void Forest::Visualition(){
freopen("forest.dot","w",stdout);
cout<<"digraph G{"<<endl;
cout<<"label=\"Forest\";"<<endl;
cout<<"node[shape=circle];"<<endl;
sort(root.begin(),root.end());
int size=root.size();
for(int i=0;i<size;i++){
queue<int> q;
q.push(root[i]);
cout<<root[i]<<";"<<endl;
while(!q.empty()){
int tmp=q.front();
q.pop();
ForestNode *p=tree[tmp].firstnode;
while(p!=NULL){
cout<<p->element<<";"<<endl;
cout<<tmp<<"->"<<p->element<<";"<<endl;
q.push(p->element);
p=p->next;
}
}
}
cout<<"}"<<endl;
fclose(stdout);
string s = "";
s += "dot -Tpng ";
s += "forest.dot";
s += " -o ";
s+="forest.png";
const char* cmd = s.data();
system(cmd);
freopen("CON","w",stdout);
}
Forest::Forest(int n){
NodeSize=n;
tree=new chain[n+200];
}
void Forest::Initialize(int m,int n){
int NodeElement;
for(int i=1;i<=m;i++){
int rootnode;
cin>>rootnode;
root.push_back(rootnode);
}
int father,num;
for(int i=1;i<=n;i++){
cin>>father>>num;
while(num--){
cin>>NodeElement;
tree[father].insert(NodeElement);
}
}
}
int Forest::ShowLevel(int root){
int sum=0;
queue<int> q;
q.push(root);
sum^=root;
while(!q.empty()){
int tmp=q.front();
q.pop();
ForestNode *p=tree[tmp].firstnode;
while(p!=NULL){
sum^=p->element;
q.push(p->element);
p=p->next;
}
}
return sum;
}
void Forest::ShowForest(){
sort(root.begin(),root.end());
int size=root.size();
for(int i=0;i<size;i++)
cout<<ShowLevel(root[i])<<" ";
cout<<endl;
}
void Forest::InsertNode(int father,int node){
if(father==-1){
root.push_back(node);
}
else{
tree[father].insert(node);
}
NodeSize++;
}
bool Forest::EraseNode(int father,int node){
bool flag=false;
if(father==-1){
vector<int>::iterator iter=root.begin();
while(iter!=root.end()){
if(*iter==node){
flag=true;
root.erase(iter);
break;
}
iter++;
}
ForestNode *p=tree[node].firstnode;
while(p!=NULL){
root.push_back(p->element);
ForestNode *q=p->next;
delete p;
p=q;
}
}
else{
flag=tree[father].erase(node);
ForestNode *p=tree[node].firstnode;
while(p!=NULL){
root.push_back(p->element);
ForestNode *q=p->next;
delete p;
p=q;
}
}
NodeSize--;
return flag;
}
int Forest::InsertEdge(int a,int b){
bool flaga=0;
bool flagb=0;
vector<int>::iterator iter=root.begin();
while(iter!=root.end()){
if(*iter==a){
flaga=true;
}
if(*iter==b){
flagb=true;
root.erase(iter);
}
iter++;
}
if(flaga&&flagb){
tree[a].insert(b);
return 0;
}
else if(flaga&&!flagb){
return 2;
}
else if(!flaga&&flagb){
return 1;
}
else
return 3;
}
binaryTreeNode* Forest::ForestToBinaryTree(int root)
{
binaryTreeNode* binaryRoot = new binaryTreeNode(root);
if (tree[root].size()<=0){
return binaryRoot;
}
binaryRoot->leftChild = ForestToBinaryTree(tree[root].firstnode->element);
binaryTreeNode *brotherChild = binaryRoot->leftChild;
ForestNode *p=tree[root].firstnode->next;
while(p!=NULL)
{
brotherChild->rightChild = ForestToBinaryTree(p->element);
brotherChild = brotherChild->rightChild;
p=p->next;
}
return binaryRoot;
}
void Forest::Transform(linkedBinaryTree& change1){
sort(root.begin(),root.end());
binaryTreeNode *t=ForestToBinaryTree(root[0]);
binaryTreeNode* tmp=t;
int size=root.size();
for(int i=1;i<size;i++){
tmp->rightChild=ForestToBinaryTree(root[i]);
tmp=tmp->rightChild;
}
change1.ChangeRoot(t);
}
#endif
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)