实验目的
- 掌握二叉树链式存储结构定义及其基本操作;
- 学会用递归方法编写对二叉树这种递归数据结构进行处理的算法;
- 熟悉二叉树的典型应用,掌握哈夫曼树的构造思想、构造算法以及进行哈夫曼编码。
实验内容
- 建立一个二叉树,并能分别利用先序、中序、后序、层次四种不同的遍历方法输出结点元素。
- 给定权值{7,19,2,6,32,3,21,10},构造哈夫曼树并进行编码。
Source Code
#include<stdio.h>
#include<malloc.h>
#define MaxSize 100
typedef struct node
{
char data;
struct node *lchild;
struct node *rchild;
}BTNode;
//创建二叉树
void CreateBTree(BTNode *&b,char *str)
{
BTNode *St[MaxSize],*p; //St数组作为顺序栈
int top = -1,k,j=0; //top为栈顶指针
char ch;
b=NULL;
ch=str[j]; //初始时二叉链为空
while(ch!='\0') //循环扫描str中的每个字符
{
switch(ch)
{
case '(':top++;St[top]=p;k=1;break; //开始处理左孩子结点
case ')':top--;break; //栈顶结点的子树处理完毕
case ',':k=2;break; //开始处理右孩子结点
default:p=(BTNode *)malloc(sizeof(BTNode)); //创建一个结点,由p指向
p->data = ch; //存放结点值
p->lchild = p->rchild = NULL; //左右指针都设置为空
if(b==NULL) //若尚未创建根结点
b=p; //p所指结点为根结点
else
{
switch(k)
{
case 1:St[top]->lchild = p; break; //新建结点作为栈结点的左孩子
case 2:St[top]->rchild = p; break; //新建结点作为栈结点的右孩子
}
}
}
j++; //继续扫描str
ch = str[j];
}
}
//先序遍历
void PreOrder(BTNode *b)
{
if(b!=NULL)
{
printf("%c",b->data);
PreOrder(b->lchild);
PreOrder(b->rchild);
}
}
//中序输出
void InOrder(BTNode *b)
{
if(b!=NULL)
{
InOrder(b->lchild);
printf("%c",b->data);
InOrder(b->rchild);
}
}
//后序输出
void PostOrder(BTNode *b)
{
if(b!=NULL)
{
PostOrder(b->lchild);
PostOrder(b->rchild);
printf("%c",b->data);
}
}
//层次输出
void LevelOrder(BTNode *b)
{
BTNode *qu[MaxSize],*p;
int rear=-1,front=-1;
qu[++rear]=b;
while(rear!=front)
{
front=(front+1)%MaxSize;
p=qu[front];
printf("%c",p->data);
if(p->lchild!=NULL)
{
rear=(rear+1)%MaxSize;
qu[rear]=p->lchild;
}
if(p->rchild!=NULL)
{
rear=(rear+1)%MaxSize;
qu[rear]=p->rchild;
}
}
}
int main(void)
{
BTNode *b;
char str[MaxSize];
printf("输入二叉树字符串:");
gets(str);
CreateBTree(b,str);
printf("先序输出:");
PreOrder(b);
printf("\n");
printf("中序输出:");
InOrder(b);
printf("\n");
printf("后序输出:");
PostOrder(b);
printf("\n");
printf("层次输出:");
LevelOrder(b);
printf("\n");
return 0;
}
Computational Results
#include<stdio.h>
#include<stdlib.h>
#define max 10000
#define maxleaf 30
#define maxnode 59
#define maxbit 10
typedef struct
{
char data; //结点值
double weight; //权值
int flag;
int parent, lchild, rchild;
}HTNode;
typedef struct
{
int bit[maxbit];
int start;
}HCode;
//构造哈夫曼树,生成哈夫曼编码
void CreateHT(HTNode ht[], HCode hcd[], int n)
{
int i, j;
int m1, m2, x1, x2, c, p;
HCode cd;
for (i = 0; i < n - 1; i++)
{
m1 = m2 = max;
x1 = x2 = 0;
for (j = 0; j < n + i; j++)
{
if (ht[j].weight < m1 && ht[j].flag == 0)
{
m2 = m1;
x2 = x1;
m1 = ht[j].weight;
x1 = j;
}
else
{
if (ht[j].weight < m2 && ht[j].flag == 0)
{
m2 = ht[j].weight;
x2 = j;
}
}
}
ht[x1].parent = n + i;
ht[x2].parent = n + i;
ht[x1].flag = 1;
ht[x2].flag = 1;
ht[n + i].weight = ht[x1].weight + ht[x2].weight;
ht[n + i].lchild = x1;
ht[n + i].rchild = x2;
}
for (i = 0; i < n; i++) //生成哈夫曼编码
{
cd.start = n - 1;
c = i;
p = ht[c].parent;
while (p!=0)
{
if (ht[p].lchild == c)
cd.bit[cd.start] = 0;
else
cd.bit[cd.start] = 1;
cd.start--;
c = p;
p = ht[c].parent;
}
for (j = cd.start + 1; j < n; j++)
{
hcd[i].bit[j] = cd.bit[j];
hcd[i].start = cd.start;
}
}
}
//哈夫曼树结点初始化
void InitHT(HTNode ht[], HCode hcd[], int n)
{
if (n <= 1)
return;
int i;
for (i = 0; i < 2 * n - 1; i++) //将指向父亲、左右孩子的指针置空
{
ht[i].weight = 0;
ht[i].parent = 0;
ht[i].flag = 0;
ht[i].lchild = -1;
ht[i].rchild = -1;
}
printf("输入每个叶子结点的值:");
for (i = 0; i < n; i++)
{
getchar(); //要放getchar接收回车符
scanf("%c", &ht[i].data);
}
printf("输入对应结点权值:");
for (i = 0; i < n; i++)
{
getchar();
scanf("%lf", &ht[i].weight);
}
}
//输出哈夫曼编码
void OutputHT(HTNode ht[], HCode hcd[], int n)
{
int i, j;
for (i = 0; i < n; i++)
{
printf("%c的编码为:", ht[i].data);
for (j = hcd[i].start + 1; j < n; j++)
{
printf("%d", hcd[i].bit[j]);
}
printf("\n");
}
}
int main()
{
HTNode ht[max]; //存放所有结点数组
HCode hcd[maxleaf];
int n,i;
printf("输入数据个数:");
scanf("%d", &n);
InitHT(ht, hcd, n);
CreateHT(ht, hcd, n);
OutputHT(ht, hcd, n);
return 0;
}
Computational Results
由于部分代码我自己还不理解,在这儿暂时不做过多解释