创建:
和二叉树一样结点内部拥有两个指针,不过不是指向左右子树,而是指向孩子结点和兄弟结点。兄弟结点之间互相连接,在同一层,孩子结点在下一层,结构像广义表,45度观看又像二叉树。创建方式类似二叉树的层序建立,也需要借助队列结构。
先处理根结点,获取第一个输入字符,保存至根结点中,将该结点入队,然后进入循环:
数据优先存放到某结点的子树中,然后再存放到其兄弟结点中。
获取队头结点,并让其出队。获取输入字符,将其保存至当前结点的长子结点(第一个孩子结点,即直接与父结点相连的子结点)中,然后长子结点入队,接下来在遇到井号之前,数据会循环保存到长子结点的兄弟结点中(当前结点的所有子结点),且将兄弟结点入队。重复上述过程,直到队列为空。
//定义结点
typedef struct mytree
{
char data;
mytree *child=nullptr;
mytree *brother=nullptr;
}mytree;
void creat_tree(mytree *&T)
{
queue<mytree*> q;
mytree *p=T;
char ch;
cin >> ch;
if(ch!='#')
{
T=new mytree;
T->data=ch;
q.push(T);
}
while(!q.empty())
{
p=q.front();
q.pop();
cin >> ch;
if(ch!='#')
{
//先将数据存放到长子中,并将其入队
p->child=new mytree;
p->child->data=ch;
q.push(p->child);
//p指向该结点的长子,在遇到#之前,接下来的字符都存放在长子的兄弟中
p=p->child;
cin >> ch;
while(ch!='#')
{
p->brother=new mytree;
p->brother->data=ch;
q.push(p->child);
p=p->brother;//指向下一个兄弟
cin >> ch;
}
}
}
}
先根遍历:
先访问父节点,再递归访问其子结点和兄弟结点。逻辑类似二叉树的先序遍历。
void PreOrderTraverse(mytree *&T)
{
if(T!=nullptr)
{
cout << T->data << endl;
PreOrderTraverse(T->child);
PreOrderTraverse(T->brother);
}
}
后根遍历:
与先根遍历相反,先递归访问父节点的子结点和兄弟结点,再访问父节点。逻辑类似二叉树的后序遍历。
void PostOrderTraverse(mytree *&T)
{
if(T!=nullptr)
{
PostOrderTraverse(T->child);
PostOrderTraverse(T->brother);
cout << T->data << endl;
}
}