大话面试题--树

1、树这种数据结构存在的意义

我们都知道最简单的数据结构分为数组,和链表,一种便于查找,一种便于插入。但是在大型存储或计算系统中,二者操作都很多,既有大规模的数据查找,又有新的数据或操作日志进行插入。因此树这种查找和插入介于两者之间的数据结构就变得十分常用。
我们所说的这些数据结构都是在内存中的。比如一颗树我们在内存中记录成以下的样子:
在这里插入图片描述
树这种数据结构在实际工程这种是没有下盘需求的,因为本身就是作为缓存用来加速读取和插入的。磁盘上面就是单纯的数据,对数据结构没必要保存到磁盘上。
以上述二叉树为例子,上述二叉树是一个二叉搜索树,总能保证左子树比根节点小。这些数据在磁盘上的就是直接存储的,在读取的过程中将树逐步建立起来:
14、8、15、11、10、17
是第一次读到14,构建了根节点,之后读到8,放在14的左子节点,15放在右子节点 ,11比14小,所以到左子树,11比8大,在8的右子树。。。以此类推。

2、序列化,反序列化二叉树

书接上文,面试要求将二叉树序列化,就是能够唯一颗二叉树对应一个字符串(因为有特殊符号表示空节点所以必须是字符串),然后利用这个字符串可以构造出树。其实这也有一定的需求,就是自己写小程序玩的时候,构造树的结构可以利用这个反序列化,输入一个字符串来构造一棵树,不需要逐个节点去构造了。
有的读者想,直接用前序遍历存储难道不行么?
即:
存储为14,8,11,10,15,17
可是这样,如下的树前序遍历也是这个结果:

在这里插入图片描述
简单来说,靠一种遍历方式无法唯一确定一棵树。因此,左右节点为空的,也要表示出来。还有,假如以字符串表示的话,每个节点前面要有特定标识,不然节点14无法和节点1加节点4区分开。
我们在每个节点前面都加上!,空节点用#表示,这棵树组成的字符串就是:
!14!8!11!#!#!10!#!#!15!#!17!#!#
这个字符就可以唯一的表示一棵树。
那么代码如何写呢?(推荐剑指offer这种的流写法)
https://github.com/zhedahht/CodingInterviewChinese2/blob/master/37_SerializeBinaryTrees/SerializeBinaryTrees.cpp
当然笔者自己也写出了一个类似的,无需流数据结构的代码:

class TreeToSequence {
public:

string toPreSequence(TreeNode* root) {
	if (NULL != root)
	{
		string strTmp = "";
		char StrIntTmp[20] = {0};
		_itoa_s(root->val, StrIntTmp,20,10);
		strTmp += "!";
		strTmp +=  StrIntTmp;
		strTmp += toPreSequence(root->left);
		strTmp += toPreSequence(root->right);
		return strTmp;
	}
	else
	{
		return "!#";
	}
}
int BitNum(int n)
{
	int i = 1;
	while (n / 10)
	{
		n /= 10;
		i++;
	}
	return i;
}
TreeNode*  toTreeNode8Sequence(string Str)
{
	if (Str[staticOffset] == '!')
	{
		staticOffset++;
	}
	if (Str[staticOffset] == '#')
	{
		staticOffset++;
		return NULL;
	}

	TreeNode *treeTmp = new TreeNode();
	treeTmp->val = atoi(&Str[staticOffset]);

	staticOffset += BitNum(treeTmp->val);

	treeTmp->left = toTreeNode8Sequence(Str);
	treeTmp->right = toTreeNode8Sequence(Str);
	return treeTmp;
}

 	int staticOffset = 0; //其中这个static是关键,因为每次根据字符串转换为树结构,到下次进入该函数时,不知道上次用了多少个字符,需要记录。而iostram的数据结构却可以较好的解决这个问题。
};

3、利用前序遍历和中序遍历重建二叉树

4、如何在一棵二叉树中查找是否包含另一棵二叉树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值