北邮数据结构实验第二次实验图

合集下载

北邮世纪学院数据结构实验文档

北邮世纪学院数据结构实验文档

北邮世纪学院数据结构实验文档实验一:<编程文档><注意:生成日期和修改日期不需要填写,系统自动填写><生成新文档的时候,需要修改页眉中标注的部分,不需要修改页脚><修改文档之后,请刷新一下目录,由于我们的文档一般比较长,还是有目录比较好。

> <文件名起名原则:_文档名称>修订历史记录本文档简要说明。

目录修订历史记录 (1)1问题描述 (3)2主函数流程MAIN() (3)2.1功能 (3)2.2性能 (3)2.3输人项 (3)2.4输出项 (3)2.5算法 (3)2.6流程逻辑 (3)2.7注释设计 (4)2.8限制条件 (4)3函数1设计说明 (4)4源程序 (4)5测试报告 (5)5.1案例一:测试MAIN() (5)5.2案例二:测试子函数 (5)5.3尚未解决的问题 (5)6心得体会 (5)7分工及签名 (5)1问题描述给出对该程序的简要描述(作业题),主要说明安排设计本程序的目的意义。

2主函数流程main()2.1功能说明该程序应具有的功能,可采用IPO图(即输入一处理一输出图)的形式。

2.2性能说明对该程序的全部性能要求,包括对精度、灵活性和时间特性的要求。

2.3输人项给出对每一个输入项的特性,包括名称、标识、数据的类型和格式、数据值的有效范围、输入的方式。

数量和频度、输入媒体、输入数据的来源和安全保密条件等等。

2.4输出项给出对每一个输出项的特性,包括名称、标识、数据的类型和格式,数据值的有效范围,输出的形式、数量和频度,输出媒体、对输出图形及符号的说明、安全保密条件等等。

2.5算法详细说明本程序所选用的算法,具体的计算公式和计算步骤。

2.6流程逻辑用图表(例如流程图、判定表等)辅以必要的说明来表示本程序的逻辑流程。

Word自带的绘图工具一般都不利于排版,建议使用Visio绘制所有的流程图和模块图,插入Word。

Visio可以有很多页,最好将自己的论文图片都放在一个vsd文件中。

北邮信通院数据结构实验报告三哈夫曼编码器.pptx

北邮信通院数据结构实验报告三哈夫曼编码器.pptx

-1
2.2 关键算法分析 (1)计算出现字符的权值
利用 ASCII 码统计出现字符的次数,再将未出现的字符进行筛选,将出现的字符及頻 数存储在数组 a[]中。
void Huffman::Init() {
int nNum[256]= {0}; //记录每一个字符出现的次数 int ch = cin.get();
第2页
北京邮电大学信息与通信工程学 院
2
-1
-1
-1
5
-1
-1
-1
6
-1
-1
-1
7
-1
-1
-1
9
-1
-1
-1
weight lchild rchild parent
2
-1
-1
5
5
-1
-1
5
6
-1
-1
6
7
-1
-1
6
9
-1
-1
7
7
0
1
7
第3页
北京邮电大学信息与通信工程学 院
13
2
3
8
16
5
4
8
29
6
7
2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每 个字符的编码输出。
3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的 字符串输出。
4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译 码,并输出译码结果。
5、打印(Print):以直观的方式打印赫夫曼树(选作) 6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫

北邮数据结构实验报告

北邮数据结构实验报告

北邮数据结构实验报告北京邮电大学信息与通信工程学院2009级数据结构实验报告实验名称:实验三哈夫曼编/解码器的实现学生姓名:陈聪捷日期:2010年11月28日1.实验要求一、实验目的:了解哈夫曼树的思想和相关概念;二、实验内容:利用二叉树结构实现哈夫曼编/解码器1.初始化:能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树。

2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

3.编码:根据编码表对输入的字符串进行编码,并将编码后的字符串输出。

4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。

5.打印:以直观的方式打印哈夫曼树。

6.计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。

7.用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2.程序分析2.1存储结构二叉树templateclassBiTree{public:BiTree();//构造函数,其前序序列由键盘输入~BiTree(void);//析构函数BiNode*Getroot();//获得指向根结点的指针protected:BiNode*root;//指向根结点的头指针};//声明类BiTree及定义结构BiNodeData:二叉树是由一个根结点和两棵互不相交的左右子树构成data:HCode*HCodeTable;//编码表inttSize;//编码表中的总字符数二叉树的节点结构templatestructBiNode//二叉树的结点结构{Tdata;//记录数据Tlchild;//左孩子Trchild;//右孩子Tparent;//双亲};编码表的节点结构structHCode{chardata;//编码表中的字符charcode[100];//该字符对应的编码};待编码字符串由键盘输入,输入时用链表存储,链表节点为structNode{charcharacter;//输入的字符unsignedintcount;//该字符的权值boolused;//建立树的时候该字符是否使用过Node*next;//保存下一个节点的地址};示意图:2.2关键算法分析1.初始化函数(voidHuffmanTree::Init(stringInput))算法伪代码:1.初始化链表的头结点2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n 记录的是链表中字符的个数)3.从字符串第2个字符开始,逐个取出字符串中的字符3.1将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。

北邮数据结构试验报告试验二含源码

北邮数据结构试验报告试验二含源码

数据结构实验报告实验名称:实验二一一栈和队学生姓名:申宇飞班级:班内序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)。

北邮 DSP 实验二实验报告

北邮 DSP 实验二实验报告

实验二:数字信号的 FFT 分析题目1假设信号 x(n) 由下述信号组成:()0.001*cos(0.45)sin(0.3)cos(0.302)4x n n n n ππππ=+-- 这个信号有两根主谱线 0.3pi 和 0.302pi 靠的非常近,而另一根谱线 0.45pi 的幅度很小,请选择合适的长度 N 和窗函数,用 DFT 分析其频谱,得到清楚的三根谱线。

步骤:1.编写离散傅里叶变换DFT 函数:function [Xk] = dft(xn,N)% Computes Discrete Fourier Transform Coefficients% [Xk] = dft(xn,N)% Xk = DFT coeff. array over 0 <= k <= N-1% xn = input signal% N = length of DFTn = [0:1:N-1]; % row vector for nk = [0:1:N-1]; % row vecor for kWN = exp(-j*2*pi/N); % Wn factornk = n'*k; % creates a N by N matrix of nk valuesWNnk = WN .^ nk; % DFT matrixXk = xn * WNnk; % row vector for DFT coefficients2.代码实现:n=0:1:999;x=0.001*cos(0.45*n*pi)+sin(0.3*n*pi)-cos(0.302*n*pi-0.25*pi);stem(n,x);title('signal x(n), 0<=n<=999');xlabel('n');X=dft(x,1000);% 计算1000点DFT magX=abs(X(1:1:501));% 镜像对称,只画出一半 k=0:1:500;w=2*pi*k/1000;stem(w/pi,magX);title('DTFT Magnitude');xlabel('frequency in pi units');axis([0.29,0.31,0,500]);xlabel('frequency between 0.29pi and 0.31pi');axis([0.44,0.46,0,0.5]);xlabel('frequency between 0.44pi and 0.46pi');3.图片:4.分析:x(n)由3个正弦函数叠加而成,周期分别是40, 20, 1000。

北邮计算机科学与技术操作系统第二次实验

北邮计算机科学与技术操作系统第二次实验

北京邮电大学操作系统第二次实验实验报告班级302班第一部分:内存管理的伙伴算法1.实验描述:实现一个内存管理的伙伴算法,实现内存块申请时的分配和释放后的回收。

用随机函数仿真进程进行内存申请,并且以较为随机的次序进行释放。

对其碎片进行统计,当申请分配内存失败时区分实际空间不足和由于碎片而不能满足。

2.实验原理解释:假设要求分配的块其大小为128个页面。

该算法先在块大小为128个页面的链表中查找,看是否有这样一个空闲块。

如果有,就直接分配;如果没有,该算法会查找下一个更大的块,具体地说,就是在块大小为256个页面的链表中查找一个空闲块。

如果存在这样的空闲块,内核就把这256个页面分为两等份,一份分配出去,另一份插入到块大小为128个页面的链表中。

如果在块大小为256个页面的链表中也没有找到空闲页块,就继续找更大的块,即512个页面的块。

如果存在这样的块,内核就从512个页面的块中分出128个页面满足请求,然后从384个页面中取出256个页面插入到块大小为256个页面的链表中。

然后把剩余的128个页面插入到块大小为128个页面的链表中。

如果512个页面的链表中还没有空闲块,该算法就放弃分配,并发出出错信号。

以上过程的逆过程就是块的释放过程,这也是该算法名字的来由。

满足以下条件的两个块称为伙伴:两个块的大小相同,两个块的物理地址连续。

伙伴算法把满足以上条件的两个块合并为一个块,该算法是迭代算法,如果合并后的块还可以跟相邻的块进行合并,那么该算法就继续合并。

3.试验运行截图:第一组数据测试截图:第二组数据测试截图:第三组数据测试截图:4.实验代码:#include<iostream>#include<stdio.h>#define GETMIN(a,b) ((a)<(b)?(a):(b)) #define GETMAX(a,b) ((a)>(b)?(a):(b)) using namespace std;struct Node{int size;int remain;int frag;int isSplit;Node *left;Node *right;Node *parent;};struct Process{int oriMem;int reqMem;Node *ptr;void init(int _oriMem){int i;if(_oriMem<=0){oriMem=0;reqMem=0;ptr=NULL;return;}oriMem=_oriMem;for(i=31;i>=0;i--){if(oriMem&(1<<i)){break;}}if(oriMem==1<<i){reqMem=oriMem;}else{reqMem=1<<(i+1);}ptr=NULL;}};class BuddyTree{private:Node *root;Node *newNode(Node *_parent,int _size,int _remain){Node *ptr=new(Node);ptr->size=_size;ptr->remain=_remain;ptr->frag=0;ptr->isSplit=0;ptr->left=NULL;ptr->right=NULL;ptr->parent=_parent;return ptr;}public:Node* getRoot(){return root;}void init(int MaxMem){root=newNode(NULL,MaxMem,MaxMem);}void requestMem(Node *ptr,Node *&res,int reqSize,int oriSize){ if(ptr->remain<reqSize){res=NULL;return;}if(ptr->size==reqSize){res=ptr;ptr->remain=0;ptr->frag+=reqSize-oriSize;return;}if(ptr->isSplit==0){int _size=ptr->size/2;ptr->isSplit=1;ptr->left=newNode(ptr,_size,_size);ptr->right=newNode(ptr,_size,_size);requestMem(ptr->left,res,reqSize,oriSize);}else{int minMem=GETMIN(ptr->left->remain,ptr->right->remain); if(minMem>=reqSize){if(ptr->left->remain<=ptr->right->remain){requestMem(ptr->left,res,reqSize,oriSize);}else{requestMem(ptr->right,res,reqSize,oriSize);}}else{if(ptr->left->remain>=reqSize){requestMem(ptr->left,res,reqSize,oriSize);}else{requestMem(ptr->right,res,reqSize,oriSize);}}}ptr->remain=GETMAX(ptr->left->remain,ptr->right->remain);ptr->frag=ptr->left->frag+ptr->right->frag;}void releaseMem(Node *ptr){int memsize=ptr->size;int frag=ptr->frag;ptr->frag=0;ptr->remain=memsize;ptr=ptr->parent;while(ptr){if(ptr->left->remain==ptr->left->size&&ptr->right->remain==ptr->right->size){ ptr->remain=ptr->size;}else{ptr->remain=GETMAX(ptr->left->remain,ptr->right->remain);}ptr->frag-=frag;ptr=ptr->parent;}}void printTree(Node *ptr){if(ptr==NULL)return;char tmp[100];sprintf(tmp,"[Node size %dB]",ptr->size);printf("%-26s",tmp);sprintf(tmp,"remaining : %dB",ptr->remain);printf("%-26s",tmp);sprintf(tmp,"fragment : %dB",ptr->frag);printf("%s\n",tmp);printTree(ptr->left);printTree(ptr->right);}};Process P[200];int test[3][20]={{24,80,4600,8,100,1,500},{70,480,3300,25,10600,8909,490,99,40},{1,20,300,4000,50000,600000,7000000,80000000,900000000}}; int n[3]={7,9,9};int memory[3]={1024,1024*1024,1024*1024*1024};int main(){BuddyTree BT;char tmp[100];for(int t=0;t<3;t++){printf("Test%d:\n",t+1);printf("Process status:\n");for(int j=0;j<n[t];j++){P[j].init(test[t][j]);sprintf(tmp,"Original request: %d",P[j].oriMem);printf("%-30s",tmp);sprintf(tmp,"Actual request: %d",P[j].reqMem);printf("%s\n",tmp);}printf("\nMemory amount : %dB\n",memory[t]);BT.init(memory[t]);printf("\n");printf("Constructing the tree:\n");for(int j=0;j<n[t];j++){sprintf(tmp,"The process needs %d bytes.",P[j].oriMem);printf("%-35s",tmp);BT.requestMem(BT.getRoot(),P[j].ptr,P[j].reqMem,P[j].oriMem);if(P[j].ptr){printf("Request success,obtain %d bytes.\n",P[j].reqMem);}else{printf("Request failed.\n");}}printf("\n");printf("After constructing,preorder the tree:\n");BT.printTree(BT.getRoot());printf("\n");printf("After constructing the tree,the sum of fragment is %d.\n",BT.getRoot()->frag);printf("\n");printf("After the release,the tree(preorder) is:\n");for(int j=0;j<n[t];j++){if(P[j].ptr){BT.releaseMem(P[j].ptr);}}BT.printTree(BT.getRoot());printf("\n");printf("\n");system("pause");printf("\n");}return 0;}第二部分:设计一个虚拟存储区和内存工作区,并使用下述算法计算访问命中率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-哈夫曼树

北邮数据结构实验报告三题目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.程序分析
2.1存储结构
存储结构:栈(递归)
2.2关键算法分析
递归调用摆放皇后
1、关键算法伪代码:
(1).如果输入的row大于皇后的数量,则输出皇后的位置
(2)否则col从0开始递增
(3)检测(row,col)上的点是否符合条件,不符合则col自增,符合则转到下一个皇后的排列
2、代码详细分析:
void SeqStack::PlaceQueen(int row) //摆放皇后
{
for (int col=0;col< n;col++) //遍历0~7,
{
Push(col);
if (Check()) //判断摆放皇后的位置是否合适
{
if (row< n-1) //若还没有放到最后一个,则进行下一个皇后的放置
PlaceQueen(row+1);
else
{
num++; //计数器加1
{
if(top>= m-1) throw "上溢";
top++; //栈顶指针上移
data[top]=x;
}
void SeqStack::Pop() //出栈操作
{
if(Empty()) throw "下溢";
top--; //栈顶指针下移
}
void SeqStack::PlaceQue计放置八皇后,只要修改输入的N,便可显示其他情况的结果。
Print(n); //打印成功的坐标点
}
}
Pop(); //若不符合条件则出栈
}
}
bool SeqStack::Empty()

北京邮电大学 数据结构 实验二 二叉树 可视化设计

北京邮电大学 数据结构 实验二 二叉树 可视化设计

数据结构实验报告实验名称:实验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

北邮 数据结构实验报告2

数据结构实验报告实验名称:__ 哈夫曼树________学生姓名:______ 蔡宇豪_________________班级:________ 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。

北邮数据结构实验二题目3迷宫问题

北邮数据结构实验二题目3迷宫问题

数据结构实验报告实验名称:实验二——题目3. 迷宫问题学生姓名:班级:2012211118班内序号:学号:日期:2013年11月25日1.实验要求利用栈结构实现迷宫求解问题。

迷宫求解问题如下:心理学家把一只老鼠从一个无顶盖的大盒子的入口赶进迷宫,迷宫中设置很多隔壁,对前进方向形成了多处障碍,心理学家在迷宫的唯一出口放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出口,测试算法的迷宫如下图所示。

提示:1、可以使用递归或非递归两种方法实现2、老鼠能够记住已经走过的路,不会反复走重复的路径3、可以自己任意设置迷宫的大小和障碍4、使用“穷举求解”的方法2. 程序分析2.1 存储结构使用栈存储迷宫坐标空栈 入栈 出栈2.2 关键算法分析2.2.1关键算法寻找迷宫路径: 每走一步:1、如果当前位置=出口,结束2、否则:假设当前位置为路径;如果东面未走过:向东走一步 如果南面未走过:向南走一步 如果西面未走过:向西走一步 如果北面未走过:向北走一步 设置当前位置走不通,回溯 2.2.2代码详细分析 #include<iostream>using namespace std;struct Point //定义结构类型Point 存储迷宫坐标 { int x,y; };template<class T>class Stack //定义模板类Stack 实现顺序栈 {public: Stack(){top=-1;} //构造函数 void Push(T n){top++;data[top]=n;} //进栈 T Pop(){top--;return data[top+1];} //出栈 private: T data[100]; //定义数组data 存储进栈数据 int top; //栈顶指针top……top};void MasePath(int arr[][10],Point start,Point end) //函数MasePath寻找迷宫路径{Stack <Point> PointStack; //栈PointStackPoint P=start; //P记录当前迷宫坐标,首先记录入口坐标arr[P.x][P.y] = 2; //-1——墙;0——路;1——错误路径;2——正确路径do{ /只要P的坐标不是出口坐标,进行此循环PointStack.Push(P); //将P记录的坐标存入存入栈if(arr[P.x][P.y+1]==0) arr[P.x][++P.y]=2; //如果P记录坐标的右左上下有路,P记录的坐标改为路的坐标,并假定是正确路径(记为2)else if(arr[P.x][P.y-1]==0) arr[P.x][--P.y]=2;else if(arr[P.x+1][P.y]==0) arr[++P.x][P.y]=2;else if(arr[P.x-1][P.y]==0) arr[--P.x][P.y]=2;else //如果P周围没有路了,将P所存坐标退出栈,该坐标记为1,P记录该坐标上一个坐标{P=PointStack.Pop();arr[P.x][P.y]=1;P=PointStack.Pop();}}while ((P.x!=end.x) || (P.y!=end.y));}void PrintPath(int arr[][10]) //打印迷宫,墙为■,错误路径或未走路径为□,正确路径为* {for (int i=0;i<10;i++){for (int j=0;j<10;j++){if (arr[i][j]==-1) cout<<"■";else if (arr[i][j]==2) cout<<" *";else cout<<"□";}cout<<endl;}cout<<endl;}void main(){int arr[10][10]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //二维数组arr记录迷宫,-1表示墙,0表示路-1,0,0,-1,0,0,0,-1,0,-1,-1,0,0,-1,0,0,0,-1,0,-1,-1,0,0,0,0,-1,-1,0,0,-1,-1,0,-1,-1,-1,0,0,0,0,-1,-1,0,0,0,-1,0,0,0,0,-1,-1,0,-1,0,0,0,-1,0,0,-1,-1,0,-1,-1,-1,0,-1,-1,0,-1,-1,-1,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};Point start,end; //start和end分别记录迷宫入口和出口坐标start.x=1;start.y=1;end.x=8;end.y=9;MasePath(arr,start,end); //寻找迷宫路径PrintPath(arr); //打印迷宫}2.2.3时间复杂度O(1)3.程序运行结果运行结果:开始记录迷宫和其出口入口坐标寻找路径打印迷宫结束测试的迷宫为10*10,有至少一条正确路径;4. 总结开始对题没有理解透,不知道怎么把解题方法用栈编写出来,于是开始一步一步确认:迷宫有横纵坐标,有“墙”有“路”,对应到编程语言就是用0,1等数字表示“墙”和“路”,用二维数组存储,刚好数组的下标可以表示迷宫坐标;由于计算机只能从一个点开始,朝四个方向挨个判断下一步是否走得通,走得通的点需要记录下其坐标,或许还可能走着走着突然发现路走不通了,需要再退回并删除已记录的部分坐标,于是自然想到用栈存储其坐标;而坐标有2个值,要存入顺序结构的栈需要先定义一个结构类型,表示坐标……到此为止,迷宫问题如何用程序语言编写已经清晰。

数据结构_迷宫求解_实验报告 北邮

数据结构_迷宫求解_实验报告 北邮

数据结构实验报告实验名称:实验二——利用栈结构实现迷宫求解问题学生姓名:班级:班内序号:学号:日期: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、如有遍历一下栈,看是否已经进栈,一进栈就舍弃,寻求下一个;无就让其进栈。

北邮数据库实验二实验报告

北邮数据库实验二实验报告

北邮数据库实验二实验报告一、实验目的本次数据库实验二的目的在于深入理解和掌握数据库中的关系模型、SQL 语言的基本操作,以及通过实际操作来提高对数据库管理系统的应用能力。

二、实验环境本次实验使用的数据库管理系统为 MySQL,操作系统为 Windows 10。

三、实验内容及步骤(一)创建数据库和表1、首先,使用以下命令创建名为“student_management”的数据库:`CREATE DATABASE student_management;`2、然后,在该数据库中创建“students”表,用于存储学生的基本信息,表结构如下:`CREATE TABLE students (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),age INT,gender VARCHAR(10));`(二)插入数据使用以下 SQL 语句向“students”表中插入一些示例数据:`INSERT INTO students (name, age, gender)VALUES ('张三', 20, '男'),('李四', 21, '女'),('王五', 19, '男');`(三)数据查询1、查询所有学生的信息:`SELECT FROM students;`2、查询年龄大于 20 岁的学生:`SELECT FROM students WHERE age > 20;`(四)数据更新将学生“张三”的年龄修改为 21 岁:`UPDATE students SET age = 21 WHERE name ='张三';`(五)数据删除删除年龄小于 20 岁的学生:`DELETE FROM students WHERE age < 20;`四、实验结果及分析(一)创建数据库和表成功创建了“student_management”数据库和“students”表,表结构符合预期。

北邮数据结构实验报告二_栈和队列

北邮数据结构实验报告二_栈和队列

2009级数据结构实验报告实验名称:实验二栈和队列学生姓名:班级:班内序号:学号:日期:2010年12月18日实验要求题目四用栈做计算器。

设计一个算术四则运算表达式求值的简单计算器。

表达式求值是程序设计语言编译中最近本的问题,它要求把一个表达式翻译成能够直接求值的序列。

基本要求:输入中缀表达式能够转化成后缀表达式,比如输入中缀表达式“(A+B)*C”,输出“AB+C*”2、操作数使用单字母变量A、B、C等表示,操作符仅为+、-、*、/、(和);3、能够对变量A、B、C等赋值,得出正确的计算结果2. 程序分析首先,程序要求用户输入一个符号表达式,只能包含字母、+、-、*、/ 以及)和(,之后程序会用一个TurnInfixToPostfix()函数将表达式转化成后缀表达式存入一个栈中,转化过程借用逆波兰算法,建立一个符号栈,遍历用户输入的表达式,如果是字母,则直接输出,如果是运算符,则压入符号栈中(包括括号),在压栈的时候又需要注意,先要检查压栈前栈顶元素的优先级,如果优先级高于要压入的符号则直接压入该符号,否则要弹栈直到栈顶元素的优先级小于该元素的优先级然后才将该符号压入栈中(在压栈的时候会涉及到栈中有括号的情况,具体细节下面会说到),将转化的后缀表达式存入栈postfix,在输出的时候只要弹栈就行。

然后,要求用户逐个输入表达式中的字母的值,这时候,需要遍历当时在转化后缀表达式的时候过度容器vec_intoposfix,如果是字母则要求用户输入数值,压入用于计算的后缀表达式容器,如果是操作符则直接压入。

最后,在利用栈来计算值的时候,利用一个递归函数,就是一次弹栈,如果是操作符则先保存起来,接着继续弹栈,如果接下来的两个元素都为数字,就将这两个数字做相应的运算,然后压栈,如此反复,最后压入栈的元素就是表达式的值。

至此,程序的功能全部实现。

2.1 存储结构[内容要求]1、存储结构:顺序表、单链表或其他存储结构,需要画示意图,可参考书上P59页图2-92.2 关键算法分析关键算法一:将中缀表达式转化为后缀表达式VoidTurnInfixToPostfix(vector<char>&vec,stack<char>&sta,vector<char>&vecfix,stack< char>&stafix)1、 {2、int priority(-1);3、4、for (vector<char>::iterator itr=vec.begin();itr!=vec.end();itr++)5、{6、if(isLetter(*itr))7、{8、vecfix.push_back(*itr);9、}10、if (isOperator(*itr))11、{12、if(!sta.empty()) priority=getPriority(sta.top());13、else priority=-1;14、if (priority<getPriority(*itr)||priority==3&&sta.top()!=')')15、{16、sta.push(*itr);17、}18、else19、{20、if (sta.top()!=')')21、{22、while(priority>=getPriority(*itr)&&sta.top()!='(')23、{24、vecfix.push_back(sta.top());25、if (!sta.empty())26、{27、sta.pop();28、if(!sta.empty()) priority=getPriority(sta.top());29、else priority=-1;30、}31、else32、break;33、}34、sta.push(*itr);35、}36、else if(sta.top()==')')37、{38、while (sta.top()!='(')39、{40、vecfix.push_back(sta.top());41、if (!sta.empty()&&sta.top()!='(')42、{43、sta.pop();44、}45、else46、break;47、}48、}49、}50、51、52、}53、54、}55、for (vector<char>::iteratoritrfix=vecfix.end();itrfix!=vecfix.begin();--itrfix)56、stafix.push(*itrfix);57、stafix.push(*itrfix);58、}对表达式a + b * c – ( d – e) / f + g其符号栈的变化过程,红色表示未压栈的符号。

北邮数据结构实验 第二次实验 图

北邮数据结构实验 第二次实验 图

数据构造实验报告1.实验要求〔1〕实验目的通过选择下面5个题目之一进展实现,掌握如下内容:➢掌握图根本操作的实现方法➢了解最小生成树的思想和相关概念➢了解最短路径的思想和相关概念➢学习使用图解决实际问题的能力(2)实验内容根据图的抽象数据类型的定义,使用邻接矩阵或邻接表实现一个图。

图的根本功能:1、图的建立2、图的销毁3、深度优先遍历图4、广度优先遍历图5、使用普里姆算法生成最小生成树6、使用克鲁斯卡尔算法生成最小生成树7、求指定顶点到其他各顶点的最短路径8、其他:比方连通性判断等自定义操作编写测试main()函数测试图的正确性2. 程序分析2.1 存储构造图:(1)带权值的无向图V09 6V1 2 V2(2)带权值的有向图V063 9 4V1 2 V2 2.2 关键算法分析〔1〕深度优先遍历int visited[MAXSIZE]={false};template<class T>void MGraph<T>::DFS(int v){cout<<vertex[v];visited[v]=true;for(int j=0;j<vNum;j++)if(arc[v][j]==1&&!visited[j])DFS(j);}时间复杂度:O(n²)〔2〕广度优先遍历int queue[MAXSIZE];int f=0,r=0;cout<<vertex[v];visit[v]=true;queue[++r]=v;while(f!=r){v=queue[++f];for(int j=0;j<vNum;j++){if(arc[v][j]==1&&!visit[j]){cout<<vertex[j];visit[j]=true;queue[++r]=j;}时间复杂度:O〔n²〕〔3〕普利姆算法int adjvex[MAXSIZE];int lowcost[MAXSIZE];int MAX=10000;template<class T>int mininum(MGraph<T> G,int a[]){int min=MAX;int k=0;for(int i=0;i<G.vNum;i++){if(a[i]!=0&&a[i]<min)//寻找U-{V-U}中边权值最小的顶点{min=a[i];k=i;}}return k;}template<class T>void MGraph<T>:: Prim(MGraph G){for(int i=0;i<G.vNum;i++){adjvex[i]=0;lowcost[i]=G.arcs[0][i];}lowcost[0]=0;//初始化U={vo}for(int i=1;i<G.vNum;i++){int k=mininum(G,lowcost);//求下一个边权值最小的邻接点 cout<<'V'<<adjvex[k]<<"->V"<<k<<endl;lowcost[k]=0;for(int j=0;j<G.vNum;j++){if(lowcost[j]!=0&&G.arcs[k][j]<lowcost[j]){lowcost[j]=G.arcs[k][j];adjvex[j]=k;}}}}时间复杂度:O(n²)〔4〕克鲁斯卡尔算法template<class T>void GenSortEdge(MGraph<T> G,VEdge E[])//获取EdgeList{int k=0,i,j;for(i=0;i<G.vNum;i++)//边赋值for(j=i;j<G.vNum;j++)if(G.arcs[i][j]!=MAX){E[k].fromV=i;E[k].endV=j;E[k].weight=G.arcs[i][j];k++;}for(i=0;i<G.arcNum-1;i++){for(j=i+1;j<G.arcNum;j++)if(E[i].weight>E[j].weight){VEdge t=E[i];E[i]=E[j];E[j]=t;}}}const int MAX_VERTEXT=20;template<class T>void MGraph<T>:: Kruskal(VEdge E[],int n,int e){int vset[MAX_VERTEXT];for(int i=0;i<n;i++) vset[i]=i;//初始化vsetint k=0,j=0;while(k<n-1){int m=E[j].fromV,n=E[j].endV;int sn1=vset[m];//m所属的集合int sn2=vset[n];//n所属的集合if(sn1!=sn2){cout<<'V'<<m<<"->V"<<n<<endl;k++;for(int i=0;i<n;i++){if(vset[i]==sn2)//集合编号为sn2的全部改为sn1vset[i]=sn1;时间复杂度:O(n²)〔5〕求最短路径,连通性判断int dist[MAXSIZE][MAXSIZE];int path[MAXSIZE][MAXSIZE];template<class T>void Floyd(MGraph<T> G){for(int i=0;i<G.vNum;i++) //寻找最短路径for(int j=0;j<G.vNum;j++){dist[i][j]=G.arcs[i][j];if(dist[i][j]!=MAX_VALUE)path[i][j]=i;elsepath[i][j]=-1;}for(int k=0;k<G.vNum;k++)for(int i=0;i<G.vNum;i++)for(int j=0;j<G.vNum;j++)if(dist[i][k]+dist[k][j]<dist[i][j])//更新迭代数组Disk[][]{dist[i][j]=dist[i][k]+dist[k][j];path[i][j]=k;}cout<<"任意两点间的最短路径长度(以矩阵表示〕:"<<endl;int l=1;for(int i=0;i<G.arcNum;i++)for(int j=0;j<G.arcNum;j++){cout<<dist[i][j]<<" ";l++;if(l>G.arcNum) {cout<<endl;l=1;}}}时间复杂度:O(n³)3. 程序运行结果〔1〕流程图:初始化带权值的无向图深度优先遍历,广度优先遍历用普利姆算法求最小生成树用克鲁斯卡尔算法求最小生成树初始化带权值的有向图用Floyd算法求任意两点间最短路径,并判断连通性删除图〔2〕本程序所用的图带权值的无向图V09 6V1 2 V2带权值的有向图V063 9 4V1 2 V2〔3〕程序结果4. 总结〔1〕遇到的问题:私有数据访问权的问题,在编程时应该注意〔2〕心得体会:通过这次实验,我掌握了图根本操作的实现方法,了解最小生成树的思想和相关概念,了解最短路径的思想和相关概念等等。

北邮世纪学院数据结构实验文档

北邮世纪学院数据结构实验文档

北邮世纪学院数据结构实验文档实验一:线性表的实现<上机实验要求>修订历史记录本文档简要说明了第一次上机实验的作业要求。

目录修订历史记录 (1)1实验目的 (3)2问题描述 (3)2.1基本要求 (3)2.2高级要求 (3)3实验要求 (3)4上机实验文档要求 (3)5编程提示 (3)1实验目的(1)熟悉Visual C++6.0的编程环境,学会编译、设置断点、调试程序;(2)学习使用MSDN帮助(3)了解线性表的不同存储结构,并掌握顺序表和链表的编程方法(4)了解软件测试的工作内容和方法。

(5)熟悉软件文档的写作(6)了解团队开发,增强合作精神。

2问题描述有n个同学一起玩游戏(10≤n≤99),大家围成一圈,依靠学号来区分同学,从某一个同学(编号为a)开始数数,遇到7的倍数或者包含7的数(比如17,27),则该同学退出圈外,请求解同学们退出的顺序(用学号表示)。

2.1基本要求(1)同学的总人数n可变(10≤n≤99),开始位置a可变(1≤a≤n);(2)用两种线性表的存储结构来分别表示围成圈的同学和退出顺序。

比如,可以用循环链表或者双链表表示围成的圈,用顺序表(一位数组)来存储退出的同学学号的顺序;(3)同学的学号可以用简单1,2,3,…,M编号;(4)文档中,对算法的时间复杂度和空间复杂度进行分析,判断复杂度与n之间的关系。

(5)算法的流程图使用Visio绘制。

2.2高级要求(1)通过读取txt文件来读取学生的学号和姓名,最后的输出结果采用名单的方式显示到屏幕上;(2)用结构体存储学生的信息;(3)可以将“过七”改成“过x”,x为2~9的任意整数。

(4)程序有差错控制,能够对错误的输入参数进行提示和识别,比如总人数为负数。

3实验要求三人一组,文档完备,不得抄袭;成绩计算方法:编码50% 测试20% 文档30%4上机实验文档要求参考“实验报告模板.doc”,包含问题描述、算法思路、算法描述、源程序清单、测试结果(典型测试实例)、心得体会、分工及签名要求上交打印版,包含签名。

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

数据结构实验报告1.实验要求( 1)实验目的通过选择下面 5 个题目之一进行实现,掌握如下内容:掌握图基本操作的实现方法了解最小生成树的思想和相关概念了解最短路径的思想和相关概念学习使用图解决实际问题的能力(2)实验内容根据图的抽象数据类型的定义,使用邻接矩阵或邻接表实现一个图。

图的基本功能:1、图的建立2、图的销毁3、深度优先遍历图4、广度优先遍历图5、使用普里姆算法生成最小生成树6、使用克鲁斯卡尔算法生成最小生成树7、求指定顶点到其他各顶点的最短路径8、其他:比如连通性判断等自定义操作编写测试 main() 函数测试图的正确性2.程序分析2.1存储结构图:(1)带权值的无向图V096V12V2(2)带权值的有向图V063 94V12V2 2.2关键算法分析(1)深度优先遍历int visited[MAXSIZE]={false}; template<class T>void MGraph<T>::DFS(int v){cout<<vertex[v];visited[v]=true;for(int j=0;j<vNum;j++)if(arc[v][j]==1&&!visited[j])DFS(j);}时间复杂度: O(n2)(2)广度优先遍历int queue[MAXSIZE];int f=0,r=0;cout<<vertex[v];visit[v]=true;queue[++r]=v;while(f!=r){v=queue[++f];for(int j=0;j<vNum;j++){if(arc[v][j]==1&&!visit[j]){cout<<vertex[j];visit[j]=true;queue[++r]=j;}时间复杂度: O( n2)(3)普利姆算法int adjvex[MAXSIZE];int lowcost[MAXSIZE];int MAX=10000;template<class T>int mininum(MGraph<T> G,int a[]){int min=MAX;int k=0;for(int i=0;i<G.vNum;i++){if(a[i]!=0&&a[i]<min)//寻找 U-{V-U} 中边权值最小的顶点{min=a[i];k=i;}}return k;}template<class T>void MGraph<T>:: Prim(MGraph G){for(int i=0;i<G.vNum;i++){adjvex[i]=0;lowcost[i]=G.arcs[0][i];}lowcost[0]=0;//初始化 U={vo}for(int i=1;i<G.vNum;i++){int k=mininum(G,lowcost);//求下一个边权值最小的邻接点cout<<'V'<<adjvex[k]<<"->V"<<k<<endl;lowcost[k]=0;for(int j=0;j<G.vNum;j++){if(lowcost[j]!=0&&G.arcs[k][j]<lowcost[j]){lowcost[j]=G.arcs[k][j];adjvex[j]=k;}}}}时间复杂度: O(n2)(4)克鲁斯卡尔算法template<class T>void GenSortEdge(MGraph<T> G,VEdge E[])//获取EdgeList{int k=0,i,j;for(i=0;i<G.vNum;i++)//边赋值for(j=i;j<G.vNum;j++)if(G.arcs[i][j]!=MAX){E[k].fromV=i;E[k].endV=j;E[k].weight=G.arcs[i][j];k++;}for(i=0;i<G.arcNum-1;i++){for(j=i+1;j<G.arcNum;j++)if(E[i].weight>E[j].weight){VEdge t=E[i];E[i]=E[j];E[j]=t;}}}const int MAX_VERTEXT=20;template<class T>void MGraph<T>:: Kruskal(VEdge E[],int n,int e){int vset[MAX_VERTEXT];for(int i=0;i<n;i++) vset[i]=i;//初始化vset int k=0,j=0;while(k<n-1){int m=E[j].fromV,n=E[j].endV;int sn1=vset[m];//m int sn2=vset[n];//n if(sn1!=sn2){所属的集合所属的集合cout<<'V'<<m<<"->V"<<n<<endl;k++;for(int i=0;i<n;i++){if(vset[i]==sn2)//集合编号为sn2 的全部改为sn1 vset[i]=sn1;时间复杂度: O(n2 )(5)求最短路径,连通性判断int dist[MAXSIZE][MAXSIZE];int path[MAXSIZE][MAXSIZE];template<class T>void Floyd(MGraph<T> G){for(int i=0;i<G.vNum;i++)//寻找最短路径for(int j=0;j<G.vNum;j++){dist[i][j]=G.arcs[i][j];if(dist[i][j]!=MAX_VALUE)path[i][j]=i;elsepath[i][j]=-1;}for(int k=0;k<G.vNum;k++)for(int i=0;i<G.vNum;i++)for(int j=0;j<G.vNum;j++)if(dist[i][k]+dist[k][j]<dist[i][j])//更新迭代数组Disk[][]{dist[i][j]=dist[i][k]+dist[k][j];path[i][j]=k;}cout<<" 任意两点间的最短路径长度( 以矩阵表示): "<<endl;int l=1;for(int i=0;i<G.arcNum;i++)for(int j=0;j<G.arcNum;j++){cout<<dist[i][j]<<" ";l++;if(l>G.arcNum) {cout<<endl;l=1;}}}时间复杂度: O(n3)3.程序运行结果(1)流程图:初始化带权值的无向图深度优先遍历,广度优先遍历用普利姆算法求最小生成树用克鲁斯卡尔算法求最小生成树初始化带权值的有向图用 Floyd 算法求任意两点间最短路径,并判断连通性删除图(2)本程序所用的图带权值的无向图V096V12V2带权值的有向图V06394V12V2( 3)程序结果4.总结(1)遇到的问题:私有数据访问权的问题,在编程时应该注意(2)心得体会:通过这次实验,我掌握了图基本操作的实现方法,了解最小生成树的思想和相关概念,了解最短路径的思想和相关概念等等。

(3)改进:可以适当对某些步骤进行合并或省略,使程序更加简洁。

源代码:#include<iostream>using namespace std;const int MAXSIZE=20;const int MAX_EDGE=20;const int MAX_VALUE=1000;struct VEdge{int fromV;// int endV;// int weight;//起始顶点终止顶点边的权值};VEdge EdgeList[MAX_EDGE];template<class T>class MGraph{public:MGraph(T a[],int n,int e);MGraph(T a[],int n,int e,int h);void DFS(int v);void BFS(int v);void Prim(MGraph G);void Kruskal(VEdge E[],int n,int e);int vNum,arcNum;int arcs[MAXSIZE][MAXSIZE];//用于储存权值的数组int arc[MAXSIZE][MAXSIZE];private:T vertex[MAXSIZE];};template<class T> //构造带权值的有向图MGraph<T>::MGraph(T a[],int n,int e,int h){int i,j,k,l;vNum=n;arcNum=e;for(k=0;k<n;k++) vertex[k]=a[k];for(k=0;k<n;k++)for(j=0;j<n;j++) arc[k][j]=0;for(int i=0;i<MAXSIZE;i++){for(int j=0;j<MAXSIZE;j++){arcs[i][j]=MAX_VALUE;}}cout<<"请输入连通的两顶点下标(弧头-弧尾)及弧的权值(<1000):"<<endl;for(int i=0;i<MAXSIZE;i++){arcs[i][i]=0;}for(k=0;k<h;k++){cin>>i>>j>>l;arcs[i][j]=l;arc[i][j]=1;}}template<class T>//带权值的无向图MGraph<T>::MGraph(T a[],int n,int e){int i,j,k,l;vNum=n;arcNum=e;for(k=0;k<n;k++) vertex[k]=a[k];for(k=0;k<n;k++)for(j=0;j<n;j++) arc[k][j]=0;cout<<"请输入连通的两顶点下标及边的权值(<1000): "<<endl;for(k=0;k<e;k++){cin>>i>>j>>l;arcs[i][j]=l;arcs[j][i]=arcs[i][j];arc[i][j]=1;arc[j][i]=arc[i][j];}}//深度广度遍历int visited[MAXSIZE]={false}; template<class T>void MGraph<T>::DFS(int v){cout<<vertex[v];visited[v]=true;for(int j=0;j<vNum;j++)if(arc[v][j]==1&&!visited[j])DFS(j);}int visit[MAXSIZE]={false};template<class T>void MGraph<T>::BFS(int v){int queue[MAXSIZE];int f=0,r=0;cout<<vertex[v];visit[v]=true;queue[++r]=v;while(f!=r){v=queue[++f];for(int j=0;j<vNum;j++){if(arc[v][j]==1&&!visit[j]){cout<<vertex[j];visit[j]=true;queue[++r]=j;}}}}//普利姆算法int adjvex[MAXSIZE];int lowcost[MAXSIZE];int MAX=10000;template<class T>int mininum(MGraph<T> G,int a[]){int min=MAX;int k=0;for(int i=0;i<G.vNum;i++){if(a[i]!=0&&a[i]<min)//寻找 U-{V-U} 中边权值最小的顶点{min=a[i];k=i;}}return k;}template<class T>void MGraph<T>:: Prim(MGraph G){for(int i=0;i<G.vNum;i++){adjvex[i]=0;lowcost[i]=G.arcs[0][i];}lowcost[0]=0;//初始化 U={vo}for(int i=1;i<G.vNum;i++){int k=mininum(G,lowcost);//求下一个边权值最小的邻接点cout<<'V'<<adjvex[k]<<"->V"<<k<<endl;lowcost[k]=0;for(int j=0;j<G.vNum;j++){if(lowcost[j]!=0&&G.arcs[k][j]<lowcost[j]){lowcost[j]=G.arcs[k][j];adjvex[j]=k;}}}}//克鲁斯卡尔算法template<class T>void GenSortEdge(MGraph<T> G,VEdge E[])//获取EdgeList{int k=0,i,j;for(i=0;i<G.vNum;i++)//边赋值for(j=i;j<G.vNum;j++)if(G.arcs[i][j]!=MAX){E[k].fromV=i;E[k].endV=j;E[k].weight=G.arcs[i][j];k++;}for(i=0;i<G.arcNum-1;i++){for(j=i+1;j<G.arcNum;j++)if(E[i].weight>E[j].weight){VEdge t=E[i];E[i]=E[j];E[j]=t;}}}const int MAX_VERTEXT=20;template<class T>void MGraph<T>:: Kruskal(VEdge E[],int n,int e){int vset[MAX_VERTEXT];for(int i=0;i<n;i++) vset[i]=i;//初始化vset int k=0,j=0;while(k<n-1){int m=E[j].fromV,n=E[j].endV;int sn1=vset[m];//m int sn2=vset[n];//n if(sn1!=sn2){所属的集合所属的集合cout<<'V'<<m<<"->V"<<n<<endl;k++;for(int i=0;i<n;i++){if(vset[i]==sn2)//集合编号为sn2 的全部改为sn1 vset[i]=sn1;}}j++;}}//求最短路径//连通性判断int dist[MAXSIZE][MAXSIZE];int path[MAXSIZE][MAXSIZE];template<class T>void Floyd(MGraph<T> G){for(int i=0;i<G.vNum;i++)//寻找最短路径for(int j=0;j<G.vNum;j++){dist[i][j]=G.arcs[i][j];if(dist[i][j]!=MAX_VALUE)path[i][j]=i;elsepath[i][j]=-1;}for(int k=0;k<G.vNum;k++)for(int i=0;i<G.vNum;i++)for(int j=0;j<G.vNum;j++)if(dist[i][k]+dist[k][j]<dist[i][j])//更新迭代数组Disk[][]{dist[i][j]=dist[i][k]+dist[k][j];path[i][j]=k;}cout<<" 任意两点间的最短路径( 以矩阵表示): "<<endl;int l=1;for(int i=0;i<G.arcNum;i++)for(int j=0;j<G.arcNum;j++){cout<<dist[i][j]<<" ";l++;if(l>G.arcNum) {cout<<endl;l=1;}}}void main(){int v,e;cout<<" 请输入顶点数(<21) 和边数 (<21) :";cin>>v>>e;if(v>20||v<0||e<0||e>20)cout<<" 输入错误! "<<endl;charch[20]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'};MGraph<char> A(ch,v,e);cout<<"请输入深度优先遍历的起始顶点下标:";int s;cin>>s;cout<<" 深度优先遍历:"<<endl;A.DFS(s);cout<<endl;cout<<" 请输入广度优先遍历的起始顶点下标:";int k;cin>>k;cout<<" 广度优先遍历:"<<endl;A.BFS(k);cout<<endl;cout<<" 普利姆算法求最小生成树:"<<endl;A.Prim(A);cout<<" 克鲁斯卡尔算法求最小生成树:"<<endl;VEdge EdgeList[MAX_EDGE];GenSortEdge(A,EdgeList);A.Kruskal(EdgeList,v,e);//初始化带权值的有向图cout<<" 构造带权值的有向图,请输入弧数:";int h;cin>>h;MGraph<char> B(ch,v,e,h);Floyd(B);}。

相关文档
最新文档