SDUT 二叉树(数组模拟) part1
p.s.讲的有点快,但是博文写的比较详细,各位多花点时间看博文吧。
相关概念
- 树:连通无回路的无向图
- 二叉树:树中节点的度不大于2的有序树
- 结点:包含一个数据元素及若干指向子树分支的信息
- 结点的度:一个结点拥有子树的数目称为结点的度
- 叶子结点:也称为终端结点,没有子树的结点或者度为零的结点
- 分支结点:也称为非终端结点,度不为零的结点称为非终端结点
- 树的度:树中所有结点的度的最大值
- 树的深度:也称为树的高度,树中所有结点的层次最大值称为树的深度
- 有序树:如果树中各棵子树的次序是有先后次序,则称该树为有序树
先序中序后序
直观的说,不同的遍历次序本质上,都是将一个字符串分成三个部分,分别指的是当前节点和其左右根。它其实是递归定义的,分别对于其左右部分,又可以有这三部分组成的结构。
其次序分别为:
先序:“根 左 右”
中序:“左 根 右”
后序:“左 右 根”
举个例子(先序输入):
随便画个二叉树
按照先序遍历,’,'代表其节点为空,应该有如下字符串
abd,,e,g,,c,f,,
遍历过程如下图:
相信看完上面过程,同学们对三个部分有了一定理解了。
先序中序后序的遍历输出比较简单,一并放在下面了。
数组模拟建树
原博客:数组模拟建树 oj 3341
建树模板
const int N = 100;
char str[N];///读入的字符串
int cnt;///树的序号,当有元素要存到里面时才自增1
int now;///字符串中光标的位置
struct tree {
char data;///字符型数据
int lc, rc;///左孩子,右孩子
}a[N];///节点的结构
int create(){///主函数先序读入str,递归建树
char temp = str[now ++];///temp代表当前的字符,并且将光标挪到下面
if(temp == ','){///如果该节点为空,标记其为-1,作为孩子返回
return -1;
}
int id = cnt ++;///从id = 0开始存
///先序:“根 左 右”
///故 先存数据,再找左右
a[id].data = temp;
a[id].lc = create();
a[id].rc = create();
return id;
}
遍历模板
依次输出,不包括空节点,无换行(输出之后可能需要手动换行)
/*
先序:“根 左 右”
中序:“左 根 右”
后序:“左 右 根”
其实变化的只有函数套用的顺序
中序是 1.找左节点 2.输出根 3. 找右节点
先序就是 1 2交换位置
后序就是 2 3交换位置
下面依次是先序/中序/后序输出
*/
void bef(int id){
if(id == -1){
return ;
}
printf("%c",a[id].data);
bef(a[id].lc);
bef(a[id].rc);
}
void mid(int id){
if(id == -1){
return ;
}
mid(a[id].lc);
printf("%c",a[id].data);
mid(a[id].rc);
}
void aft(int id){
if(id == -1){
return ;
}
aft(a[id].lc);
aft(a[id].rc);
printf("%c",a[id].data);
}
层序(BFS)
原博客:数组模拟层序输出 oj 3344
层序输出模板
//需要调用queue头函数
//本函数并不是递归调用,而是while循环直到没有元素可以入队
void seq_show(int root){///Sequence 层序
if(root == -1) return ;///避免出现空树的情况
queue<int> q;
q.push(root);///存队首
while(!q.empty()){
///弹出队列最前方元素并输出
int id = q.front();
q.pop();
printf("%c",a[id].data);
///如果该元素有左右孩子,入队
///这样从树的结构上来说,保证了树上层大于下层(优先级1),左边大于右边(优先级2)
if(a[id].lc != -1)
q.push(a[id].lc);
if(a[id].rc != -1)
q.push(a[id].rc);
}
}
层序bfs函数图解如下
其他
通过中序后序得到二叉树
通过先序中序得到二叉树
感谢学习!