南京邮电大学数据结构实验二(二叉树的基本操作及哈夫曼编码/译码系统的实现)

一、二叉树的创建和遍历

(一)算法设计

1、数据结构
typedef struct btnode {                     // 二叉树节点结构体
    ElemType element;
    struct btnode* lChild;
    struct btnode* rChild;
}BTNode;

分析:设计了二叉树节点结构体,内含三个成员变量,本节点的关键字值element,左孩子和有孩子节点的地址lChild 和 rChild。

2、算法流程图绘制

在这里插入图片描述

3、模块设计

在这里插入图片描述

(二)算法实现与分析

1、先序构建二叉树
BTNode* PreCreateBt(BTNode* t) {
    char c;
    c = getchar();
    if (c == '#') {                             // 输入#表示此节点没有孩子
        t = NULL;
    }
    else {
        t = (BTNode*)malloc(sizeof(BTNode));
        t->element = c;                         //构造根结点
        t->lChild = PreCreateBt(t->lChild);     //构造左子树
        t->rChild = PreCreateBt(t->rChild);     //构造右子树
    }
    return t;
}

算法分析:采用递归算法,先构造根节点,再构造左孩子,再构造右孩子,依次递归。
时间复杂度:O(n)

2、先序遍历 VLR
void PreOrderTransverse(BTNode* t) {
    if (t == NULL) {
        return;
    }
    printf("%c", t->element);           // 先序遍历根结点并输出
    PreOrderTransverse(t->lChild);      // 先序遍历左子树
    PreOrderTransverse(t->rChild);      // 先序遍历右子树
}
算法分析:采用递归算法,先遍历根节点,再遍历左孩子,再遍历右孩子。
时间复杂度:O(n)
3、中序遍历 LVR
void InOrderTransverse(BTNode* t) {
    if (t == NULL) {
        return;
    }
    InOrderTransverse(t->lChild);      // 中序遍历根结点的左子树
    printf("%c", t->element);          // 打印输出根结点
    InOrderTransverse(t->rChild);      // 中序遍历根结点的右子树
}

算法分析:采用递归算法,先遍历左孩子,再遍历根节点并输出,再遍历右孩子。
时间复杂度:O(n)

4、后序遍历 LRV
void PostOrderTransverse(BTNode* t) {
    if (t == NULL) {
        return;
    }
    PostOrderTransverse(t->lChild);      // 后序遍历根结点的左子树
    PostOrderTransverse(t->rChild);      // 后序遍历根结点的右子树
    printf("%c", t->element);            // 最后打印输出根结点
}

算法分析:采用递归算法,先遍历左孩子,再遍历右孩子,再遍历根节点并输出。
时间复杂度:O(n)

(三)实验结果

在这里插入图片描述

二、二叉树求解

(一)算法设计

1、数据结构
typedef struct btnode {
    ElemType element;
    struct btnode* lChild;
    struct btnode* rChild;
}BTNode;

分析:设计了二叉树节点结构体,内含三个成员变量,本节点的关键字值element,左孩子和有孩子节点的地址lChild 和 rChild。如果节点的element为 ’#’ 则表示该节点为空。

2、算法流程图绘制

在这里插入图片描述

3、模块设计

在这里插入图片描述

(二)算法实现与分析

1、求二叉树结点个数
//求二叉树结点个数
int Size(BTNode* t) {
    if (t == NULL) return 0;
    return Size(t->lChild) + Size(t->rChild) + 1;
}

分析:如果为空树,返回二叉树结点数为0;不是空树,则依次递归本节点的左孩子和右孩子,返回
返回左子树点数+右子树节点数+1;即可求得二叉树节点的数量。
时间复杂度:O(n)

2、求二叉树叶子结点数
//求二叉树叶子结点个数
int Leaf(BTNode* t) {
    if (t == NULL) return 0;
    if ((t->lChild == NULL) && (t->rChild == NULL)) return 1;
    return Leaf(t->lChild) + Leaf(t->rChild);
}

分析:如果为空树,返回叶子结点数为0;不是空树且当前节点的左孩子和右孩子均为空节点,返回1;
否则计算左子树的叶子节点数与右子树叶子节点数之和并返回;即可求得二叉树叶子节点的数量。
时间复杂度:O(n)

3、求二叉树的高度
//求二叉树的高度
int Depth(BTNode* t) {
    if (t == NULL) return 0;
    else return 1 + std::max(Depth(t->lChild), Depth(t->rChild));
}

分析:如果当前节点为空,返回树的高度为0;否则递归1+左孩子和右孩子中较大的树的高度并返回。
时间复杂度:O(n)

4、求交换二叉树所有左右子树
//交换二叉树所有子树
void Swap(BTNode* t) {
    if (t) {
        BTNode* temp = t->lChild;
        t->lChild = t->rChild;
        t->rChild = temp;
        Swap(t->lChild);
        Swap(t->rChild);
}

分析:采用递归算法,如果当前节点不为空,则将本节点的左右孩子交换,依次递归调用左孩子和右孩子,即可完成二叉树所有子树的交换。
时间复杂度:O(n)

(三)实验结果

在这里插入图片描述

三、哈夫曼树

(一)算法设计

1、数据结构
typedef struct hfmTNode {
    ElemType element;           //结点的数据域
    int w;                      //结点的权值
    struct hfmTNode* lChild;    //结点的左孩子指针
    struct hfmTNode* rChild;    //结点的右孩子指针
}HFMTNode;

分析:创建哈夫曼树节点结构体,内含4个成员变量,分别为节点的数据域,节点的权值,节点的左孩子地址和节点的右孩子地址。

2、算法流程图绘制

在这里插入图片描述

3、模块设计

在这里插入图片描述

(二)算法实现与分析

1、哈夫曼树的创建
HfmTree CreateHfmTree(ElemType weight[], char charArr[], int size)
{
    PriQueue pQ(size);
    HfmTree x, y, z;
    for (int i = 0; i < size; i++) {
        z.MakeTree(weight[i], charArr[i], x, y);
        z.SetWeight(weight[i]);
        pQ.Append(z);
        z.SetNull();
    }
    for (int i = 1; i < size; i++) {
        pQ.Deal(x);
        pQ.Deal(y);
        z.MakeTree(x.GetWeight() + y.GetWeight(), '*', x, y); // *区别叶子节点和普通结点
        z.SetWeight(x.GetWeight() + y.GetWeight());
        pQ.Append(z);
        z.SetNull();
    }
    pQ.Deal(z);
    return z;
}

分析:函数传入三个变量,分别是权值数组,要编码的字符数组和字符数量。先依据传入的顺序生成队列。
选择两个权值最小的节点进行结合生成新的二叉树。如果超过两棵树则继续循环。

2、哈夫曼树的编码
void HfmTree::Code(BTNode* t, char a)
{
    if (t) {
        if (t->ch == a) {
            cout << t->num;
        }
        Code(t->lChild, a);
        Code(t->rChild, a);
    }
}

分析:传入要编码的字符串,依次将字符串中的字符传入本函数,得到0-1序列
时间复杂度:O(n)

3、哈夫曼树的解码
// 由输入的编码输出相应的字符
void HfmTree::DeCode(BTNode* q)
{
    cout << "请输入二进制编码(0和1的组合):" << endl;
    string n;
    cin >> n;
    BTNode* t = q;
    int count = n.length();
    for (int i = 0; i < count; i++) {
        if (n[i] == '0' && t->lChild->ch != '*') {
            cout << t->lChild->ch;
            t = q;
        }
        else if (n[i] == '1' && t->rChild->ch != '*') {
            cout << t->rChild->ch;
            t = q;
        }
        else if (n[i] == '0' && t->lChild != NULL) {
            t = t->lChild;
        }
        else if (n[i] == '1' && t->rChild != NULL) {
            t = t->rChild;
        }
        else {
            cout << "Decode fail!";
            return;
        }
}

分析:在哈夫曼树的编码数组中查找对应字符的二进制编码并输出。
时间复杂度:O(n)

4、打印哈夫曼树

分析:因为使用先序遍历和中序遍历可以唯一的表示一棵树,所以依次打印哈夫曼树的先序遍历和中序遍历。
时间复杂度:O(n)

(三)实验结果

在这里插入图片描述

四、全部代码

全部代码

五、实验报告

需要参考的可以点击此处下载实验报告

  • 15
    点赞
  • 130
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
数据结构算法分析》实验报告 姓名 学号_ _____ __年 __月__ __日 上机题目:以静态链表为存储结构,编写给定权值{7,19,2,6,32,3}构造哈夫曼树的 算法。 (输出以存储结构表示或以树型显示(90度旋转)) 需求分析 1. 输入数据必须为int的整形数据,其数值范围为:-~47 2. 输出的数据格式为:%d 3. 测试数据的数据为:{7,19,2,6,32,3} 详细设计 1. 该程序采用顺序表的存储结构,其数据结构定义如下: #define n 6 #define m 2*n-1 #define max 100typedef struct {int data; int lchild,rchild,prnt; }hufmtree; 所用数据类型中每个操作的伪码算法如下: 创建哈夫曼树 Program hufm(hufmtree t[m]) FOR i=0;i<m;i++ TO t[i].data=0; t[i].lchild=0; t[i].rchild=0; t[i].prnt=0; End FOR 输入结点值 FOR i=n;i<m;i++ TO p1=0;p2=0; small1=max;small2=max FOR j=0;j<=i-1;j++ TO IFt[j].prnt?=0 IF(t[j].data<small1) small2=small1; small1=t[j].data; p2=p1; p1=j;} ELSE IF(t[j].data<small2) small2=t[j].data; p2=j; t[p1].prnt=i+1; t[p2].prnt=i+1; t[i].lchild=p1+1; t[i].rchild=p2+1; t[i].data=t[p1].data+t[p2].data; END IF END FOR END Hufman 调试分析 1. 调试过程中主要遇到哪些问题?是如何解决的? 开始的时候main函数的数据结构类型定义的与主函数不同,而且缺少返回值,导致最 后的结果陷入死循环,通过看书,向同学询问,得以解决。 2. 经验和体会 哈夫曼树又称最优二叉树,此次实验创建哈夫曼树算法,虽然依旧犯了不少错误,但 仍解决了。在其中学习了很多,对树有了更深的了解。 测试结果 附件 见 058詹奇.Cpp ----------------------- 数据结构算法分析实验报告全文共3页,当前为第1页。 数据结构算法分析实验报告全文共3页,当前为第2页。 数据结构算法分析实验报告全文共3页,当前为第3页。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

亦是远方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值