树的存储结构
树也就是二叉树的加强版,一个头结点有多个后继,其余性质与二叉树相仿。
所以树便有了一种与二叉树相对应的存储方法
孩子兄弟法:
简单的来说,就是一种变种的二叉树,二叉树的结点,一个指针域存储树的孩子(也就是他的子树),一个指针域存储树的兄弟(也就是他相邻的子树),这样便将一棵树使用二叉树的方式储存了。
遍历的改变
先序遍历:
1)访问根结点
2)访问子树
3)访问兄弟树
中序遍历:
1)访问子树
2)访问根结点
3)访问兄弟树
因为不可能先访问兄弟树,也就不存在后序遍历了。
树的创建
这次构造的是一棵无序树,所以选择树的构造方法是一开始创建一棵完整的树。
具体步骤是:
1)输入插入元素
2)测试元素是否为空,为空结束
3)创建新结点,元素插入
4)插入元素孩子结点,重复1~5,(递归调用)
5)插入元素兄弟结点,重复1~5,(递归调用)
这里函数的输入变量,应该为引用。
森林
森林也就是很多树的集合。
一棵树的孩子兄弟表示法是没有右子树的,因为根树是单独的,他没有兄弟。同样的当树不止一棵时,右子树也就能补全了。
代码:
class Node
{
friend class Tree;
int key;//键
string data;//数据域
Node* child;//孩子域
Node* next;//兄弟域
Node(int k,string item) :key(k),data(item){}
};
class Tree
{
public:
void create()//创建树
{
cout << "输入头结点的键和值:" << endl;
create(root);
}
void LCtrave(){ LCtrave(root); }//先序
void CLtrave(){ CLtrave(root); }//中序
int leafnum(){ return leafnum(root); }//叶子数
int defth(){ return defth(root); }//深度
int size()//结点数
{
int t=size(root);
Node* x = root;
while (x->next)
{
t += size(x->next);
x = x->next;
}
return t;
}
private:
Node* root = NULL;//根结点
//工具函数
void create(Node* &x);
void visit(Node* x)//打印元素
{
cout << x->key << ":" << x->data << endl;
}
void LCtrave(Node* x);
void CLtrave(Node* x);
int leafnum(Node* x);
int defth(Node* x);
int size(Node* x);
};
void Tree::create(Node* &x)
{
string item;
int k;
cin >> k >> item;
if (k==0&&item == "NULL")return;
x = new Node(k,item);
cout << "请输入" << x->key << "的孩子:" << endl;
create(x->child);
cout << "请输入" << x->key << "的兄弟:" << endl;
create(x->next);
}
void Tree::LCtrave(Node* x)
{
if (x)
{
visit(x);
LCtrave(x->child);
LCtrave(x->next);
}
}
void Tree::CLtrave(Node* x)
{
if (x)
{
CLtrave(x->child);
visit(x);
CLtrave(x->next);
}
}
int Tree::leafnum(Node* x)
{
if (!x)return 0;//结点空返回0
if (!x->child)//无孩子必为叶子结点
return 1 + leafnum(x->next);
else//有孩子,查询孩子和兄弟的结点树
return leafnum(x->child) + leafnum(x->next);
}
int Tree::defth(Node* x)
{
int c, n;
if (!x)return 0;
else
{
c = defth(x->child);//孩子深度
n = defth(x->next);//兄弟深度
return c + 1 > n ? c + 1 : n;
//根与兄弟比较谁高返回谁
}
}
int Tree::size(Node* x)
{
if (!x)return 0;
int c = 0, n = 0;
if (x->child)
{
c = size(x->child);//孩子结点数
n = size(x->child->next);//孩子兄弟的结点数
}
return c + n + 1;
}