文章目录
5.1 二叉树
5.1.1 二叉树的定义
每个结点的度都不大于2,且孩子结点次序不能任意颠倒的树称为二叉树
5.1.2 二叉树的性质
1).在二叉树的第i层上至多有2i-1个结点
2).深度为k的二叉树至多有2k-1个结点
3).若终端结点数为n0,而度数为二的结点数为n2,则n0=n2+1
4).具有n个结点的完全二叉树的深度为
⌊
l
o
g
2
n
⌋
+
1
\left \lfloor log_2n \right \rfloor+1
⌊log2n⌋+1
5).对具有n个结点的完全二叉树,对序号为i的结点有:
\quad
若i=1,则序号为i的结点是根节点,无双亲结点;若i>1,则结点的双亲节点序号为
⌊
i
/
2
⌋
\left \lfloor i/2 \right\rfloor
⌊i/2⌋
\quad
若2i>n,则序号为i的结点无左孩子;若<=,则序号为i的结点的左孩子结点的序号为2i
\quad
若2i+1>n,则序号为i的结点无右孩子;若<=,则序号为i的结点的右孩子结点序号为2i+1
5.1.3 二叉树的存储结构
顺序存储结构:适用于完全二叉树
链式存储结构:
typedef char ElemType;
typedef struct Node
{
ElemType e;
struct Node * Lchild;
struct Node * Rchild;
}BiTNode,* Bitree;
5.1.4 二叉树的创建和遍历
\\"SeqStack.cpp"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXSIZE 50
typedef char ElemType;
typedef struct Node
{
ElemType e;
struct Node * Lchild;
struct Node * Rchild;
}BiTNode,* Bitree;
typedef struct
{
BiTNode *elem[MAXSIZE];
int top;
}SeqStack;
void InitStack(SeqStack *S)//初始化
{
S->top=-1;
}
int IsEmpty(SeqStack S)//判栈空函数
{
if(S.top==-1) return true;
else
return false;
}
int IsFull(SeqStack S)//判栈满函数
{
if(S.top==MAXSIZE-1) return true;
else
return false;
}
int Push(SeqStack *S,BiTNode *x)//在S顶部插入元素x
{
if(IsFull(*S)) return false;
S->elem[++S->top]=x;
return true;
}
int Pop(SeqStack *S,BiTNode **x)//删除栈S顶部元素
{
if(IsEmpty(*S)) return false;
(*x)=S->elem[S->top--];
return true;
}
int GeTop(SeqStack S,BiTNode **x)
{
if(IsEmpty(S)) return false;
(*x)=S.elem[S.top];
return true;
}
\\"SeqQueue.cpp"
#include"SeqStack.cpp"
typedef char ElemType;
typedef struct
{
BiTNode * elem[MAXSIZE];
int front;
int rear;
}SeqQueue;
int InitQueue(SeqQueue *Q)//初始化队列
{
Q->front=Q->rear=0;
}
int IsEmpty(SeqQueue Q)//判断队列空
{
if(Q.front==Q.rear) return true;
else
return false;
}
int EnterQueue(SeqQueue *Q,BiTNode *x)//队尾插入x
{
if((Q->rear+1)%MAXSIZE==Q->front) return false;
Q->elem[Q->rear]=x;
Q->rear=(Q->rear+1)%MAXSIZE;
return true;
}
int DeleteQueue(SeqQueue *Q,BiTNode **x)//队头元素出队
{
if(IsEmpty(*Q)) return false;
(*x)=Q->elem[Q->front];
Q->front=(Q->front+1)%MAXSIZE;
return true;
}
int GetHead(SeqQueue Q,BiTNode **x)//取队头元素
{
if(IsEmpty(Q)) return false;
(*x)=Q.elem[Q.front];
return true;
}
#include"SeqQueue.cpp"
void Initiate(Bitree *bt)//初始化二叉树
{
* bt=(Bitree)malloc(sizeof(BiTNode));
(* bt)->Lchild=(* bt)->Rchild=NULL;
}
void InCreate(Bitree *bt)//先序遍历创建二叉树
{
char ch;
ch=getchar();
if(ch=='.')
* bt=NULL;
else
{
* bt=(Bitree)malloc(sizeof(BiTNode));
(* bt)->e=ch;
InCreate(&((*bt)->Lchild));
InCreate(&((*bt)->Rchild));
}
}
int IsEmpty(Bitree bt)//判断二叉树为空
{
if(bt->Lchild==NULL && bt->Rchild==NULL)
return true;
else return false;
}
void Visit(ElemType e)//访问二叉树的节点
{
printf("%c",e);
}
void PreOrder(Bitree root)//递归先序遍历二叉树
{
if(root!=NULL)
{
Visit(root->e);
PreOrder(root->Lchild);
PreOrder(root->Rchild);
}
}
void InOrder(Bitree root)//递归中序遍历二叉树
{
if(root!=NULL)
{
InOrder(root->Lchild);
Visit(root->e);
InOrder(root->Rchild);
}
}
void PostOrder(Bitree root)//递归后序遍历二叉树
{
if(root!=NULL)
{
PostOrder(root->Lchild);
PostOrder(root->Rchild);
Visit(root->e);
}
}
void StackPreOrder(Bitree root)//基于栈的先序遍历
{
SeqStack S;
InitStack(&S);
BiTNode * p = root;
while(p!=NULL||!IsEmpty(S))
{
if(p)
{
Push(&S,p);
Visit(p->e);
p = p->Lchild;
}
else
{
Pop(&S,&p);
p = p->Rchild;
}
}
}
void StackInOrder(Bitree root)//基于栈的中序遍历
{
SeqStack S;
InitStack(&S);
BiTNode * p = root;
while(p!=NULL || !IsEmpty(S))
{
if(p)
{
Push(&S,p);
p=p->Lchild;
}
else
{
Pop(&S,&p);
Visit(p->e);
p=p->Rchild;
}
}
}
void StackPostOrder(Bitree root)//基于栈的后序遍历
{
BiTNode *p,*q;
p=root,q=NULL;
SeqStack S;
InitStack(&S);
while(p!=NULL || !IsEmpty(S))
{
if(p!=NULL)
{
Push(&S,p);
p=p->Lchild;
}
else
{
GeTop(S,&p);
if((p->Rchild==NULL) || (p->Rchild==q))
{
Visit(p->e);
q=p;
Pop(&S,&p);
p=NULL;
}
else
{
p=p->Rchild;
}
}
}
}
void LevelTraversal(Bitree root)//层序遍历
{
SeqQueue Q;
BiTNode *p;
InitQueue(&Q); //队列的初始化
EnterQueue(&Q,p); //入队
while(!IsEmpty(Q))//队列空,遍历结束
{
DeleteQueue(&Q,&p);//出队打印
printf("%c",p->e);
if(p->Lchild!= NULL)
{
EnterQueue(&Q,p->Lchild);
}
if(p->Rchild != NULL)
{
EnterQueue(&Q,p->Rchild);
}
}
}
int main()
{
Bitree bt,root;
Initiate(&bt);
printf("请输入你想要创建的二叉树(按先序):");
InCreate(&bt);
root=bt;
printf("先序遍历二叉树:");
PreOrder(root);
printf("\n中序遍历二叉树:");
InOrder(root);
printf("\n后序遍历二叉树:");
PostOrder(root);
printf("\n基于栈的先序遍历:");
StackPreOrder(root);
printf("\n基于栈的中序遍历:");
StackInOrder(root);
printf("\n基于栈的后序遍历:");
StackPostOrder(root);
printf("\n层序遍历");
LevelTraversal(root);
return 0;
}
5.1.5 线索二叉树
5.2 树与森林的遍历
5.2.1 树的遍历
先根遍历:对应转换后二叉树的前序遍历。
\quad\quad\quad\quad
1.访问根结点
\quad\quad\quad\quad
2.从左到右,依次先根遍历根结点的每一棵子树
后根遍历:对应转换后二叉树的中序遍历。
\quad\quad\quad\quad
1.从左到右,依次后根遍历根结点的每一棵子树
\quad\quad\quad\quad
2.访问根结点
5.2.2 森林的遍历
先序遍历
\quad\quad\quad\quad
1.访问森林中第一棵树的根节点
\quad\quad\quad\quad
2.先序遍历第一棵树的根节点的子树森林
\quad\quad\quad\quad
3.先序遍历除去第一棵树后剩余的树构成的森林
中序遍历
\quad\quad\quad\quad
1.中序遍历森林中第一棵树的根节点的子树森林
\quad\quad\quad\quad
2.访问第一棵树的根结点
\quad\quad\quad\quad
3.中序遍历除去第一棵树之后剩余的树构成的森林
后序遍历
\quad\quad\quad\quad
1.后序遍历森林中第一棵树的根节点的子树森林
\quad\quad\quad\quad
2.后序遍历除去第一棵树之后剩余的树构成的森林
\quad\quad\quad\quad
3.访问第一棵树的根结点
5.3 哈夫曼树
//哈夫曼树的创建及哈夫曼编码的生成
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 20//叶子结点的最大数量
#define M 2*N-1// 全部结点的最大数量
typedef char * HuffmanCode[N+1];
typedef struct
{
int weight;
int Parent;
int Lchild;
int Rchild;
}HTNode,HuffmanTree[M+1];
//在ht[1]-ht[i]范围内选两个parent为0,且权值最小的结点,并把序号赋值给s1,s2
void select(HuffmanTree ht,int i,int &s1,int &s2)
{
int w1=100,w2=100;
int j,k;
for(j=1;j<=i;j++)
if((ht[j].Parent==0) && (ht[j].weight<w1))
{
s1=j;
w1=ht[j].weight;
}
for(k=1;k<=i;k++)
if((ht[k].Parent==0) && (ht[k].weight<w2) && (k!=s1))
{
s2=k;
w2=ht[k].weight;
}
}
void CrtHuffmantree(HuffmanTree ht,int w[],int n)//建立哈弗曼树
{
int i,m;
int s1,s2;
m=2 * n-1;
for(i=1;i<=n;i++) ht[i]={w[i],0,0,0};
for(i=n+1;i<=m;i++) ht[i]={0,0,0,0};
for(i=n+1;i<=m;i++)//创建非叶结点
{
select(ht,i-1,s1,s2);
ht[i].weight=ht[s1].weight+ht[s2].weight;
ht[s1].Parent=i,ht[s2].Parent=i;
ht[i].Lchild=s1,ht[i].Rchild=s2;
}
}
void Visit(HuffmanTree ht,int m)//访问哈弗曼树
{
int i;
printf("weight parent Lchild Rchild\n");
for(i=1;i<=m;i++)
{
printf("%3d%9d%9d%10d\n",ht[i].weight,ht[i].Parent,ht[i].Lchild,ht[i].Rchild);
}
}
void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int n)
{
int i,j,start,c,p;
char * cd;
cd=(char * )malloc(n*sizeof(char));
cd[n-1]='\0';
for(i=1;i<=n;i++)
{
start=n-1;
c=i;
p=ht[i].Parent;
while(p!=0)
{
start--;
if(ht[p].Lchild==c)
{
cd[start]='0';
}
else
{
cd[start]='1';
}
c=p,p=ht[p].Parent;
}
hc[i]=(char *)malloc((n-start)*sizeof(char));
strcpy(hc[i],&cd[start]);
printf("%d的编码为:",ht[i].weight);
while(start!=n-1)
{
printf("%c",cd[start]);
start++;
}
printf("\n");//打印ht[i]问题
}
free(cd);
}
int main()
{
int n,m,i;
HuffmanTree ht;
HuffmanCode hc;
printf("请输入你想要创建哈弗曼树叶子结点的数量:");
scanf("%d",&n);
m=2*n-1;//定义完n再m
int w[n+1];
printf("请输入你想要创建哈弗曼树的权值:");
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
CrtHuffmantree(ht,w,n);
printf("\nHuffmantree:\n");
Visit(ht,m);
CrtHuffmanCode(ht,hc,n);
return 0;
}