话说吧,人有时候就是很笨,当然这里说我自己呢,呵呵,最近学数据结构学到了普通的二叉树,线索二叉树,还有赫夫曼二叉树,几乎是每一部分的知识看了三遍才基本能够清晰的知道其实现原来是什么,怎么来的,怎么去用!哎可能真的是笨,所以特作此笔记记录下来首先是普通二叉树关于普通二叉树的基本知识可见一位博主的文章理论知识讲的很详细,查看一下代码是<零基础学算法>这书上的大部分都相同,但是有少部分不同,主要是自己理解了之后慢慢敲上去的,特此做个笔记!
头文件中的结构体申明:
#define QUEUE_MAXSIZE 50
typedef int TreeDepth ;
typedef struct ChainTree
{
char dat;
struct ChainTree *Left;
struct ChainTree *Right;
}ChainBinTree;
ChainBinTree* InitBinTree(); //初始化产生一个二叉树的根节点并返回一个根节点指针
int AddBinNode(ChainBinTree *T); //添加到当前根节点的左子树还是右子树0,左,1 右
TreeDepth GetBinTreeDepth(ChainBinTree* T); //获取树的深度
int FindData(ChainBinTree *T,char dat); //查找树种是否存在dat数据
int BinTreeSearch(ChainBinTree *T,int SearchType); //Search指明遍历树的方式
void ReleaseTree(ChainBinTree *T); //释放二叉树所占的资源
函数的实现代码:
//实现函数
//1.初始化二叉树
ChainBinTree* InitBinTree()
{
ChainBinTree *p; //测试不用指针可否ChaiBinTree
if(!(p=(ChainBinTree*)malloc(sizeof(ChainBinTree))))
{
printf("创建节点失败!\n");
exit(-1);
}
printf("输入根节点数据!\n");
scanf("%c",&p->dat);
p->Left=NULL;
p->Right=NULL;
return p;
}
//2.添加树节点
int AddBinNode(ChainBinTree* T)
{
int LorR;
ChainBinTree *Node;
if(T)
{
if(! (Node=(ChainBinTree*)malloc(sizeof(ChainBinTree))) )
{
printf("创建子节点失败!\n");
exit(-1);
}
fflush(stdin);
printf("请输入节点数据!\n");
scanf("%c",&Node->dat);
Node->Left=NULL;
Node->Right=NULL;
printf("要添加到左子树(0)--还是右子树(1)!\n");
scanf("%d",&LorR);
switch(LorR)
{
case 0:
if(T->Left)
{
printf("左子树非空!\n");
return 0;
}
else
T->Left=Node;
break;
case 1:
if(T->Right)
{
printf("右子树非空!\n");
return 0;
}
else
T->Right=Node;
break;
}
}
else
{
printf("当前根节点为空,添加失败!\n");
return 0;
}
return 1;
}
//3.获取到树的深度
TreeDepth GetBinTreeDepth(ChainBinTree* T)
{
int depth1,depth2;
if(T)
{
depth1=GetBinTreeDepth(T->Left);
depth2=GetBinTreeDepth(T->Right);
//depth=depth1>depth2 ? depth1 : depth2;
if(depth1>depth2)
return depth1+1;
else
return depth2+1;
}
return 0;
}
//4.查找二叉树中的数据
int FindData(ChainBinTree *RootTree,char dat)
{
if(RootTree)
{
if(RootTree->dat==dat)
return 1;
else if(FindData(RootTree->Left,dat))
return 1;
else if(FindData(RootTree->Right,dat))
return 1;
else
return 0;
}
else
return 0;
}
//5.遍历二叉树
int BinTreeSearch(ChainBinTree *T,int SearchType)
{
int head=0,tail=0; //按层遍历中的数据
ChainBinTree *p=NULL;
ChainBinTree *q[QUEUE_MAXSIZE];
switch(SearchType)
{
//先序遍历 中--左--右
case 0:
if(T)
{
printf("%c ",T->dat);
BinTreeSearch(T->Left,SearchType);
BinTreeSearch(T->Right,SearchType);
}
else
return 0;
break;
//中序遍历 左--中--右
case 1:
if(T)
{
BinTreeSearch(T->Left,SearchType);
printf("%c ",T->dat);
BinTreeSearch(T->Right,SearchType);
}
else
return 0;
break;
//后续遍历 左--右--中
case 2:
if(T)
{
BinTreeSearch(T->Left,SearchType);
BinTreeSearch(T->Right,SearchType);
printf("%c ",T->dat);
}
else
return 0;
break;
//按层遍历
case 3:
if(T)
{
tail=(tail+1)%QUEUE_MAXSIZE;
q[tail]=T;
}
while(head!=tail)
{
head=(head+1)%QUEUE_MAXSIZE;
p=q[head];
printf("%c ",p->dat);
if(NULL!=p->Left)
{
tail=(tail+1)%QUEUE_MAXSIZE;
q[tail]=p->Left;
}
if(NULL!=p->Right)
{
tail=(tail+1)%QUEUE_MAXSIZE;
q[tail]=p->Right;
}
}
break;
}
return 1;
}
//6.释放二叉树资源,即清空二叉树
void ReleaseTree(ChainBinTree *T)
{
if(T)
{
ReleaseTree(T->Left);
ReleaseTree(T->Right);
free(T);
}
else
return;
}
这几种树种我看就算这个树,最好理解了,最主要是递归的了,应该比较简单!其中我将四种遍历方式整合到一个函数BinTreeSearch()了.主函数测试:
int main(int argc,char* argv[])
{
ChainBinTree *p;
int Select,type;
char ch;
p=InitBinTree();
while(1)
{
printf("0--添加节点 1--求树的深度\n");
printf("2--查找数据 3--遍历树\n");
printf("4--结束操作\n");
printf("请输入要选择的操作\n");
fflush(stdin);
//scanf("%d",&Select);
scanf("%d",&Select);
switch(Select)
{
case 0:
if( AddBinNode(p))
printf("添加节点成功!\n");
break;
case 1:
printf("当前树的深度是:%d\n",GetBinTreeDepth(p));
break;
case 2:
fflush(stdin);
printf("请输入要查找的数据\n");
scanf("%c",&ch);
if(FindData(p,ch))
printf("查找成功,该数据在树种\n");
else
printf("查找失败!\n");
break;
case 3:
printf("请选择遍历方式\n");
printf("0--先序遍历 1--中序遍历 2--后续遍历 3--按层遍历\n");
// fflush(stdin);
scanf("%d",&type);
BinTreeSearch(p,type);
break;
case 4:
ReleaseTree(p);
return 0;
}
printf("\n");
}
return 0;
}
对了,上述还有点细节需要注意,本人菜鸟就是不知道为什么必须要用fflush(stdin)来刷新缓冲流,才能使输入生效,这个我还得去查查,另外今天做实验有个scanf的问题也值得注意,以后写个关于scanf的总结再说这个吧!
竟忘了关于这个代码以及线索二叉树的代码已经上传 没资料的同学可以看下下载代码