树(3)---树与森林

树的存储结构

树也就是二叉树的加强版,一个头结点有多个后继,其余性质与二叉树相仿。

所以树便有了一种与二叉树相对应的存储方法

孩子兄弟法:

简单的来说,就是一种变种的二叉树,二叉树的结点,一个指针域存储树的孩子(也就是他的子树),一个指针域存储树的兄弟(也就是他相邻的子树),这样便将一棵树使用二叉树的方式储存了。


遍历的改变

先序遍历:

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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值