一:创建
既然有先序法遍历,那应该也有先序法创建.二叉链的数据模型是:
typedef struct BinaryTree
{ char data;
struct BinaryTree* lchild;
struct BinaryTree* rchild;
}BT;
下面就用二叉链的数据类型,创建一个二叉树
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#include <string.h>
typedef struct BinaryTree
{
char data;
struct BinaryTree* lchild;
struct BinaryTree* rchild;
}BT;
void Creat_Tree(BT** T)
{
if((*T))
{
char input = 0;
printf("请输入你想要存储的字符:>");
scanf("%c",&input);
getchar();
if(input != 'Q')
{
*T = (BT*)malloc(sizeof(BT));//判断你的输出,如果不是Q,就创建一个结点来存储你的输出
(*T)->data = input;//结点赋值
Creat_Tree(&((*T)->lchild));//创建结点的左孩指针,并根据你的输出,判断是否创建左孩子结点
Creat_Tree(&((*T)->rchild));//创建结点的右孩指针,并根据你的输出,判断是否创建右孩子结点
}
else
{
(*T) = NULL;//如果你输出Q,那么给当前结点赋空值,不再向下添加元素
}
}
}
int main()
{
BT* T;
Creat_Tree(&T);
printf("%c\n",T->data);
printf("%c\n",T->lchild->lchild->data);
printf("%c\n",T->rchild->data);
return 0;
}
这样,一个二叉树就创建完成,运行起来,输入值.
此刻,二叉树实例已经生成,下面我们就针对这个二叉树进行遍历 ,二叉树的遍历主流:先序遍历,中序遍历,后序遍历
二:二叉树的遍历
1:递归遍历,先序,中序,后序
先序:通过指针,找到结点后.先对该结点的值进行操作(赋值,取值,打印等等),然后,再对左孩子指针指向的结点进行操作,一直到左孩子指针为空后,再对右孩子进行操作,通俗点讲,就是先操作结点的值域,再操作结点的左孩子,最后操作结点的右孩子的一个顺序D->L->R
同理中序为:L->D->R,后序为:L->R->D
下面就这三种递归方式的代码实现:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#include <string.h>
typedef struct BinaryTree
{
char data;
struct BinaryTree* lchild;
struct BinaryTree* rchild;
}BT;
void Creat_Tree(BT** T)
{
if((*T))
{
char input = 0;
printf("请输入你想要存储的字符:>");
scanf("%c",&input);
getchar();
if(input != 'Q')
{
*T = (BT*)malloc(sizeof(BT));//判断你的输出,如果不是Q,就创建一个结点来存储你的输出
(*T)->data = input;//结点赋值
Creat_Tree(&((*T)->lchild));//创建结点的左孩指针,并根据你的输出,判断是否创建左孩子结点
Creat_Tree(&((*T)->rchild));//创建结点的右孩指针,并根据你的输出,判断是否创建右孩子结点
}
else
{
(*T) = NULL;//如果你输出Q,那么给当前结点赋空值,不再向下添加元素
}
}
}
void PreOrder(BT* T)//先序遍历
{
if(T)
{
printf("%c ",T->data);//取数据
if(T->lchild)PreOrder(T->lchild);//递归处理左孩子
if(T->rchild)PreOrder(T->rchild);//递归处理右孩子
}
}
void MidOrder(BT* T)//中序遍历
{
if(T)
{
if(T->lchild)PreOrder(T->lchild);
printf("%c ",T->data);
if(T->rchild)PreOrder(T->rchild);
}
}
void PostOrder(BT* T)//后序遍历
{
if(T)
{
if(T->lchild)PreOrder(T->lchild);
if(T->rchild)PreOrder(T->rchild);
printf("%c ",T->data);
}
}
int main()
{
BT* T;
Creat_Tree(&T);
printf("先序遍历的结果是:\n");
PreOrder(T);//先序遍历
printf("\n");
printf("中序遍历的结果是:\n");
MidOrder(T);//中序遍历
printf("\n");
printf("后序遍历的结果是:\n");
PostOrder(T);//后序遍历
return 0;
}
然后,我们运行起来,先创建,再遍历,得到的结果是:
结果没有问题,但我们从代码里看到,三个排序方法,其实很相似.只是取数据的时机不相同而已,确实,不管哪种排序,代码遍历每个结点的路线是不变的,变化的只是在哪个时间去取结点的数据,所以三种排序的时间度和空间度是相同的.
前面的方法都是用递归的思想,就是用栈来保存每个节点的参数的变量.每个结点都要新开辟一个栈,如果二叉树的深度太大,那么这些个方法的执行效率就大打折扣了.只是要保存路过的结点的数据,我也可以自己开一个栈用来保存数据,利用栈的先进后出的特点,再从里面取出来就好了,这样效率也高了不少,所以到底用哪种方法,要看具体的情况而定.下面就介绍一下普通的循环方式来遍历二叉树(用中序的思想)
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#include <string.h>
typedef struct BinaryTree//二叉树,结点类型
{
char data;
struct BinaryTree* lchild;
struct BinaryTree* rchild;
}BT;
typedef struct Stack//栈结构体
{
int* top;//栈顶指针
int* basic;//栈底指针
int sz;//栈的大小
}S;
void Creat_Tree(BT** T)
{
if((*T))
{
char input = 0;
printf("请输入你想要存储的字符:>");
scanf("%c",&input);
getchar();
if(input != 'Q')
{
*T = (BT*)malloc(sizeof(BT));//判断你的输出,如果不是Q,就创建一个结点来存储你的输出
(*T)->data = input;//结点赋值
Creat_Tree(&((*T)->lchild));//创建结点的左孩指针,并根据你的输出,判断是否创建左孩子结点
Creat_Tree(&((*T)->rchild));//创建结点的右孩指针,并根据你的输出,判断是否创建右孩子结点
}
else
{
(*T) = NULL;//如果你输出Q,那么给当前结点赋空值,不再向下添加元素
}
}
}
void Creat_Stack(S* SP)//创建并初始化一个栈
{
SP->basic = malloc(sizeof(int)*MAXSIZE);
if(!SP->basic)//判断申请内存有没有成功
{
printf("创建失败");
return;
}
else
{
SP->top = SP->basic;//栈顶指针=栈底指针,栈为空
SP->sz = MAXSIZE;
}
}
void Push_Stack(S* SP, BT* a)
{
if(SP->top - SP->basic < SP->sz)
{
*(SP->top) = a;
SP->top++;
}
else
{
printf("栈已经满了");
}
}
int Pop_Stack(S* SP)
{
if(SP->top - SP->basic > 0)
{
SP->top--;
return *(SP->top);
}
else
{
printf("栈已经空了");
}
}
void Traversal(BT* T, S* SP)
{
while(T||SP->top - SP->basic > 0)//传入的结点不为空,栈不为空
{
if(T)
{
Push_Stack(SP,T);//结点地址入栈
T = T->lchild;//指针指向他的左孩子
}
else
{
T = Pop_Stack(SP);//如果左孩子为空,就取得该结点的数据
printf("%c ", T->data);
T = T->rchild;//然后指向右孩子
}
}
}
int main()
{
BT* T;
S SP;
Creat_Tree(&T);
Creat_Stack(&SP);//创建一个顺序栈,用来存储结点的地址
printf("循环遍历的结果是:\n");
Traversal(T,&SP);
return 0;
}
.