前面我们学习二叉树的性质和二叉树四种遍历的逻辑,这篇文章是对二叉树的的扩展和之前学过四种的遍历代码实现,另外对二叉树的存储结构进行分析,顺便代码实现,博主尽量简单明了表示,哈哈哈,说不难吧又有点难,说容易吧也容易,难搞哦,学习吧学习吧,让小的们卷起来,顺带看你对于这个知识是觉得难还是容易。嘿嘿的
二叉树的顺序存储就是用一组连续的存储单元存放二又树中的结点元素,一般按照二叉树结点自上向下、自左向右的顺序存储。使用此存储方式,结点的前驱和后继不一定是它们在逻辑上的邻接关系,非常适用于满二又树和完全二又树。根据完全二叉树和满二叉树的特性,完全二又树存放在一维数组中,将发现结点的编号正好与数组元素的下标对应。采用顺序存储能够最大地节省存储空间,可以利用数组元素下标值确定结点在二叉树中的位置以及结点之间的关系。(讲人话就是:用一个数组,从下标1开始存,假设我们用i表示,这个结点的左孩子存在下标位置为2i的地方,这个结点的右孩子存在下标2i+1的地方,这样的存储比较适合完全二叉树和满二叉树)
对于一般的二叉树,通常采用链式存储结构。链表中的每一个结点包含两个指针,分别指向对应的结点的左孩子和右孩子(注:在树孩子兄弟链表存储结构中,每个结点的两个指针分别指向对应结点的第一个孩子和下一个兄弟)(讲人话就是:是一个链表,这个链表的结点有两个指针,一个指向这个结点的左孩子,一个指向这个结点的右孩子,data就是这个结点的值)
typedef struct Tree{
char data; // 存放数据域
struct Tree *leftsubtree; // 遍历左子树指针
struct Tree *rightsubtree; // 遍历右子树指针
}
顺序是根据根结点来定的,我根结点先输出就是先序
// 先序遍历
void PreOrder(BinaryTree T) // 采用先序遍历二叉树
{
if(T==NULL) // 递归中遇到NULL,返回上一层节点
{
return;
}
printf("%d ",T->data); // 利用递归输出
PreOrder(T->leftsubtree); // 递归遍历左子树
PreOrder(T->rightsubtree); // 递归遍历右子树
}
根结点在中间输出就是中序
// 中序遍历
void InOrder(BinaryTree T) // 先序遍历二叉树
{
if(T==NULL) // 递归中遇到NULL,返回上一层节点
{
return;
}
InOrder(T->leftsubtree); // 递归遍历左子树
printf("%d ",T->data);
InOrder(T->rightsubtree); // 递归遍历右子树
}
根结点最后输出就是后序结点
// 后序遍历
void PostOrder(BinaryTree T) // 后序遍历二叉树
{
if(T==NULL) // 递归中遇到NULL,返回上一层节点
{
return;
}
PostOrder(T->leftsubtree); // 递归遍历左子树
PostOrder(T->rightsubtree); // 递归遍历右子树
printf("%d ",T->data);
}
层次遍历就是使用队列将这个结点的值先输出,然后把这个结点左子树入队,再把右子树入队,从左往右输出,从上到下遍历输出。
void LevelOrder(BinaryTree T,int MaxSize)
{
BinaryTree p;
BinaryTree qu[MaxSize]; //定义一个循环的队列,存放二叉链结点的指针
int front,rear; //定义队列的头和尾用来出队和入队
front=rear=0; //把队列置为空队列
rear++;
qu[rear] =T; //根指针入队
while(front!=rear)//只要队列不为空就继续循环
{
front =(front+1)%MaxSize;//移动头指针
p = qu[front]; //将qu[front]保存的指针出队
printf("%C ",p->data); //输出这个出队的值
if(p->leftsubtree!=NULL)//判断这个结点有没有左孩子,有左孩子就入队
{
rear = (rear+1)%MaxSize;
qu[rear] = p->leftsubtree;
}
if(p->rightsubtree!=NULL)//判断这个结点有没有右孩子,有右孩子就入队
{
rear =(rear+1)%MaxSize;
qu[rear] = p->rightsubtree;
}
}
}
#include
#include
typedef struct Tree{
char data; // 存放数据域
struct Tree *leftsubtree; // 遍历左子树指针
struct Tree *rightsubtree; // 遍历右子树指针
}Tree,*BinaryTree;
BinaryTree CreateTree()
{
char data;
int temp;
BinaryTree T;
scanf("%c",&data); // 输入数据
temp=getchar(); // 吸收空格
if(data == '0'){ // 输入-1 代表此节点下子树不存数据,也就是不继续递归创建
return NULL;
}else{
T = (BinaryTree)malloc(sizeof(Tree)); // 分配内存空间
T->data = data; // 把当前输入的数据存入当前节点指针的数据域中
printf("请输入%c的左子树: ",data);
T->leftsubtree = CreateTree(); // 开始递归创建左子树
printf("请输入%c的右子树: ",data);
T->rightsubtree = CreateTree(); // 开始到上一级节点的右边递归创建左右子树
return T; // 返回根节点
}
}
// 先序遍历
void PreOrder(BinaryTree T) // 采用先序遍历二叉树
{
if(T==NULL) // 递归中遇到NULL,返回上一层节点
{
return;
}
printf("%C ",T->data); // 利用递归输出
PreOrder(T->leftsubtree); // 递归遍历左子树
PreOrder(T->rightsubtree); // 递归遍历右子树
}
// 中序遍历
void InOrder(BinaryTree T) // 先序遍历二叉树
{
if(T==NULL) // 递归中遇到NULL,返回上一层节点
{
return;
}
InOrder(T->leftsubtree); // 递归遍历左子树
printf("%C ",T->data);
InOrder(T->rightsubtree); // 递归遍历右子树
}
// 后序遍历
void PostOrder(BinaryTree T) // 后序遍历二叉树
{
if(T==NULL) // 递归中遇到NULL,返回上一层节点
{
return;
}
PostOrder(T->leftsubtree); // 递归遍历左子树
PostOrder(T->rightsubtree); // 递归遍历右子树
printf("%C ",T->data);
}
//层次遍历
void LevelOrder(BinaryTree T,int MaxSize)
{
BinaryTree p;
BinaryTree qu[MaxSize]; //定义一个循环的队列,存放二叉链结点的指针
int front,rear; //定义队列的头和尾用来出队和入队
front=rear=0; //把队列置为空队列
rear++;
qu[rear] =T; //根指针入队
while(front!=rear)//只要队列不为空就继续循环
{
front =(front+1)%MaxSize;//移动头指针
p = qu[front]; //将qu[front]保存的指针出队
printf("%C ",p->data); //输出这个出队的值
if(p->leftsubtree!=NULL)//判断这个结点有没有左孩子,有左孩子就入队
{
rear = (rear+1)%MaxSize;
qu[rear] = p->leftsubtree;
}
if(p->rightsubtree!=NULL)//判断这个结点有没有右孩子,有右孩子就入队
{
rear =(rear+1)%MaxSize;
qu[rear] = p->rightsubtree;
}
}
}
int main(int argc, char *argv[])
{
BinaryTree S;
printf("请输入第一个节点的数据:\n");
S = CreateTree(); // 接受创建二叉树完成的根节点
printf("先序遍历结果: \n");
PreOrder(S); // 先序遍历二叉树
printf("\n中序遍历结果: \n");
InOrder(S); // 中序遍历二叉树
printf("\n后序遍历结果: \n");
PostOrder(S); // 后序遍历二叉树
printf("\n层次遍历结果: \n"); // 层次遍历二叉树
LevelOrder(S,9);
return 0;
}
博主只是对二叉树做了一些简单的操作,四种遍历都需要我们学会,先序就是先输出根结点的值,中序就是把根结点在中间输出,后序就是根结点在最后输出,层次遍历就是使用队列将这个结点的值先输出,然后把左子树入队,再把右子树入队,从左往右输出,从上到下,两种存储结构比较的简单,顺序存储就是使用数组来保存二叉树,博主没有做很多的解释,博主使用遍历时用的是链式存储二叉树,上面代码。好了感谢你看到这里,创作不易,希望大家给博主点赞关注评论收藏。
上一篇:数据结构专升本学习,二叉树篇(画图教你二叉树的5个性质,四个遍历)
下一篇:数据结构专升本学习,画图教你秒懂线索二叉树(线索二叉树的建立和简单操作)逻辑代码分析