实验三 二叉树基本操作

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验三二叉树基本操作
(2课时)
一、实验目的
1.掌握二叉树的结构特征,以及各种存储结构的特点及使用范围。

2.掌握用指针类型描述、访问和处理二叉树的运算。

二、实验要求
1.程序结构清晰、语句完整,包含有头文件和main函数;
2.格式正确,语句采用缩进格式;
3.运行结果正确,输入输出有提示,格式美观。

三、实验设备、材料和工具
1.奔腾2计算机或以上机型
2.turboc2,vc++,TC++
四、实验内容和步骤
实验内容:
1.统计一棵二叉树中每种类型结点数(度为0、1、2的结点数)。

2.分别输入一棵有6个结点和8个结点的二叉树,编程序输出先序、中序和后序的遍历结果。

3.哈夫曼树及哈夫曼编码。

五、实验报告要求
1.根据实验内容初步设计好程序,并从理论上排除错误;
2.针对程序的健壮性准备好测试数据;
3.结果分析中如实填写运行后的结果,并记录调试过程中产生的重要问题和解决方法。

六、根据实验过程填写下面内容
1:程序:#include"test.h"
int LeafCount1=0,LeafCount2=0,LeafCount3=0;
void leaf_a(BiTree root)
{
if(root!=NULL)
{
leaf_a(root->LChild);
leaf_a(root->RChild);
if(root->LChild==NULL&&root->RChild==NULL)
LeafCount1++;
else if(root->LChild==NULL||root->RChild==NULL)
LeafCount2++;
else if(root->LChild!=NULL||root->RChild!=NULL)
LeafCount3++;
else
printf("不符合题意!");
}
}
void main()
{
BiTree root;
printf("按先序遍历序列建立二叉树,请输入需要插入的序列:\n");
CreateBiTree(&root);
// PreOrder(root);
leaf_a(root);
printf("度为0的节点数:%d\n",LeafCount1);
printf("度为1的节点数:%d\n",LeafCount2);
printf("度为2的节点数:%d\n",LeafCount3);
}
#include <stdio.h>
#include <malloc.h>
#include <conio.h>
typedef char DataType;
void Visit(char ch)
{
printf("%c ",ch);
}
typedef struct Node
{
DataType data;
struct Node *LChild;
struct Node *RChild;
}BiTNode, *BiTree;
void CreateBiTree(BiTree *bt)
{
char ch;
ch = getchar();
if(ch=='#')
*bt=NULL;
else
{
*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点
(*bt)->data=ch;
CreateBiTree(&((*bt)->LChild)); //生成左子树
CreateBiTree(&((*bt)->RChild)); //生成右子树
}
}
void PreOrder(BiTree root)
/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {
if (root!=NULL)
{
Visit(root->data); /*访问根结点*/
PreOrder(root->LChild); /*先序遍历左子树*/
PreOrder(root->RChild); /*先序遍历右子树*/ }
}
void InOrder(BiTree root)
/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {
if (root!=NULL)
{
InOrder(root ->LChild); /*中序遍历左子树*/
Visit(root ->data); /*访问根结点*/
InOrder(root ->RChild); /*中序遍历右子树*/
}
}
void PostOrder(BiTree root)
/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/ {
if(root!=NULL)
{
PostOrder(root ->LChild); /*后序遍历左子树*/
PostOrder(root ->RChild); /*后序遍历右子树*/
Visit(root ->data); /*访问根结点*/
}
}
结果
分析:(要求完全理解程序,需每人答辩)
a
b c
d e
f
2:程序:#include"bitree.h"
void main()
{
BiTree T;
char ch;
printf("按照先序遍历建立二叉树,请输入序列:\n");
CreateBiTree(&T);
printf("\n先序遍历为:"); //先序遍历
PreOrder(T);
printf("\n中序遍历为:"); //中序遍历
InOrder(T);
printf("\n后序遍历为:"); //后序遍历
PostOrder(T);
}
#include <stdio.h>
#include <malloc.h>
#include <conio.h>
#define false 0
#define true 1
typedef char DataType;
typedef struct Node
{
DataType data;
struct Node *LChild;
struct Node *RChild;
}BiTNode, *BiTree;
void CreateBiTree(BiTree *bt)
{
char ch;
ch=getchar();
if(ch=='#')
*bt=NULL;
else
{
*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点
(*bt)->data=ch;
CreateBiTree(&((*bt)->LChild)); //生成左子树
CreateBiTree(&((*bt)->RChild)); //生成右子树}
}
void PreOrder(BiTree root)
/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {
if (root!=NULL)
{
printf("%c ",root ->data); /*访问根结点*/
PreOrder(root ->LChild); /*先序遍历左子树*/
PreOrder(root ->RChild); /*先序遍历右子树*/
}
}
void InOrder(BiTree root)
/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/ {
if (root!=NULL)
{
InOrder(root ->LChild); /*中序遍历左子树*/
printf("%c ",root ->data); /*访问根结点*/
InOrder(root ->RChild); /*中序遍历右子树*/
}
}
void PostOrder(BiTree root)
/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/ {
if(root!=NULL)
{
PostOrder(root ->LChild); /*后序遍历左子树*/
PostOrder(root ->RChild); /*后序遍历右子树*/
printf("%c ",root ->data); /*访问根结点*/
}
}
结果
分析:(要求完全理解程序,需每人答辩)
第一个8个结点的二叉树图形为:
b c
e
f g h
第二个为6个节点的二叉树图形:
a
b c
d e f
对结点的输出实现递归调用,输出各种遍历的情况
3:程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "huffman.h"
//typedef char* HuffmanCode;/*动态分配数组,存储哈夫曼编码*/
/*typedef struct
{
unsigned int weight ; /* 用来存放各个结点的权值
unsigned int parent, LChild,RChild ; //指向双亲、孩子结点的指针}HTNode, * HuffmanTree; //动态分配数组,存储哈夫曼树
*/
//输出哈夫曼树
void outputHuffman(HuffmanTree HT, int m)
{
if(m!=0)
{
printf("%d ", HT[m].weight);
outputHuffman(HT,HT[m].LChild);
outputHuffman(HT,HT[m].RChild);
}
}
HuffmanTree HT; //ht哈夫曼树
HuffmanCode HC; //hc哈弗曼编码
int *w;
int i,n; // 元素的个数;
int wei; // 元素的权值;
int m;
printf("输入哈夫曼树的总结点树:" );
scanf("%d",&n);
w=(int *)malloc((n+1)*sizeof(int));
for(i=1;i<=n;i++)
{
printf("请输入第%d个元素的权值:",i);
fflush(stdin);//清除缓存
scanf("%d",&wei);
w[i]=wei;
}
CrtHuffmanTree(&HT,w,n);
m = 2*n-1;
outputHuffman(HT,m);
printf("\n");
CrtHuffmanCode(&HT,&HC,n);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 20
#define M 2*N-1
typedef char* HuffmanCode[N+1];/*存储N个哈夫曼编码串的头指针数组*/
{
unsigned int weight ; /* 用来存放各个结点的权值*/
unsigned int parent, LChild,RChild ; /*指向双亲、孩子结点的指针*/ }HTNode, HuffmanTree[M+1]; /*动态分配数组,存储哈夫曼树*/
void select(HuffmanTree *ht,int n, int *s1, int *s2)
{
int i;
int min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0)
{ min = i;
i = n+1;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0)
{
if((*ht)[i].weight < (*ht)[min].weight)
min = i;
}
}
*s1 = min;
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0 && i!=(*s1))
{ min = i;
i = n+1;
}
}
for(i=1; i<=n; i++)
{
if((*ht)[i].parent == 0 && i!=(*s1))
{
if((*ht)[i].weight < (*ht)[min].weight)
min = i;
}
}
*s2 = min;
}
void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
/*从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码*/
{
char *cd;
int i;
unsigned int c;
int start;
int p;
hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); /*分配n个编码的头指针*/
cd=(char * )malloc(n * sizeof(char )); /*分配求当前编码的工作空间*/
cd[n-1]='\0'; /*从右向左逐位存放编码,首先存放编码结束符*/
for(i=1;i<=n;i++) /*求n个叶子结点对应的哈夫曼编码*/
{
start=n-2; /*初始化编码起始指针*/
for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) /*从叶子到根结点求编码*/ if( (*ht)[p].LChild == c)
{
cd[start]='0'; /*左分支标0*/
--start;
}
else
{
cd[start]='1'; /*右分支标1*/
--start;
}
(*hc)[i]=(char *)malloc((n-start)*sizeof(char)); /*为第i个编码分配空间*/
strcpy((*hc)[i],&cd[start+1]);
}
free(cd);
for(i=1;i<=n;i++)
printf("%d编码为%s\n",(*ht)[i].weight,(*hc)[i]);
}
void CrtHuffmanTree(HuffmanTree *ht , int *w, int n)
{ /* w存放已知的n个权值,构造哈夫曼树ht */
int m,i;
int s1,s2;
m=2*n-1;
// *ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /*0号单元未使用*/ for(i=1;i<=n;i++)
{/*1-n号放叶子结点,初始化*/
(*ht)[i].weight = w[i];
(*ht)[i].LChild = 0;
(*ht)[i].parent = 0;
(*ht)[i].RChild = 0;
}
for(i=n+1;i<=m;i++)
{
(*ht)[i].weight = 0;
(*ht)[i].LChild = 0;
(*ht)[i].parent = 0;
(*ht)[i].RChild = 0;
} /*非叶子结点初始化*/
/* ------------初始化完毕!对应算法步骤1---------*/
for(i=n+1;i<=m;i++) /*创建非叶子结点,建哈夫曼树*/
{ /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分
别赋值给s1、s2返回*/
select(ht,i-1,&s1,&s2);
(*ht)[s1].parent=i;
(*ht)[s2].parent=i;
(*ht)[i].LChild=s1;
(*ht)[i].RChild=s2;
(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
}
}/*哈夫曼树建立完毕*/
结果
分析:(要求完全理解程序,需每人答辩)
通过调用select函数找出最小的两个权值,用CrtHuffman函数存放权值构成哈夫曼树
再调用CrtHuffmanCode函数实现从叶子结点到根,逆向求每个叶子结点对应的哈弗曼编码。

相关文档
最新文档