知识点
二叉树生成
广义表表示二叉树结构生成二叉链表
二叉树的广义表表示形式为: (A(B(,D(E,F)),C))。特点:靠近左括号的结点是在左子树上,而逗号右边的结点是在右子树上。
BinTNode *CreateTree(char *str) {
BinTNode *st[100];
BinTNode *p = NULL;
int top, k, j = 0;
top = -1;
char ch = str[j];
BinTNode *b = NULL;
while (ch != '\0')
{
switch (ch) {
case '(':
top++;
st[top] = p;
k = 1;
break;
case ')':
top--;
break;
case ',':
k = 2;
break;
default:
p = (BinTNode *)malloc(sizeof(BinTNode));
p->data = ch;
p->lchild = p->rchild = NULL;
if (b == NULL)
b = p;
else {
switch (k) {
case 1:
st[top]->lchild = p;
break;
case 2:
st[top]->rchild = p;
break;
}
}
}
j++;
ch = str[j];
}
return b;
}
完全二叉树的层次顺序依次输入结点信息建立二叉链表的算法
如下图所示:
下标从1开始,处理起来更方便些。牺牲下标为0的结点。
算法思想
根据 一维数组读出来的字符,建立下需那个二叉链表。如果读出来不是@,就建立一个新的结点,如果是第一个是那就是根结点,不是,就是左孩子或右孩子链到双亲结点上。
算法实现
BinTree CreateBinTree(BinTree bt) {
BinTNode *Q[100];
BinTNode *s;
int front,rear;
char ch;
ch = getchar();
bt = NULL;
front = 1;
rear = 0;
while (ch != '#')
{
s = NULL;
if (ch != '@') {
s = (BinTNode *)malloc(sizeof(BinTNode));
s->data = ch;
s->lchlid = s->rchiId = NULL;
}
rear++;
Q[rear] = s;
if (rear == 1)
bt = s;
else {
if (s != NULL && Q[front] != NULL)
if (rear % 2 == 0)
Q[front]->lchild = s;
else
Q[front]->rchild = s;
if (rear % 2 != 0)
front++;
}
ch = getchar();
}
return bt;
}
二叉树遍历,必考
遍历
是指沿着某条搜索路径(线)周游二叉树,依次对树中每个结点访问且仅访问一次。
递归遍历算法
(1)先序遍历DLR(根左右):也叫先根遍历,若二叉树非空,则依次执行如下操作: ① 访问根结点; ②遍历左子树;③遍历右子树。
(2)中序遍历LDR(左根右):也叫中根遍历,若二叉树非空,则依次执行如下操作: ①遍历左子树; ②访问根结点; ③遍历右子树。
(3)后序遍历LRD(左右根):也叫后根遍历,若二叉树非空,则依次执行如下操作: ①遍历左子树; ②遍历右子树; ③访问根结点。
递归算法实现
前根遍历
void Preorder(BinTree bt)
{
if(bt!=NULL)
{ printf("%c",bt->data);
Preorder(bt->lchild);
preorder(bt->rchild);
}
}
中根遍历
void Inorder(BinTree bt)
{ if(bt!=NULL)
{ Inorder(bt->lchild);
printf("%c",bt->data);
Inorder(bt->rchild);
}
}
后根遍历
void Postorder(BinTree bt)
{ if(bt!=NULL)
{ Postorder(bt->lchild);
Postorder(bt->rchild);
printf("%c",bt->data);
}
}
非递归算法实现
利用栈的非递归中根遍历算法
void Inorderl(BinTree bt)
{
SeqStack S;
BinTNode *P;
InitStack(&S);
Push(&S,bt);
while (!StackEmpty(&S)) {
while (GetTop(&S))
Push(&S,GetTop(&S)->lchild);
p = Pop(&S);
if (!StackEmpty(&S)) {
printf("%c",GetTop(&S)->data);
p = Pop(&S);
Push(&S,p->rchild);
}
}
}
利用指针数组实现中根遍历
实质是用指针数组模拟堆栈
void Inorder2(B1nTree bt)
{
BinTNode *ST[100];
int top = 0;
ST[top] = bt;
do {
while (ST[top] != NULL)
{
top = top + 1;
ST[top] = ST[top - 1]->lchild;
}
top = top - 1;
if (top >= 0)
{
printf("%c", ST[top]->data);
ST[top] = ST[top]->rchild;
}
} while (top != -1);
}
利用栈实现前根遍历
思想:利用栈先将二叉树根结点指针入栈,然后执行出栈,获取栈顶元素值(即结点指针),若不为空值,则访问该结点,再将右、左子树的根结点指针分别入栈,依次重复出栈、入栈,直至栈空为止。
void Preorderl(BinTree bt)
{
SeqStack S;
InitStack(&S);
Push(&S, bt);
while (!StackEmpty(&S))
{
bt = Pop(&S);
if (bt != NULL)
{
printf("%c", bt->data);
Push(&S, bt->rchild);
Push(&S, bt->lchiid);
}
}
}
非递归层次遍历
从上到下,从左到右 算法思想: 采用一队列Q,若树不空,先将二叉树根结点输出,并将根结点指针入队,然后出队。然后将左右儿子入队,出队,出队时当左右儿子依次入队,再出队…
void TransLevel(BinTree bt)
{
cirQueue Q;
InitQueue(&Q);
if (bt == NULL)
return;
else {
printf("%c", bt->data);
EnQueue(&Q, bt);
while (!QueueEmpty(&Q)) {
bt = DeQueue(&Q);
if (bt->rchild != NULL) {
printf("%c", bt->lchild->data);
EnQueue(&Q, bt->lchild);
}
if (bt->rchild != NULL) {
printf("%c", bt->rchild->data);
EnQueue(&Q, bt->rchild);
}
}
}
}
由遍历恢复二叉树,必考
-
已知二叉树的前序遍历序列和中序遍历序列,可以唯一地恢复该二叉树。 原则是:在前序序列中确定根结点(最前面那个结点一定是根结点),然后根据根结点在中序序列中的位置分出根结点的左、右子树(根结点前面的那些结点为根结点的左子树上的结点,根结点后面的那些结点为根结点的右子树上的结点)。恢复该二叉树的任何一棵子树的过程仍然遵循这个原则 -
同理,已知二叉树的中序遍历序列和后序遍历序列,也可以唯一地恢复该二叉树 只是在后序序列中去确定根结点(最后面那个结点一定是根结点),而在中序序列中分出左右子树的过程与上述过程没有区别。 -
已知二叉树的前序遍历序列和后序遍历序列,无法唯一地恢复该二叉树,因为无法确定左右子树。
真题
已知二叉树的链式存储结构,求二叉树的深度。
分析:若一棵二叉树为空,则它的深度为0,否则它的深度等于其左右子树中的最大深度加l。设depl和depr分别表示左右子树的深度,则二叉树的深度为: max(depl,depr)+1
int BinTreeDepth(BinTree bt)
{
int depl, depr;
if (bt == NULL)
return 0;
else {
depl = BinTreeDepth(bt->lchild);
depr = BinTreeDepth(bt->rchild);
if (depl > depr)
return depl + 1;
else
return depr + 1;
}
}
以二叉链表为存储结构,试编写p所指结点在树中层数的算法。
分析:设h为返回P所指结点的所在层数,初值为0;树为空时返回0。lh指示二叉树bt的层数(即高度),调用时置初值为为l。
int Level(BinTree bt, BinTNode* P, int lh)
{
static int h = 0;
if (bt == NULL)
h = 0;
else if (bt == p)
h = lh;
else {
Level(bt->lchild, p, lh + 1);
if (h == 0)
Level(bt->rchild, p, lh + 1);
}
return h;
}
ic int h = 0;
if (bt == NULL)
h = 0;
else if (bt == p)
h = lh;
else {
Level(bt->lchild, p, lh + 1);
if (h == 0)
Level(bt->rchild, p, lh + 1);
}
return h;
}
|