树和二叉树
以下代码全部本人手动敲滴,若有帮助请点个赞吧
一.树的表示方法
1.倒置树结构(最为常用)
2.文氏图表示法
3.广义表形式(嵌套括号形式)
4.凹入表示法
二.二叉树
1.二叉树的性质
1_1 在二叉树的第i层至多有2^i-1个结点(数学归纳法可证明)
1_2 深度为k的二叉树至多有2^k-1个结点。
1_3 对任意二叉树T,若终端结点数为n0,而其度数为2的结点数为n2,则n0=n2+1.
1_4 对于完全二插树,其有n个节点,那么其深度为log2 n+1;
1_5 对二叉树从上到下,从左到右依次用1-n进行标号
若i=1,则序号为i的结点为根结点;若i>1,则序号为i的结点的双亲结点序号为[i/2];
若2i>n,那么序号为i的结点没有左孩子,若2i<=n,那么序号为i的结点的左孩子序号为2i;
若2i+1>n,则序号为i的结点无右孩子,若2i+1>n,那么序号为i的结点的右孩子的序号为2i+1.
2.二叉树的存储结构
2_1顺序存储结构
2_2链式存储结构
typedef struct Node
{
DataType data;
struct Node*LChild;
struct Node*RChild;
}BitNode,*BitTree;
PS:若一个二叉树右n个结点,则其二叉链表中必含有2n个指针域,其中必含有n+1个空指针域,n-1个实指针域
3.二叉树的遍历
3_1先序遍历
递归算法:
void PreOrder
{
if(root!=NULL)
{
print(root->data);
PreOrder(root->LChild);
PreOrder(root->RChild);
}
}
输出二叉树中的叶子结点
void PreOrder
{
if(root!=NULL)
{
if(root->LChild==NULL&&root->RChild==NULL)
print(root->data);
PreOrder(root->LChild);
PreOrder(root->RChild);
}
}
void leaf(BiTree root)
{
int leafcount=0;
if(root!=NULL)
leaf(root->LChild);
leaf(root->RChild);
if(root->Lchild==NULL&&root->Rchild==NULL)leafcount++;
}
非递归算法1
//前序遍历
void PreOrder1(BitNode *b)
{
BitNode*p;
SqStack* s;
InitStack(s);
if(b!=NULL){
Push(s,b);//根节点入栈
while(!StackEmpty(s))//栈不为空就继续
{
Pop(s,p);//把s中的顶部弹出来并赋予p
print("%c",p->data);
if(p->rchild!=NULL)Push(s,p->rchild);
if(p->lchild!=NULL)Push(s,p->lchild);
}
printf("\n");
}
DestroyStack(s);
}
非递归算法2
void PreOrder2(BitNode *b)
{
BitNode*p;SqStack *st;
p=b;
while(StackEmpty(st)|| p!=NULL)
{
while(p!=NULL)
{
printf("%c",p->data);
Push(st,p);
p=p->Lchild;
}
if(!StackEmpty(st))
{
Pop(st,p);
p=p->Rchild;
}
}
printf("\n");
Destory(st);
}
用扩展的先序遍历序列创建二叉链表
void CreateBit(BiTree *bt)
{
char ch;
ch=getchar();
if(ch=='.')*b=NULL;
else
{
*bt=(BiTree)malloc(sizeof(BiTree));
(*bt)->data=ch;
CreateBit(&((*bt)->Lchild));
CreateBit(&(((*bt)->Rchild));
}
}
3_2中序遍历
//递归算法
void MiddleOrder(BitNode* b)
{
if(b!=NULL)
{
MiddleOrder(b->Lchild);
printf("%c",b->data);
MiddleOrder(b->Rchild);
}
}
//非递归算法(直接调用栈)
void MiddleOrder2(BitNode* b)
{
int top=0; BitNode*p=b;
do
{
while(p!=NULL)
{
if(top>m)return;
top=top+1;
s[top]=p;
p=p->Lchild;
}//遍历左子树
if(top!=0)
{
p=s[top];
top=top-1;
Visit(p->data);
p=p->Rchild;
}//遍历右子树
}while(p!=NULL||top!=0)
}
void MiddleOrder3(BitNode* b)
{
InitStack(&S);
p=root;
while(p!=NULL||!IsEmpty(S))
{
if(p!=NULL)
{
Push(&S,p);
p=p->Lchild;
}
else
{
pop(&s,&p);Visit(p->data);
p=p->Rchild;
}
}
}
3_3后序遍历
//递归算法
void EndOrder(BitNode* b)
{
if(b!=NULL){
EndOrder(b->Lchild);
EndOrder(b->Rchild);
printf("%c",b->data);
}
}
//后序遍历非递归操作
void EndOrder2(BitNode *root)
{
BitNode*p,*q;
Stack S;
q=NULL;p=root;
InitStck(S);
while(p!=NULL||IsEmpty(S))
{
if(p!=NULL)
z {
Push(&S,p);
p=p->Lchild;
}
else
{
GetTop(&S,&p);
if(p->Rchild==NULL||p->Rchild==q)//无右孩子或右孩子已经被遍历过
{
visit(p->data);
q=p;
Pop(&S,&p);p=NULL;//p置空方可继续退层
}
else
p=p->Rchild;
}
}
}
3_4其他
//求二叉树的高度
int PostTreeDepth(BiTree bt)
{
int hl,hr,mX;
if(bt!=NULL)
{
hl=PostTreeDepth(bt->Lchild);
hr=PostTreeDepth(bt->Rchild);
max=hl>hr?hl:hr;
return max+1;
}
return 0;//空树返回零
}
void PrintTree(BiTree bt,int nLayer)//按横向树形显示二叉树
{
if(bt==NULL)return;
PrintTree(bt->Rchild,nLayer++);
for(int i=0;i<nLayer;i++)
printf(" ");
printf("%c",bt->data);
PrintTree(bt->Rchild,nLayer+1);
}
//先序遍历求二叉树高度的递归算法
int depth=0;
void PreTreeDepth(Bitree bt,int h)//h初始值为1
{
if(bt!=NULL)
{
if(h>depth)depth=h;
PreTreeDepth(bt->Lchild,h+1);//遍历左子树
PreTreeDepth(bt->Rchild,h+1);//遍历右子树
}
}
4.线索二叉树
新增了Ltag和Rtag两个标志位,0表示指向孩子,1表示指向的是前驱
//中序建立线索二叉树
BinTree pre = NULL;
void Inthread(BinTree bt)
{
if(bt != NULL){
Inthread(bt->LChild);
if(!bt->LChild){
bt->Ltag = 1;
bt->LChild = pre;
}
if(pre&& !pre->RChild){
pre->RChild = bt;
pre->Rtag = 1;
}
pre = bt;
Inthread(bt->RChild);
}
}