内容:编写程序,实现下述功能,并上机调试通过。
1.按中序顺序建立一课二叉树;
2.用非递归的方式遍历二叉树(先序,中序或后序),输出遍历序列
本题有两个要求,首先,要用中序顺序建立二叉树。但问题在于,只用中序输入无法创建一个确定的二叉树,因为对于一个已知的中序遍历结果,由于根节点不确定性,所以可能会对应多种不同结构的二叉树,例子如下:
所以我们要想办法解决根节点不确定的问题,对此有两个方向的想法。
一是:在编译过程规定好根节点的标识符,当输入该字符时,直接将该字符定义为根节点,在遍历结果中,该字符左侧即为左子树成员,右侧即为右子树成员。最左侧元素即为一个叶子结点。由此可生成一个确定的二叉树。
二是:通过采用其他的结构(先序,后序,层序)与中序结果进行比对,通过对同一二叉树的不同遍历结果,找出根节点在中序遍历结果中的位置,该位置以左即为左子树,以右即为右子树。此报告以中序加后序为例进行演示。后序遍历的最后一个元素即为整个二叉树根节点,在通过递归的方法求左子树的根节点,以此类推,求完左子树的所有元素后,再同方法求右子树的所有元素,完成整个二叉树的创建。
问题的第二部分要求用非递归方法实现二叉树的先序遍历,首先,将生成的二叉树以二叉链表的形式存储,一维数组stack[MAXNODE]用以实现栈,设置变量top用以表示栈顶位置,通过top值的变化实现栈的遍历,即二叉树的遍历。
代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNODE 100
typedef char TElemType;
typedef int Status;
typedef struct BiTNode
{
TElemType data;
struct BiTNode* lchild, * rchild;
}BiTNode, * BiTree;
//中序后序建立二叉树
BiTNode* Creat(int len, char* zhong, char* hou)
{
if (len == 0)//长度为0,返回错误
{
return NULL;
}
//创建根节点
BiTNode* T;
T = (struct BiTNode*)malloc(sizeof(struct BiTNode));
//由后续遍历二叉树得,后序的第一个元素即为根节点
T->data = hou[len - 1];
int i;
for (i = 0; i < len; i++)
if (hou[len - 1] == zhong[i])
break;
//for循环找出中序的根节点在数组中的位置
//构造左子树
T->lchild = Creat(i, zhong, hou);//通过递归找左子树的根节点,结束后i的值为左子树中节点的个数
//构造右子树
T->rchild = Creat(len - i - 1, zhong + i + 1, hou + i);//通过递归找右子树的根节点
//zhong+i为根节点的地址值
return T;
}
//访问根节点
void visite(char ch)
{
printf("%c", ch);
}
//非递归先序遍历
void NRPreOrder(BiTree T)
{
BiTree stack[MAXNODE], p;
int top;
if (T == NULL)return;
top = 0;
p = T;
while (!(p == NULL && top == 0))
{
while (p != NULL)
{
visite(p->data);
if (top < MAXNODE - 1)
{
stack[top] = p;
top++;
}
else
{
printf("栈溢出");
return;
}
p = p->lchild;
}
if (top <= 0)return;
else
{
top--;
p = stack[top];
p = p->rchild;
}
}
}
int main()
{
char zhong[100], hou[100];
int len;
printf("中序二叉树:\n");
gets_s(zhong, 99);
printf("后序二叉树:\n");
gets_s(hou, 99);
BiTNode* T = NULL;
len = strlen(zhong);
T = Creat(len, zhong, hou);
printf("先序遍历:\n");
NRPreOrder(T);
return 0;
}
内容:
若用二叉链表作为二叉树的存储表示,设计算法求二叉树中度为1的节点数量。
算法分析:
某一节点的度即为该节点所拥有的子树数量,本题前置条件为二叉树,所以某一节点的度最多为2,度为1的节点即只有左子树,或只有右子树。
想要达到题目要求找只有一个子树的结点,所以需要遍历整个二叉树,才能找出符合要求的节点数目,需要通过一个计数器来记下度为1的结点的数量。
详细步骤:
首先,我们需要判断当前结点的左右孩子的情况,若其有左右孩子,则直接先以左孩子的结点为根节点,继续判断,以此类推,直到某一结点的左右孩子都为空或者只有一个孩子,返回。当其只有左孩子时,即根节点本身度为1,所以先将度为1的情况+1,再将该结点的左孩子节点作为根节点,继续向下判断执行。同理,当其只有右孩子时,也先将度为1的情况+1,再将该结点的右孩子节点作为根节点,继续向下判断执行。直到所有结点均被遍历时,函数调用结束,输出此时的值,即为二叉链表的度为1的值。
总结:
利用二叉树结构上的递归特性,用递归的方法实现。若某结点有左子树和右子树,则以此结点为根的二叉树中度为1的结点个数=左子树的度为1的结点个数+右子树中度为1的结点数。若该结点只有一棵子树,则以此结点为根的二叉树中度为 1 的结点个数=1 +其唯一子树中度为1的结点个数。若该结点没有子树,则此结点为根的二叉树中度为1的结点个数=0。
算法代码如下
typedef struct Node
{ //二叉树的二叉链表结点的结构
DataType data;
struct Node *LChild;
struct Node *Rchild;
} BiTNode, *BiTree;
int Num(BiTree ptr)
{
BiTNode *temp;
if (ptr->LChild != NULL&&ptr->Rchild != NULL) //该二叉树均有左右孩子
return Num(ptr->LChild) + Num(ptr->Rchild);
else if (ptr->LChild == NULL&&ptr->Rchild != NULL) //该二叉树只有右孩子
return 1 + Num(ptr->Rchild);
else if (ptr->LChild != NULL&&ptr->Rchild == NULL) //该二叉树只有左孩子
return 1 + Num(ptr->LChild);
return 0;
}//使用该算法时对象需要是二叉树