一、二叉树的存储结构
————顺序存储(一维数组)———
1 #define MaxSize 100 //假设二叉树最大编号为99 2 typedef char DataType; //定义二叉树节点的数据类型,假设为char型 3 typedef struct{ 4 DataType data[MaxSize]; 5 int biTreeNum; //二叉树的节点个数 6 }SeqBiTree;
——————二叉链表————————
1 typedef char DataType; 2 typedef struct BiNode{ 3 DataType data; 4 struct BiNode * lchild,* rchild; 5 }BiNode;
二、二叉树的遍历
遍历过程
转载自数据结构——遍历二叉树
————深度优先遍历————
1.前序遍历
2.中序遍历
3.后序遍历
————广度优先遍历————
4.层序遍历
总结:a.我们提到的四种遍历方式,其实都是在把树种的结点编程某种意义上的线性序列,这样给程序执行带来了好处。
b.前序、中序、后序遍历最根本的区别就是双亲结点的访问时机——前序是先访问双亲结点,然后左孩子,最后右孩子;中序是左孩子,双亲,右孩子;后序是左孩子、右孩子最后双亲结点。
c.树的定义就使用了递归这一方式,当然,对树的遍历也是使用递归(注意递归算法一定要有结束递归的标志)
代码实现 —— 基于二叉链表的存储结构
1.前序遍历
1 void PreOrder(BiNOde * root){ 2 if(root==NULL) //递归调用的结束条件 3 return; 4 else{ 5 printf("%c",root->data);//访问根节点的数据域,为char型 6 PreOrder(root->lchild); //前序递归遍历root的左子树 7 PreOrder(root->rchild);//前序递归遍历root的右子树 8 } 9 }
2.中序遍历
1 void InOrder(BiNode * root){ 2 if(root==NULL){ //递归调用的结束条件 3 return; 4 } 5 else{ 6 InOrder(root->lchild);//中序递归遍历root的左子树 7 printf("%c",root->data);//访问根节点的数据域,为char型 8 InOrder(root->rchild);//中序递归遍历root的右子树 9 } 10 }
3.后序遍历
1 void PostOrder(BiNode * root){ 2 if(root==NULL){ 3 return; //递归调用的结束条件 4 } 5 else{ 6 PostOrder(root->lchild); //后序递归遍历root的左子树 7 PostOrder(root->rchild); //后序递归遍历root的右子树 8 printf("%c",root->data); //访问根节点的数据域,为char型 9 } 10 }
4.层序遍历
访问某一层的节点后,再对各个节点的左孩子和右孩子顺序访问,这样一层一层进行,先访问的节点其左右孩子也要先访问,这符合队列的操作特性。因此,在层序遍历时,设置一个队列存放已访问的节点
1 void LevelOrder(BiNode * root){ 2 BiNode * q=NULL,*Q[MaxSize] //采用顺序队列 3 int front = rear =-1; //初始化顺序队列 4 if(root==NULL) //二叉树为空,算法结束 5 return; 6 Q[++rear]=root; //根指针入队 7 while(front!=rear){ //当队列非空时 8 q=Q[++front]; //出队 9 printf("%c",q->data); //访问节点,为char型 10 if(q->lchild!=NULL) 11 Q[++rear]=q->lchild; 12 if(q->rchild!=NULL) 13 Q[++rear]=q->rchild; 14 } 15 }