二叉树的顺序结构只适用于完全二叉树(与满二叉树的结点编码一一对应的二叉树),否则最坏的情况一个深度为k且只有k个结点的单支树却需要2的k次方-1个单位的存储空间。
即二叉树一般用链式结构,链式结构又有二叉链表和三叉链表。不同之处在于三叉链表多了一个指针域保存指向其双亲的指针,当所有空链域都用来保存其他信息如前继或后继,就成了线索链表。
二叉链表需要一个值域,分别指向左、右子数的指针,定义如下:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
typedef struct BiTNode{
char data;
BiTNode *lchild,*rchild;
}BiTNode,*BiTree; //二叉链表
遍历二叉树有3种方法,先、中、后序遍历,区别在于访问根结点的顺序,通过递归方法可以很容易实现遍历算法,也可以借助栈实现非递归的遍历算法等。
定义二叉树初始化函数,先序遍历递归函数等。void CreateBiTree(BiTree &T){ //按先序从根结点依个输入值
char ch;
scanf("%c",&ch);
if(ch == ' '){
T = NULL;
}else{
T = (BiTree)malloc(sizeof(BiTNode)); //创建结点
T->data = ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
bool PreOrderTraverse(BiTree T,bool(* Visit)(char c)){ //先序遍历递归算法 ,函数作为参数,char为传入函数的参数类型
if(T != NULL){
if(Visit(T->data)) //调换顺序则实现中序、后序遍历递归算法
if(PreOrderTraverse(T->lchild,Visit))
if(PreOrderTraverse(T->rchild,Visit)) return true;
return false;
}
return true;
}
bool InOrderTraverse(BiTree T,bool(* Visit)(char c)){ //中遍历递归算法
if(T != NULL){
if(InOrderTraverse(T->lchild,Visit))
if(Visit(T->data))
if(InOrderTraverse(T->rchild,Visit)) return true;
return false;
}
return true;
}
bool PrintElement(char c){
printf("%c",c);
return true;
}
主函数如下:
main(){
BiTree T;
CreateBiTree(T);
printf("先序遍历:");
PreOrderTraverse(T,PrintElement);
printf("\n中序遍历:");
InOrderTraverse(T,PrintElement);
printf("\n");
}
运行结果:
二叉树有个重要的应用——赫夫曼树(最优二叉树),是指各叶子结点的平均带权路径最短的二叉树,在权值不同如概率空间分布不同时,可以有效减少操作的次数。。。下次再说。