北邮 数据结构实验报告2
北邮c++八皇后数据结构实验报告

数据结构实验报告实验名称:实验二——栈和队列学生姓名:班级:班内序号:学号:日期:1.实验要求【实验目的】1、进一步掌握指针、模板类、异常处理的使用2、掌握栈的操作的实现方法3、掌握队列的操作的实现方法4、学习使用栈解决实际问题的能力5、学习使用队列解决实际问题的能力【实验内容】利用栈结构实现八皇后问题。
八皇后问题19世纪著名的数学家高斯于1850年提出的。
他的问题是:在8*8的棋盘上放置8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列、同一斜线上。
请设计算法打印所有可能的摆放方法。
提示:1、可以使用递归或非递归两种方法实现2、实现一个关键算法:判断任意两个皇后是否在同一行、同一列和同一斜线上2. 程序分析#include<iostream>#include<cmath>using namespace std;const int N=8; //皇后的个数static int m=0;//用来计数,使用方法数class Queen{public:void Print();//输出皇后的排列int Check(int i,int k);//判断位置是否符合要求void Queens(int k);//递归调用private:int q[N];//存储每个皇后位置int num;};void main(){Queen Q;cout<<"Queen可能的位置:"<<endl;Q.Queens(1);//从第一个皇后开始排cout<<"共有"<<m<<" 种方法放置Queen"<<endl;}void Queen::Queens(int k)//计算出皇后的排列,k是当前皇后数量{ int i;if(k>N)//如果达到里要求的数量输出皇后排列{ Print();}else //否则在适当的位置添加一个新皇后{for(i=1;i<=N;i++)if(Check(i,k)) //判断该行中该位置放置'皇后'是否符合要求{q[k]=i; //记录改行中该点的位置Queens(k+1); //放置下一行的'皇后'}}}void Queen::Print(){cout<<"第"<<++m<<"种:";for(int i=1;i<=N;i++){cout<<endl;for(int j=1;j<=N;j++){if(j==q[i])cout<<"Q ";elsecout<<"* ";}}cout<<endl;}int Queen::Check(int i,int k){int j;j=1;while(j<k){if((q[j]==i) || abs(q[j]-i)==abs(j-k)) //判断列,判断斜线是否满足条件return 0; //不符合返回0j++;}return 1; //符合返回}1,首先声明一个Queen类,包含打印函数,找Queen位置函数以及判断位置是否合理函数;Print() Check(int i,int k) Queens(int k)Queens(int k)函数:从第一个位置开始2.1 存储结构2.1存储结构1、存储结构:栈(递归)2.2 关键算法分析1、递归void Queen::Queens(int k,int n)//计算出皇后的排列,k是当前皇后数量,n是数量上限{ int i;if(k>n)//如果达到里要求的数量输出皇后排列{ Print(n);count();}else //否则在适当的位置添加一个新皇后{for(i=1;i<=n;i++)if(Check(i,k)) //判断该行中该位置放置'皇后'是否符合要求{q[k]=i; //记录改行中该点的位置Queens(k+1,n); //放置下一行的'皇后'}}}算法步骤:(1).如果输入的k大于皇后的数量,则输出皇后的位置(2)。
北邮数据结构试验报告试验二含源码

数据结构实验报告实验名称:实验二一一栈和队学生姓名:申宇飞班级:班内序03号:学号:日期2013年11月18日:1- 实验要求1.1实验目的:通过选择卞面五个题目之一进行实现,掌握如卞内容:>进一步掌握指针、模板类、异常处理的使用>掌握栈的操作的实现方法>掌握队列的操作的实现方法>学习使用栈解决实际问题的能力>学习使用队列解决实际问题的能力1.2实验内容题目1根据栈和队列的抽象数据类型的定义,按要求实现一个栈或一个队列。
要求:1、实现一个共享栈2、实现一个链栈3、实现一个循环队列4、实现一个链队列编写测试mainO函数测试线性表的正确性。
2.程序分析2.1存储结构链栈:栈的链式存储结构,其实现原理类似于单链表,结点结构与单链表相同,但链栈在实现时直接采用栈顶指针指向栈顶元素。
第]页北京邮电大学信息与通信工程学院data next栈顶栈底关键算法分析链栈:一、入栈操作算法步骤:自然语言描述:1、建立新结点2、给p结点的数据域赋值3、修改p结点的指针域,将其指向栈顶结点4、栈顶指针指向p结点伪代码描述:1)Node<T> * s = new Node<T>;2)p->data = x;3)p->next = top;4)top = p;二、出栈操作算法步骤:自然语言描述:1、判断栈是否为空2、保存栈顶结点的数据域3、定义指针p指向栈顶结点4、栈顶指针指向下一个结点5、释放p结点伪代码描述:1)if(EmptyO)throw" F溢“;2)T x = top->data;3)Node<T> * p = top;4)top = top->next;5)elete p;三、链栈的取栈顶元素算法步骤:自然语言描述:1、判断栈是否为空第3页2、定义指针p指向栈顶结点3、返回栈顶元素的值,不删除伪代码描述1)if(EmptyO)tlu'ow H卜溢";2)Node<T>*p=top;3)cout«p->data;四、遍历链栈元素算法步骤:自然语言描述:1、定义指针p指向栈顶结点2、判断栈是否为空3、返回栈元素的值4、把下一个指针的值赋给p 伪代码描述:1)Node<T>*p = top;2)while(p !=NULL)3)cout« p->data ;4)p = p->next;五、析构函数算法步骤:自然语言描述:1、判断栈顶指针是否为空2、定义指针p指向栈顶结点3、把下一个指针的值赋给栈顶指针4、释放要释放的指针伪代码描述:1)while(top)2)strnct Node <T> * p = top;3)top = top->next;4)deletep; 时间复杂的:0(1)。
北邮数据结构实验报告

北邮数据结构实验报告摘要:本报告基于北邮数据结构实验,通过实际操作和实验结果的分析,总结和讨论了各实验的目的、实验过程、实验结果以及相关的问题和解决方法。
本报告旨在帮助读者了解数据结构实验的基本原理和应用,并为今后的学习和研究提供参考。
1. 实验一:线性表的操作1.1 实验目的本实验旨在掌握线性表的基本操作以及对应的算法实现,包括插入、删除、查找、修改等。
1.2 实验过程我们使用C++语言编写了线性表的相关算法,并在实际编程环境下进行了测试。
通过插入元素、删除元素、查找元素和修改元素的操作,验证了算法的正确性和效率。
1.3 实验结果经过测试,我们发现线性表的插入和删除操作的时间复杂度为O(n),查找操作的时间复杂度为O(n),修改操作的时间复杂度为O(1)。
这些结果与预期相符,并反映了线性表的基本特性。
1.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如插入操作的边界条件判断、删除操作时的内存释放等。
通过仔细分析问题,我们优化了算法的实现,并解决了这些问题。
2. 实验二:栈和队列的应用2.1 实验目的本实验旨在掌握栈和队列的基本原理、操作和应用,并进行实际编程实现。
2.2 实验过程我们使用C++语言编写了栈和队列的相关算法,并在实际编程环境下进行了测试。
通过栈的应用实现表达式求值和逆波兰表达式的计算,以及队列的应用实现图的广度优先遍历,验证了算法的正确性和效率。
2.3 实验结果经过测试,我们发现栈的应用可以实现表达式的求值和逆波兰表达式的计算,队列的应用可以实现图的广度优先遍历。
这些结果证明了栈和队列在实际应用中的重要性和有效性。
2.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如中缀表达式转后缀表达式的算法设计、表达式求值的优化等。
通过查阅资料和与同学的讨论,我们解决了这些问题,并完善了算法的实现。
3. 实验三:串的模式匹配3.1 实验目的本实验旨在掌握串的基本操作和模式匹配算法,并进行实际编程实现。
北邮高级计算机系统结构实验二三四五

实验二指令流水线相关性分析·实验目的通过使用WINDLX模拟器,对程序中的三种相关现象进行观察,并对使用专用通路,增加运算部件等技术对性能的影响进行考察,加深对流水线和RISC 处理器的特点的理解。
·实验原理:指令流水线中主要有结构相关、数据相关、控制相关。
相关影响流水线性能。
·实验步骤一.使用WinDLX模拟器,对Fact.s做如下分析:(1)观察程序中出现的数据/控制/结构相关。
指出程序中出现上述现象的指令组合。
(2)考察增加浮点运算部件对性能的影响。
(3)考察增加forward部件对性能的影响。
(4)观察转移指令在转移成功和转移不成功时候的流水线开销。
·实验过程一.使用WinDLX模拟器,对Fact.s做如下分析:浮点加、乘、除部件都设置为1,浮点数运算部件的延时都设置为4,如图1:图1 初始设置将fact.s和input.s加载至WinDLX中,如图2示。
图2 加载程序1.观察程序中出现的数据/控制/结构相关;指出程序中出现上述现象的指令组合。
1)数据相关点击F7,使程序单步执行,当出现R-Stall时停止,运行过程中出现下图3所示,输入整数6。
图3 输入整数6打开Clock Diagram,可以清楚的看到指令执行的流水线如图4所示。
图4 指令流水线双击第一次出现R-Stall的指令行,如图5所示。
图5 指令详细信息对以上出现的情况分析如下:程序发生了数据相关,R-Stall(R-暂停)表示引起暂停的原因是RAW。
lbu r3,0×0(r2)要在WB周期写回r3中的数据;而下一条指令seqi r5,r3,0×a要在intEX周期中读取r3中的数据。
上述过程发生了WR冲突,即写读相关。
为了避免此类冲突,seq r5,r4,0×a的intEX指令延迟了一个周期进行。
由此,相关指令为:2)控制相关由图6可以看出,在第4时钟周期:第一条指令处于MEM段,第二条命令处于intEX段,第三条指令出于aborted状态,第四条命令处于IF段。
北邮数据结构实验报告三题目2-哈夫曼树

11.实验要求利用二叉树结构实现哈夫曼编/ 解码器(1). 初始化:能够对输入的任意长度的字符串s 进行统计,统计每个字符的频度,并建立哈夫曼树。
(2). 建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
(3). 编码:根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
(4). 译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
(5). 打印:以直观的方式打印哈夫曼树。
(6). 计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。
(7). 用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。
2.程序分析2.1存储结构二叉树:示意图:root2.21{2.3 关键算法分析1. 定义哈夫曼树的模板类#include <iostream>#include <string.h> using namespace std; structLNode {char ch;int weight;char code[20];LNode* next; };struct TNode{int weight; //int Lchild; //int Rchild; //int Parent; // };class Huffman 结点权值左孩子指针右孩子指针双亲指针// 链表的节点, 用来统计字符频率,并编码// 字符// 权值// 字符编码// 指向下一个节点// 哈弗曼树结点的结构体1 public:Huffman(); ~Huffman(); void CreateTable(); void PrintTable(); void Encoding(); void Decoding(); void Comrate();// 构造函数,输入、统计字符,创建哈弗曼树、码表// 释放链表空间、哈弗曼树的节点// 建立编码表,并将信息存入链表// 输出码表// 哈弗曼编码// 译码void SelectMin(int &x,int &y,int begin,int end);void reverse(char ch[]); voidcontrol();private: // 选取权值最小的两个数,创建哈弗曼树// 将码值倒置,用来编码// 对菜单交互等提示操作TNode* troot;LNode* lroot; void List(char a[]); void HTree(); int Letter; char astr[1000]; char bstr[1000]; // 在统计字符频率是构建链表的根节点// 统计字符的权值建立的单链表// 哈弗曼树建立// 共有不同字符总数// 用户输入的一串字符// 将字符串的码值保存Huffman::Huffman(){lroot=new LNode;bstr[0]='\0';lroot->next=NULL;Letter=0; // 初始化字符总数为1 cout<<" 请输入一串字符,以回车键结束"<<endl;cin.getline(astr,1000,'\n');if(strlen(astr)==0) throw 1;else{List(astr); // 用链表存储每个字符HTree();CreateTable();Encoding();}};Huffman::~Huffman(){delete troot;LNode* p=lroot;while(p=lroot->next)1{{ lroot=p->next; delete p; p=lroot;}delete p; };2. 建立哈夫曼树void Huffman::HTree(){LNode* p=lroot; int a=0;troot=new TNode[2*Letter-1]; //2n-1 while (p=p->next){troot[a].weight=p->weight; troot[a].Parent=-1; troot[a].Lchild=-1; troot[a].Rchild=-1; a++;};for (int i=Letter;i<2*Letter-1;i++)troot[i].Parent=-1; int x,y,begin=0;for (int j=Letter;j<2*Letter-1;j++) while (troot[begin].Parent!=-1)begin++;个结点// 建立叶子节点// 是两个最小值的角标SelectMin(x,y,begin,j);troot[j].weight=troot[x].weight+troot[y].weight;troot[j].Lchild=x;troot[j].Rchild=y;troot[j].Parent=-1;troot[x].Parent=j;troot[y].Parent=j;}};3.统计字符的频率void Huffman::List(char a[]){LNode *p=lroot;int i=0;while(a[i]!='\0'){{while (p&&p->ch!=a[i]) // 查找链表中没有该字符或者找到该字符p=p->next;if (!p) // 如果没有该字符,创建节点。
北京邮电大学 数据结构 实验二 二叉树 可视化设计

数据结构实验报告实验名称:实验2——二叉树的构造学生姓名:XXXXNB班级:XXXXXX班内序号:学号:XXXXXXX日期:XXXXXXXX1.实验要求根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。
二叉树的基本功能:1、二叉树的建立2、前序遍历二叉树3、中序遍历二叉树4、后序遍历二叉树5、按层序遍历二叉树6、求二叉树的深度7、求指定结点到根的路径8、二叉树的销毁9、其他:自定义操作编写测试main()函数测试线性表的正确性2.程序分析2.1 存储结构采用二叉树的存储结构,其中每个二叉树的结点定义了一个结构体,该结构体包含三个元素,分别是一个T 类型的数据域data,一个指向T 类型的指针左孩子,一个指向T 类型的指针右孩子,示意图如图所示:2.2 关键算法分析代码描述:1.构造函数template < class T >void BiTree<T>::Creat(BiNode<T>*&R, T data[], int i,int n)//i表示位置,从1开始,n表示数组长度{if (i <= n&&data[i - 1]){R = new BiNode < T > ;//创建根节点R->data = data[i - 1];Creat(R->LChild, data, 2 * i, n);//创建左子树Creat(R->RChild, data, 2 * i + 1, n);//创建右子树}else R = NULL;}template<class T>BiTree<T>::BiTree(T data[], int n){Creat(Root, data, 1, n);//利用递归循环构造}2.前序遍历//前序遍历,递归template<class T>void BiTree<T>::PreOrder(BiNode<T>*R)//前序遍历,递归//R都是源自于一开始构造所产生的根节点//根->左->右{if (R != NULL){cout << R->data<<" ";//访问结点PreOrder(R->LChild);//遍历左子树PreOrder(R->RChild);//遍历右子树}}//前序遍历,非递归template<class T>void BiTree<T>::PreOrderNormal(BiNode<T>*R)//用栈模板进行非递归操作{stack<BiNode<T>*> s;//结构栈BiNode<T>* p = R;//从根结点开始循环while (p != NULL || !s.empty()){while (p != NULL){cout << p->data << " ";s.push(p);p = p->LChild;//先压栈,再更改指针域}if (!s.empty())//检验栈是否为空,栈为空后,遍历结束{p = s.top();s.pop();p = p->RChild;}}}3.中序遍历//中序遍历,递归template<class T>void BiTree<T>::InOrder(BiNode<T>*R)//左->根->右//递归,中序遍历{if (R != NULL){InOrder(R->LChild);//遍历左子树cout << R->data<<" ";//访问节点InOrder(R->RChild);//遍历右子树}}4.后序遍历//后序遍历,递归template<class T>void BiTree<T>::PostOrder(BiNode<T>*R)//递归,后序遍历//左->右->根{if (R != NULL){PostOrder(R->LChild);//遍历左子树PostOrder(R->RChild);//遍历右子树cout << R->data<<" ";//访问节点}}时间复杂度:O(n)5.层序遍历template<class T>void BiTree<T>::LevelOrder(BiNode<T>*R)//层序遍历{queue<BiNode<T>*> q;BiNode<T>* p = R;//从根结点开始循环if(p!=NULL) q.push(p);while (!q.empty()){p = q.front();cout << p->data<<" ";q.pop();if (p->LChild != NULL) q.push(p->LChild);if (p->RChild != NULL) q.push(p->RChild);}}6.析构函数//析构函数template<class T>void BiTree<T>::Release(BiNode<T>*R){if (R != NULL){Release(R->LChild);//释放左子树Release(R->RChild);//释放右子树delete R;//释放根节点}}template<class T>BiTree<T>::~BiTree(){Release(Root);//释放二叉树}7.求二叉树深度template<class T>int BiTree<T>::Depth(BiNode<T>*R)//输出二叉树的深度{if (R == NULL) return 0;else{int m = Depth(R->LChild);int n = Depth(R->RChild);return m >= n ? m + 1:n + 1;}}时间复杂度:O(n)8.求路径template<class T>bool BiTree<T>::Findpath(BiNode<T>*R, T s)//找出指定元素到根节点的路径{if (R == NULL){return false;}else{if (R->data == s)//当前元素等于e,输出该节点{cout << R->data<<" ";return true;}else if (Findpath(R->LChild, s))//经过该结点的左孩子能到达e,输出该结点{cout << R->data<<" ";return true;}else if (Findpath(R->RChild, s))//经过该结点的右孩子能到达e,输出该结点{cout << R->data << " ";return true;}elsereturn false;}}template<class T>void BiTree<T>::Detect(BiNode<T>*R, T s){if (!(Findpath(R, s))){throw"输入元素有误!";}}3. 程序运行结果主函数流程图:测试截图:初始化二叉树,菜单创建执行功能:4. 总结.调试时出现了一些问题如:异常抛出的处理,书中并未很好的提及异常处理,通过查阅资料,选择用try catch 函数对解决。
北邮数据库实验报告2模板

北京邮电大学实验报告课程名称:数据库系统原理实验名称:E-R建模与关系表转换网络工程系315班姓名王倩教师吴起凡成绩_________2016年4月5日实验二 E-R建模与关系表转换●实验目的1. 理解和掌握E-R图的基本概念。
2. 培养根据实际应用领域数据对象描述,抽取数据对象特征、关联关系等信息,设计数据库概念结构的能力。
3. 选做:学习Power Designer,进行数据模型转换和关系表的自动创建,培养软件辅助设计工具的使用能力。
●实验原理对GSM网络的各种配置资源,及资源之间的相互关系,如控制,分配给,相邻等,进行抽象,设计概念数据模型(CDM),形成E-R图,然后利用Power Designer 数据库概念设计工具,将数据库概念结构转化为物理结构,然后再转化为SQL脚本,从而在数据库中直接生成表结构。
●实验平台及环境1. 软硬件环境处理器:Inter(R) Core(TM) i5-2520M CPU 2.50GHz内存:2G操作系统:Windows 8.1 专业版,32位2. 工具实验平台: Microsoft SQL Server2012数据库管理系统数据库系统概念设计工具:Sybase Power Designer 12●实验内容1.根据数据需求描述抽象出E-R图阅读《GSM移动通信网络配置数据库》课程实验背景资料-11-v4.doc,根据GSM的基本概念,分析其中的数据需求,将其描述抽象成实体和联系,并确定实体和联系的属性,特别要注意标明其主键和外键等约束关系,最终形成E-R图。
2.将E-R图输入相关设计工具(Power Design)形成概念模型(CDM)。
3.使用工具将E-R图转换为数据库物理结构(PDM)。
4.将物理模型转化为生成数据库中的表和视图的脚本,注意要选择数据库为SQL Server。
5.执行SQL脚本,生成表和视图。
6.成功后,查看生成的表和视图的情况。
●实验步骤1. 需求分析GSM移动通信网络配置数据库是对通信网中的各种资源及各种资源之间的关系进行描述。
数据结构_迷宫求解_实验报告 北邮

数据结构实验报告实验名称:实验二——利用栈结构实现迷宫求解问题学生姓名:班级:班内序号:学号:日期:2012年11月19日一、实验目的1、进一步掌握指针、模板类、异常处理的使用2、掌握栈的操作的实现方法3、掌握队列的操作的实现方法4、学习使用栈解决实际问题的能力5、学习使用队列解决实际问题的能力二、实验要求:利用栈结构实现迷宫求解问题。
迷宫求解问题如下:心理学家把一只老鼠从一个无顶盖的大盒子的入口赶进迷宫,迷宫中设置很多隔壁,对前进方向形成了多处障碍,心理学家在迷宫的唯一出口放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出口,测试算法的迷宫如下图所示。
提示:1、可以使用递归或非递归两种方法实现2、老鼠能够记住已经走过的路,不会反复走重复的路径3、可以自己任意设置迷宫的大小和障碍4、使用“穷举求解”的方法三、程序分析1、存储结构栈存储结构;示意图;2、关键算法分析A、绘制迷宫;伪代码:1、输出迷宫的大小及全部设置为障碍;2、根据键盘的输入绘制迷宫的路线,起始点和终点;void draw()//绘制迷宫障碍{k=getch();switch(int(k)){case 105://上if(by>5){by--;j--;}break;case 107://下if(by<M+4){by++;j++;}break;case 106://左if(bx>2){bx=bx-2;i--;}break;case 108://右if(bx<2*N){bx=bx+2;i++;}break;case 114://'R'路map[i][j]=0;cout<<".";break;case 119://'W'墙map[i][j]=-3;cout<<"■";break;case 115://'S'起点s[0].x=i;//起点入栈s[0].y=j;top=1;map[i][j]=-1;cout<<k;break;case 101://'E'终点map[i][j]=-2;cout<<k;break;}gotoxy(bx,by);}B、路径寻找伪代码;1、向某一方向查找是否有路;2、如有遍历一下栈,看是否已经进栈,一进栈就舍弃,寻求下一个;无就让其进栈。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构实验报告实验名称:__ 哈夫曼树________学生姓名:______ 蔡宇豪_________________班级:________ 2 5____________________ 班内序号:__________15__________________学号:_________2012210673___________________ 日期:________2013.11.24____________________2. 程序分析2.1 存储结构哈夫曼树结点的存储结构包括双亲域parent,左子树lchild,右子树rchild,还有字符word,权重weight,编码code对用户输入的信息进行统计,将每个字符作为哈夫曼树的叶子结点。
统计每个字符出现的次数作为叶子的权重,统计次数可以根据每个字符不同的ASCII码,根据叶子结点的权重建立一个哈夫曼树2.2 关键算法分析要实现哈夫曼解/编码器,就必须用二叉树结构建立起哈夫曼树,其中有4个关键算法,首先是初始化函数,统计每个字符的频度,并建立起哈夫曼树;然后是建立编码表,将每个字符的编码输出;再次就是编码算法,根据编码表对输入的字符串进行编码,并将编码后的字符串输出;最后是译码算法,利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。
1.初始化函数int i,j;for(i=0;i<MAX;i++)a[i]=0; //先将a[]数组中每个值都赋为,不然程序会运行出错?for(i=0;s[i]!='\0';i++) //'\0'字符串结束标志{for(j=0;j<n;j++){if(s[i]==b[j]) //判断该字符是否已经出现过break;}if(j<n) //该字符出现过,对应计数器加一a[j]++;else//该字符为新字符,上面的循环全部运行完毕,j=n,记录到b[j]中,对应计数器加一{b[j]=s[i];a[j]++;n++; //出现的字符种类数加一}}//cout<<"共有"<<n<<"种字符,分别为:"<<endl;for(i=0;i<n;i++)cout<<b[i]<<"出现次数为:"<<a[i]<<endl;HTree=new HNode[2*n-1] ; //哈夫曼树初始化for(int i=0;i<2*n-1;i++){if(i<n){HTree[i].weight=a[i];}else{HTree[i].weight=0;}HTree[i].LChild=-1;HTree[i].RChild=-1;HTree[i].parent=-1;}int x,y,m1,m2; //x,y用于存放权值最小结点在数组中的下标for(int i=n;i<2*n-1;i++) //开始建哈夫曼树{//找出权值最小的结点m1=m2=MAX; //MAX=1000x=y=0;for(int j=0;j<i;j++){if(HTree[j].weight<m1&&HTree[j].parent==-1){m2=m1;m1=HTree[j].weight;x=j;}else if(HTree[j].weight < m2 && HTree[j].parent==-1){m2=HTree[j].weight;y=j;}}HTree[x].parent=HTree[y].parent=i;HTree[i].weight=HTree[x].weight+HTree[y].weight;HTree[i].LChild=x;HTree[i].RChild=y;HTree[i].parent=-1;2.生成编码表HCodeTable=new HCode[n];for(int i=0;i<n;i++){HCodeTable[i].data=b[i];int child=i;int parent=HTree[i].parent;int k=0;while(parent!=-1){if(child==HTree[parent].LChild)HCodeTable[i].code[k]='0';elseHCodeTable[i].code[k]='1';k++;child=parent;parent=HTree[child].parent;}HCodeTable[i].code[k]='\0';cout<<b[i]<<"的编码:";for(int j=k-1;j>=0;j--)cout<<HCodeTable[i].code[j];cout<<endl;}3.编码cout<<"编码后的字符串为:";while(*d!='\0'){for(int i=0;i<n;i++){if(b[i]==*d) //判断,每当出现一种时,就找到对应编码并输出{int k=strlen(HCodeTable[i].code);for(int j=k-1;j>=0;j--){*s=HCodeTable[i].code[j];cout<<*s;s++;}}}d++;}*s='\0';cout<<endl;【计算关键算法的时间、空间复杂度】关键算法A的时间复杂度为O(n),关键算法B的时间复杂度为O(n),关键算法C的时间复杂度为O(n),关键算法D的时间复杂度为O(n).2.3 其他程序完整代码:#include<iostream>using namespace std;const int MAX=1000;struct HNode{int weight;int parent;int LChild;int RChild;};struct HCode{char data;char code[200];};class Huffman{private:HNode *HTree; //哈夫曼树HCode *HCodeTable; //哈夫曼编码表char b[MAX]; //记录出现的字符int a[MAX]; //记录每个字符出现的次数,即权值static int n; //字符的种类数(静态变量)public:void init(char s[]); //初始化void init1(char s[]);void CreateCodeTable(); //创建编码表void Encoding(char *s,char *d); //编码void Decoding(char *s,char *d); //解码int count1() //算编码前长度{int q1=0;for(int i=0;i<n;i++){q1+=8*a[i];}return q1;}int count2() //算编码后长度{int q2=0;for(int i=0;i<n;i++){q2+=strlen(HCodeTable[i].code)*a[i];}return q2;}};int Huffman::n=0;void Huffman::init(char s[]){int i,j;for(i=0;i<MAX;i++)a[i]=0; //先将a[]数组中每个值都赋为,不然程序会运行出错?for(i=0;s[i]!='\0';i++) //'\0'字符串结束标志{for(j=0;j<n;j++){if(s[i]==b[j]) //判断该字符是否已经出现过break;}if(j<n) //该字符出现过,对应计数器加一a[j]++;else//该字符为新字符,上面的循环全部运行完毕,j=n,记录到b[j]中,对应计数器加一{b[j]=s[i];a[j]++;n++; //出现的字符种类数加一}}//cout<<"共有"<<n<<"种字符,分别为:"<<endl;for(i=0;i<n;i++)cout<<b[i]<<"出现次数为:"<<a[i]<<endl;HTree=new HNode[2*n-1] ; //哈夫曼树初始化for(int q=0;q<2*n-1;q++){if(q<n){HTree[q].weight=a[q];}else{HTree[q].weight=0;}HTree[q].LChild=-1;HTree[q].RChild=-1;HTree[q].parent=-1;}int x,y,m1,m2; //x,y用于存放权值最小结点在数组中的下标for(int w=n;w<2*n-1;w++) //开始建哈夫曼树{//找出权值最小的结点m1=m2=MAX; //MAX=1000x=y=0;for(int j=0;j<i;j++){if(HTree[j].weight<m1&&HTree[j].parent==-1){m2=m1;m1=HTree[j].weight;x=j;}else if(HTree[j].weight < m2 && HTree[j].parent==-1){m2=HTree[j].weight;y=j;}}HTree[x].parent=HTree[y].parent=w;HTree[w].weight=HTree[x].weight+HTree[y].weight;HTree[w].LChild=x;HTree[w].RChild=y;HTree[w].parent=-1;}}void Huffman::init1(char s[]){int i,j;for(i=0;i<MAX;i++)a[i]=0; //先将a[]数组中每个值都赋为,不然程序会运行出错?for(i=0;s[i]!='\0';i++) //'\0'字符串结束标志{for(j=0;j<n;j++){if(s[i]==b[j]) //判断该字符是否已经出现过break;}if(j<n) //该字符出现过,对应计数器加一a[j]++;else//该字符为新字符,上面的循环全部运行完毕,j=n,记录到b[j]中,对应计数器加一{b[j]=s[i];a[j]++;n++; //出现的字符种类数加一}}HTree=new HNode[2*n-1] ; //哈夫曼树初始化for(int e=0;e<2*n-1;e++){if(e<n){HTree[e].weight=a[e];}else{HTree[e].weight=0;}HTree[e].LChild=-1;HTree[e].RChild=-1;HTree[e].parent=-1;}int x,y,m1,m2; //x,y用于存放权值最小结点在数组中的下标,m1,m2用于存放两个无父结点且结点权值最小的两个结点for(int r=n;r<2*n-1;r++) //开始建哈夫曼树{//找出权值最小的结点m1=m2=MAX; //MAX=1000x=y=0;for(int j=0;j<r;j++){if(HTree[j].weight<m1&&HTree[j].parent==-1){m2=m1;//y=x;m1=HTree[j].weight;x=j;}else if(HTree[j].weight < m2 && HTree[j].parent==-1){m2=HTree[j].weight;y=j;}}HTree[x].parent=HTree[y].parent=r;HTree[r].weight=HTree[x].weight+HTree[y].weight;HTree[r].LChild=x;HTree[r].RChild=y;HTree[r].parent=-1;}}void Huffman::CreateCodeTable() //生成编码表{HCodeTable=new HCode[n];for(int i=0;i<n;i++){HCodeTable[i].data=b[i];int child=i;int parent=HTree[i].parent;int k=0;while(parent!=-1){if(child==HTree[parent].LChild)HCodeTable[i].code[k]='0';elseHCodeTable[i].code[k]='1';k++;child=parent;parent=HTree[child].parent;}HCodeTable[i].code[k]='\0';cout<<b[i]<<"的编码:";for(int j=k-1;j>=0;j--)cout<<HCodeTable[i].code[j];cout<<endl;}}void Huffman::Encoding(char *s,char *d) // 编码算法 //d为字符串{cout<<"编码后的字符串为:";while(*d!='\0'){for(int i=0;i<n;i++){if(b[i]==*d) //判断,每当出现一种时,就找到对应编码并输出{int k=strlen(HCodeTable[i].code);for(int j=k-1;j>=0;j--){*s=HCodeTable[i].code[j];cout<<*s;s++;}}}d++;}*s='\0';cout<<endl;}void Huffman::Decoding(char *s,char *d) //s为编码串{cout<<"解码后的字符串为:";while(*s!='\0'){int parent=2*n-1-1;while(HTree[parent].LChild!=-1){if(*s=='0')parent=HTree[parent].LChild;elseparent=HTree[parent].RChild;s++;}*d=HCodeTable[parent].data;cout<<*d;d++;}cout<<endl;void main(){int i=0;char d[MAX];char s[MAX];cout<<"请输入字符串:";while((d[i]=getchar())!='\n')i++;d[i]='\0';Huffman h;cout<<"哈夫曼功能:"<<endl;cout<<"1.统计字符种类及出现次数"<<endl;cout<<"2.数据的编码解码"<<endl;cout<<"3.分析压缩效果"<<endl;int q;for(;;){cout<<"请输入(1~3)"<<endl;cin>>q;bool x=0;switch (q){case 1:h.init(d);break;case 2:h.init1(d);h.CreateCodeTable();h.Encoding(s,d);h.Decoding(s,d);break;case 3:cout<<"编码前的长度为:"<<h.count1()<<endl;cout<<"编码后的长度为:"<<h.count2()<<endl;cout<<"压缩比为:"<<(h.count2()*1.0/h.count1())<<endl;break;default:cout<<"请输入选择!!!!!"<<endl;break;}}3.}程序运行结果分析输入:I love data Structure, I love Computer。