一. 实验目的
-
键盘输入数据,构建一颗二叉树(双链存储);
-
递归算法实现二叉树遍历,前序、中序、后续均可;
-
2 中算法改写为非递归算法实现。
二. 实验内容及算法解释
- 数据类型解释:
struct leaf{
int data;
struct leaf *lchild;
struct leaf *rchild;
};
双链节点,每个节点有三个数据域,一个为数据存储,其余两个分别指向左孩子和右孩子。
- 二叉树创建:
struct leaf *InitBiTree ()//输入一个数字,构成根节点
{
int num;
scanf("%d", &num);
struct leaf *root = (struct leaf*)malloc(sizeof(struct leaf));
if(num > 0)
{
root->data = num;
root->lchild = (struct leaf*)malloc(sizeof(struct leaf)); root->lchild->data = -1;
root->rchild = (struct leaf*)malloc(sizeof(struct leaf)); root->rchild->data = -1;
}
else return NULL;
return root;
}
为了后续插入遍历方便,我将每一个节点的左右孩子存储的数据均赋为-1(此数据不可能从键盘输入,可作为该节点为空的标志)。
- 二叉树的延伸:
void Insert ( struct leaf *root )//添加数据作为子节点
{
printf("%d ", root->data);
struct leaf *stack[256];
stack[0] = root->lchild;
stack[1] = root->rchild;
int top = 0;
int plc = 2;
int num;
while(1)
{
scanf("%d", &num);
if ( num < 0 ) break;
else{
printf("%d ", num);
struct leaf *p = stack[top++];
p->data = num;
p->lchild = (struct leaf*)malloc(sizeof(struct leaf)); p->lchild->data = -1;
p->rchild = (struct leaf*)malloc(sizeof(struct leaf)); p->rchild->data = -1;
stack[plc++] = p->lchild;
stack[plc++] = p->rchild;
}
}
printf("\n");
}
我采用的是完全二叉树构建方式。每添加一个数据,都按满二叉树编号的顺序插入到已有的二叉树里。为了找到下一个空的叶子,我建立了一个存储空叶子的栈,每出现空叶子,就进栈;叶子存储数据后就出栈,并将它的左右孩子进栈。
- 递归前序遍历:
void PreOrderTraverse1 ( struct leaf* root )//递归前序遍历,按顺序输出该完全二叉树的各个节点。
{
if ( root->data == -1 ) return;
else{
printf("%d ", root->data);
PreOrderTraverse1 ( root->lchild );
PreOrderTraverse1 ( root->rchild );
}
}
- 非递归前序遍历:
void PreOrderTraverse2 ( struct leaf* root )//非递归前序遍历,按顺序输出该完全二叉树的各个节点。
{
struct leaf *stack[256];
struct leaf *p = root;
int top = 0;
while ( p->data != -1 )
{
printf("%d ",p->data);
struct leaf *q = p->rchild;
if ( q->data != -1 ) stack[top++] = q;
p = p->lchild;
if ( p->data == -1 && top == 0 ) break;
else if ( p->data == -1 ) p = stack[--top];
}
printf("\n");
}
三. 实验结果
-
输入:1 2 3 -1
输出:1 2 3
1 2 3
-
输入:1 2 3 5 6 12 3 15 1 1 -1
输出:1 2 3 5 6 12 3 15 1 1
1 2 5 15 1 6 1 3 12 3
此结果符合完全二叉树结构和前序遍历输出顺序