⬘ 数据结构报告 ⬘
数据结构是指相互之间具有(存在)一定联系(关系)的数据元素的集合,元素之间的互相联系称为逻辑结构。数据元素的逻辑结构基本类型有四种:
集合:结构中的数据元素除了“同属于一个集合”外,没有其他关系。
数据结构在计算机内存中的存储包括数据元素的存储和元素之间的关系的表示。
元素之间的关系在计算机中有两种不同的表示方法:顺序表示和非顺序表示。由此得出两种不同的存储结构,即:顺序存储结构和链式存储结构。
顺序存储结构:用数据元素在存储器中的相对位置来表示数据元素的逻辑结构(关系)。
链式存储结构:在每一个数据元素中增加一个存放另一个元素地址的指针(pointer),用该指针来表示数据元素的逻辑结构(关系)。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌───────────┃──────────┐
┏━━━━━━━━╋━━━━━━━━━┓┏━━━━━━━╋━━━━━━━━━┓
┃ ┏╋┓ ┏╋┓ ┏━━╋━━┓ ┏━━╋━━┓
一般线性表 栈和队列 串 数组 广义表 一般树 二叉树 有向图 无向图
数据结构的主要运算包括:
是由n(n>=0)个类型相同的数据元素a1,a2....an组成的有限序列,
记作(a1,a2,...,ai-1,ai,ai+1,...,an)这里的数据元素ai(1<=i<=n)只是一个抽象的符号,其具体含义在不同情况下可以不同,它既可以是原子类型,也可也是结构类型,但同一线表中的数据元素必须属于同一数据对象。此外,线性表中相邻数据元素之间存在着序偶关系,即对于非空的线性
表(a1,a2,...,ai-1,ai,ai+1,...,an).表中ai-1,领先于ai,称ai-1是ai的直接前驱,而称ai,是ai-1的直接后续。除了第一个元素a1外,每个元素ai有且仅有一个被称为直接前驱的结点ai-1, 除了最后一个元素an外,每个元素ai有且仅有一个被称为直接后继的结点ai+1.线性表中元素的个数n被定义为线性表的长度,n=0时被称为空表。线性表的特点可以概况如下:
同一性:线性表由同类数据元素组成,每个ai必须属于同一个数据对象
有穷性:线性表由有限个数据元素组成。表长度就是表中数据元素的个数
有序性:线性表中表中相邻的数据元素之间存在着序偶关系(ai,ai+1)
由此可以看出,线性表是一种最简单的数据结构,因为数据结构之间是由一前驱一后继的直观有序的关系确定;线性表又是一种最常见的数据结构,因为矩阵,数组,字符串:堆栈,队列等都符合线性条件。
⬘ 数据结构报告 ⬘
探索数据结构的美:我的学习之路
自从我接触数据结构以来,它们一直是我学习编程的重要部分。数据结构是计算机科学的核心基础,它们定义了如何组织和存储数据,以及如何操作这些数据。在此,我想分享我从学习数据结构中获得的一些心得体会。
首先,我深深感受到数据结构与算法的精彩纷呈。数据结构不仅仅是存储和操作数据的工具,更是一种思考方式。学习数据结构,让我学会了如何运用结构化思维,将问题分解为更小的、可管理的部分。同时,算法的精妙之处也让我惊叹不已。例如,快速排序和归并排序的算法设计,让我领略到了计算机科学家们的智慧。
其次,我领悟到数据结构与算法在实践中至关重要。在学习数据结构时,我经常通过编写代码来理解概念。这种实践使我更深入地理解了数据结构的操作和性能,也让我更好地理解了数据结构背后的原理。此外,我也学会了如何优化算法,以提高程序的效率。
另外,我认识到数据结构与算法的适用性。每种数据结构都有其独特的用途和适用场景。例如,堆是一种高效的优先级排序数据结构,而链表则在插入和删除操作上表现出色。了解各种数据结构的特性和适用场景,有助于我根据问题的需求选择最合适的数据结构。
最后,我发现学习数据结构是一个持续的过程。数据结构与算法是不断发展和演化的,我时常需要更新我的知识库,以适应新的变化和挑战。这种持续的学习使我始终保持对数据结构的敏感和探索欲望。
总的来说,学习数据结构让我受益良多。我不仅学会了如何更好地解决问题,也锻炼了我的逻辑思维和编程技巧。我相信,在未来的学习和工作中,我会继续探索数据结构的世界,发现更多的美。
⬘ 数据结构报告 ⬘
数据结构报告
引言:
数据结构是计算机科学中的一门重要课程,它研究如何组织和存储数据,以便在计算机中高效地操作和处理。数据结构对于计算机科学的发展和应用起着至关重要的作用。本报告将详细介绍数据结构的相关主题,包括数组、链表、栈、队列和树等。
一、数组
数组是一种线性数据结构,它由相同类型的元素组成,并按照一定的顺序存储在内存中。数组提供了按下标随机访问元素的能力,具有快速读取和修改元素的特点。本节将介绍数组的定义、基本操作及其在实际应用中的使用。
二、链表
链表是另一种常见的线性数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。与数组相比,链表的插入和删除操作更加灵活,但访问元素时需要遍历整个链表。本节将介绍链表的分类、基本操作以及它在实际应用中的应用场景。
三、栈
栈是一种具有特殊操作规则的线性数据结构,它遵循先进后出(Last In First Out,LIFO)的原则。栈主要包含入栈和出栈两个基本操作,可以用于实现简单的计算器、函数调用等。本节将介绍栈的定义、基本操作以及它在计算机系统中的应用。
四、队列
队列是一种具有特殊操作规则的线性数据结构,它遵循先进先出(First In First Out,FIFO)的原则。队列主要包含入队和出队两个基本操作,可以用于实现线程池、消息队列等。本节将介绍队列的定义、基本操作以及它在实际应用中的使用。
五、树
树是一种非线性的数据结构,由节点和边组成,节点之间存在层次关系。树具有层次性、唯一根节点和子树的递归结构等特点。树的应用非常广泛,比如文件系统、数据库索引和图像压缩等。本节将介绍树的定义、基本概念以及常见的树结构和它们的应用场景。
六、总结
数据结构是计算机科学的基础,它为我们提供了有效存储和操作数据的方法。通过本报告的详细介绍,我们了解了数组、链表、栈、队列和树等常见的数据结构,以及它们在实际应用中的使用场景。在实际开发中,根据不同的问题需求选择合适的数据结构非常重要,只有熟练掌握数据结构的原理和应用,才能更高效地解决实际问题。
参考文献:
1.《数据结构与算法分析- C语言描述》
2.《数据结构与算法分析- Java语言描述》
3.《Introduction to Algorithms》
附录:数据结构相关算法代码实现及其测试用例
⬘ 数据结构报告 ⬘
1、世界上公认的第一台电子计算机诞生的年代是( 20世纪40年代)
2、20GB的硬盘表示容量约为( 200亿个字节)
3、在微机中,西文字符所采用的编码是( ASCII码)
4、计算机安全是指计算机资产安全,即(计算机信息系统和信息不受自然和人为有害因素威胁和危害)
5、度量计算机运算速度常用的单位是( MIPS)
6、下列设备组中,完全属于计算机输出设备的一组是( 打印机,绘图仪,显示器)
7、计算机操作系统的主要功能是(管理计算机系统的软硬件资源,以充分发挥计算机资源的效率,并为其他软件提供良好的运行环境)
8、计算机软件的确切含义是(计算机程序、数据与相应文档的总称)
9、下列关于计算机病毒的叙述中,错误的是(感染计算机病毒的计算机具有对该病毒的免疫性)
10、在一个非零无符号二进制整数之后添加一个0,则此数的值为原数的( 2倍)
11、以下关于编译程序的说法正确的是( 编译程序完成高级语言程序到低级语言程序的等价翻译)
12、用高级程序设计语言编写的程序(具有良好的可读性和可移植性)
13、一个完整的计算机系统的组成部分的确切提法应该是(计算机硬件和软件 )
14、运算器的完整功能是进行( 算术运算和逻辑运算)
15、计算机网络最突出的优点是(资源共享和快速传输信息)
16、以太网的拓扑结构(总线型)
17、能直接与CPU交换信息的存储器是(内存储器)
18、正确的IP地址是( 202.112.111.1)
19、上网需要在计算机上安装( 浏览器软件)
20、世界上公认的第一台电子计算机诞生在( 美国 )
⬘ 数据结构报告 ⬘
北京邮电大学信息与通信工程学院
2009级数据结构实验报告
实验名称: 实验三哈夫曼编/解码器的实现
学生姓名:陈聪捷
日 期: 2010年11月28日
1.实验要求
一、实验目的:
了解哈夫曼树的思想和相关概念;
二、实验内容:
利用二叉树结构实现哈夫曼编/解码器
1.初始化:能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树。
2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。
3.编码:根据编码表对输入的字符串进行编码,并将编码后的字符串输出。
4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。
5.打印:以直观的方式打印哈夫曼树。
6.计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。
7.用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。
2. 程序分析
2.1 存储结构
二叉树
template
class BiTree
{
public:
BiTree(); //构造函数,其前序序列由键盘输入
~BiTree(void); //析构函数
BiNode* Getroot(); //获得指向根结点的指针
protected:
BiNode *root; //指向根结点的头指针
};
//声明类BiTree及定义结构BiNode
Data:
二叉树是由一个根结点和两棵互不相交的左右子树构成
data:
HCode* HCodeTable;//编码表
int tSize; //编码表中的总字符数
二叉树的节点结构
template
struct BiNode //二叉树的结点结构 {
T data; //记录数据
T lchild; //左孩子
T rchild; //右孩子
T parent; //双亲
};
编码表的节点结构
struct HCode
{
char data; //编码表中的字符
char code[100]; //该字符对应的编码
};
待编码字符串由键盘输入,输入时用链表存储,链表节点为 struct Node
{
char character; //输入的字符
unsigned int count;//该字符的权值
bool used; //建立树的时候该字符是否使用过
Node* next; //保存下一个节点的地址
};
示意图:
2.2 关键算法分析
1.初始化函数(void HuffmanTree::Init(string Input))
算法伪代码:
1.初始化链表的头结点
2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n记录的是链表
中字符的个数)
3.从字符串第2个字符开始,逐个取出字符串中的字符
3.1 将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出
的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。
3.2 如果当前取出的字符与链表中已经存在的字符都不相同,则将其加入
到链表尾部,同时n++
4.tSize=n(tSize记录链表中字符总数,即哈夫曼树中叶子节点总数)
5.创建哈夫曼树
6.销毁链表
源代码:
void HuffmanTree::Init(string Input)
{
Node *front=new Node; //初始化链表的头结点
if(!front)
throw exception("堆空间用尽");
front->next=NULL;
front->character=NULL;
front->count=0;
Node *pfront=front;
char ch=Input[0]; //获得第一个字符
Node* New1=new Node;
if(!New1)
throw exception("堆空间用尽");
New1->character=ch; //将第一个字符插入链表
New1->count=1;
New1->next=pfront->next;
pfront->next=New1;
bool replace=0; //判断在已经写入链表的字符中是否有与当前读出的字符相同的字符 int n=1; //统计链表中字符个数
for(int i=1;i
{
ch=Input[i]; //获得第i个字符
do
{
pfront=pfront->next;
if((int)pfront->character == (int)ch) //如果在链表中有与当前字符相同的字符,
该字符权值加1
{
pfront->count++;
replace=1;
break;
}
}while(pfront->next);
if(!replace) //如果在链表中没找到与当前字符相同的字符,则将该字符作为新成 员插入链表
{
Node* New=new Node;
if(!New)
throw exception("堆空间用尽");
New->character=ch;
New->count=1;
New->next=pfront->next;
pfront->next=New;
n++;
}
pfront=front; //重置pfront和replace变量为默认值 replace=0;
}
tSize=n; //tSize记录的是编码表中字符个数
CreateHTree(front,n); //创建哈夫曼树
pfront=front;
while(pfront) //销毁整个链表
{
front=pfront;
pfront=pfront->next;
front;
}
时间复杂度:
若输入的字符串长度为n,则时间复杂度为O(n)
2.创建哈夫曼树(void HuffmanTree::CreateCodeTable(Node *p))
算法伪代码:
1. 创建一个长度为2*tSize-1的三叉链表
2. 将存储字符及其权值的链表中的字符逐个写入三叉链表的前tSize个结点
的data域,并将对应结点的孩子域和双亲域赋为空
3. 从三叉链表的第tSize个结点开始,i=tSize
3.1 从存储字符及其权值的.链表中取出两个权值最小的结点x,y,记录其
下标x,y。
3.2 将下标为x和y的哈夫曼树的结点的双亲设置为第i个结点
3.3 将下标为x的结点设置为i结点的左孩子,将下标为y的结点设置为
i结点的右孩子,i结点的权值为x结点的权值加上y结点的权值,i
结点的双亲设置为空
4. 根据哈夫曼树创建编码表
源代码:
void HuffmanTree::CreateHTree(Node *p,int n)
{
root= new BiNode[2*n-1]; //初始化哈夫曼树
Node *front=p->next;
if(n==0)
throw exception("没有输入字符");
for(int i=0;i
root[i].data=front->count;
root[i].lchild=-1;
root[i].rchild=-1;
root[i].parent=-1;
front=front->next;
}
front=p;
int New1,New2;
for(i=n;i<2*n-1;i++)
{
SelectMin(New1,New2,0,i); //从0~i中选出两个权值最小的结点
root[New1].parent=root[New2].parent=i; //用两个权值最小的结点生成新结点,
新节点为其双亲
root[i].data=root[New1].data+root[New2].data;//新结点的权值为其孩子的权值的和 root[i].lchild=New1;
root[i].rchild=New2;
root[i].parent=-1;
}
CreateCodeTable(p); //创建编码表
}
时间复杂度:
在选取两个权值最小的结点的函数中要遍历链表,时间复杂度为O(n),故该函数
的时间复杂度为O(n^2)
3.创建编码表(void HuffmanTree::CreateCodeTable(Node *p))
算法伪代码:
1.初始化编码表
2.初始化一个指针,从链表的头结点开始,遍历整个链表
2.1 将链表中指针当前所指的结点包含的字符写入编码表中
2.2 得到该结点对应的哈夫曼树的叶子结点及其双亲
2.3 如果哈夫曼树只有一个叶子结点,将其字符对应编码设置为0
2.4 如果不止一个叶子结点,从当前叶子结点开始判断
2.4.1 如果当前叶子结点是其双亲的左孩子,则其对应的编码为0,否
则为1
2.4.2 child指针指向叶子结点的双亲,parent指针指向child指针的双亲,
重复2.4.1的操作
2.5 将已完成的编码倒序
2.6 取得链表中的下一个字符
3.输出编码表
源代码:
void HuffmanTree::CreateCodeTable(Node *p)
{
HCodeTable=new HCode[tSize]; //初始化编码表
Node *front=p->next;
for(int i=0;i
{
HCodeTable[i].data=front->character; //将第i个字符写入编码表
int child=i; //得到第i个字符对应的叶子节点
int parent=root[i].parent; //得到第i个字符对应的叶子节点的双亲
int k=0;
if(tSize==1) //如果文本中只有一种字符,它的编码为0
{
HCodeTable[i].code[k]='0';
k++;
}
while(parent!=-1) //从第i个字符对应的叶子节点开始,寻找它到根结点的路径
{
if(child==root[parent].lchild) //如果当前结点为双亲的左孩子,则编码为0,
否则编码为1
HCodeTable[i].code[k]='0';
else
HCodeTable[i].code[k]='1';
k++;
child=parent;
parent=root[child].parent;
}
HCodeTable[i].code[k]='';
Reverse(HCodeTable[i].code); //将编码逆置
front=front->next; //得到下一个字符
}
cout<<"编码表为:"<
for(i=0;i
{
cout<
parent=root[parent].lchild;
else //编码为1则寻找右孩子
parent=root[parent].rchild;
i++;
}
if(tSize==1) //如果编码表只有一个字符,则根结点即为叶子结点 i++;
d.append(1,HCodeTable[parent].data);//将叶子节点对应的字符追加到解码串中 }
cout<
}
时间复杂度:
设待解码串长度为n,则复杂度为O(n)
8. 计算哈夫曼编码的压缩比(void HuffmanTree::Calculate(string s1,string s2)) 算法伪代码:
1. 获得编码前字符串的长度,即其占用的字节数
2. 获得编码后的字符串的长度,将其除以8然后向上取整,得到其占用的字
节数
3. 压缩比将两个相除
源代码:
void HuffmanTree::Calculate(string s1,string s2)
{
int cal1=s1.length();
int cal2=s2.length();
cal2=ceill((float)cal2/8); //将编码串的比特数转化为字节数 cout<<"编码前的字符串长度:"<
cout<<"编码后的字符串长度:"<
cout<<"压缩比为:"<<((double)cal2/(double)cal1)*100<<"%"<
}
时间复杂度:
O(1)
9. 打印哈夫曼树(void HuffmanTree::PrintTree(int TreeNode,int layer) ) 算法伪代码:
1. 如果待打印结点为空,则返回
2. 递归调用函数打印当前结点的右子树
3. 根据当前结点所在的层次确定其前面要输出多少空格,先输出空格,在打
印当前结点的权值
4. 递归调用函数打印当前结点的左子树
源代码:
void HuffmanTree::PrintTree(int TreeNode,int layer)
{
if(TreeNode==-1) //如果待打印结点为空,则返回 return;
else
{
PrintTree(root[TreeNode].rchild,layer+1); //先打印该结点的右子树,layer记录
的是该结点所在的层次
for(int i=0;i
空格
cout<<' ';
cout<
PrintTree(root[TreeNode].lchild,layer+1); //打印该结点的左子树
}
}
时间复杂度:
中序遍历哈夫曼树,复杂度为O(n)
10. 菜单函数(void HuffmanTree::Menu())
算法伪代码:
1. 逐一读取键盘缓存区中的字符,并将它们逐一追加到记录输入字符串的
string变量中,直到读到回车输入符为止
2. 删除string变量末尾的回车输入符
3.利用string变量创建哈夫曼树,初始化编码表。
4. 直观打印哈夫曼树
5. 对输入的字符串进行编码
6. 对编码后的字符串进行解码
7. 计算编码前后的压缩比并输出
源代码:
void HuffmanTree::Menu()
{
cout<<"请输入你要编码的文本,按回车键确定输入"<
string Input;
char letter;
do //将字符逐个读入Input变量中
{
letter=cin.get();
Input.append(1,letter);
}while(letter!=' ');
Input.erase(Input.length()-1,1); //去掉Input末尾的回车符
Init(Input); //根据输入的字符串创建哈夫曼树及其编码表 cout<<"直观打印哈夫曼树"<
PrintTree(2*tSize-1-1,1); //打印哈夫曼树
cout<<' '<<' ';
string d1,d2;
cout<<"编码后的字符串为"<
Encode(Input,d1); //编码并打印编码串
cout<<"解码后的字符串为"<
Decode(d1,d2); //解码并打印解码串
cout<<"ASCII码编码与HUFFMAN编码的比较"<
Calculate(Input,d1); //计算编码前后的压缩比
}
2.3 其他
1.由于题目要求能输入任意长的字符串,所以本程序采用了string变量来记录输入
的字符串,并采用string类的类成员函数来完成各项任务
2.打印哈夫曼树时采用了递归函数,且采用了凹凸表的形式打印哈夫曼树。
3.为了输入空格,输入时采取逐个字符输入的方式
3. 程序运行结果
主函数流程图:
运行结果:
各函数运行正常,没有出现bug
4. 总结
经过这次实验,我了解了哈夫曼树的创建过程,了解了一种不等长编码的方法,用设断点调试的方法更加熟练,同时熟悉了STL中string类型的用法,对C++更加熟悉
⬘ 数据结构报告 ⬘
《数据结构与算法》实验报告
专业 班级 姓名 学号
实验项目
实验一 二叉树的应用
实验目的
1、进一步掌握指针变量的含义及应用。
2、掌握二叉树的结构特征,以及各种存储结构的特点及使用范围。
访问和处理二叉树的运算。
实验内容
题目1:编写一个程序,采用一棵二叉树表示一个家谱关系。要求程序具有如下功能:
(1)用括号表示法输出家谱二叉树,
(2)查找某人的所有儿子,
(3)查找某人的所有祖先。
算法设计分析
(一)数据结构的定义
为了能够用二叉树表示配偶、子女、兄弟三种关系,特采用以下存储关系,则能在二叉树上实现家谱的各项运算。
二叉树型存储结构定义为:
typedef struct SNODE
{char name[MAX]; //人名
struct SNODE *left;//指向配偶结点
struct SNODE *right; //指向兄弟或子女结点
}FNODE;
(二)总体设计
实验由主函数、家谱建立函数、家谱输出函数、儿子查找函数、祖先查找函数、结点定位函数、选择界面函数七个函数共同组成。其功能描述如下:
(1)主函数:统筹调用各个函数以实现相应功能
void main()
(2)家谱建立函数:与用户交互建立家族成员对应关系
void InitialFamily(FNODE *&head) //家谱建立函数
(3)家谱输出函数:用括号表示法输出家谱
输出形式为:父和母(子,子)
void PrintFamily(FNODE *head) //家谱输出函数
(4)儿子查找函数:在家谱中查找到某人所有的子女并输出,同时也能辨别出其是否为家族成员与是否有子女
void FindSon(FNODE *b,char p[]) //儿子查找函数
(5)祖先查找函数:在家谱中查找到某人所有的祖先并输出,同时也能辨别出其是否为家族中成员。
int FindAncestor(FNODE *head,char son[ ]) //祖先查找函数
(6)结点定位函数:在家谱中找到用户输入人名所对应的结点。
FNODE *findnode(FNODE *b,char p[]) //结点定位函数
(7)选择界面函数:为便于编写程序,将用户选择部分独立为此函数。
void PRINT(int &n)
(三)各函数的详细设计:
void InitialFamily(FNODE *&head) //家谱建立函数
1:首先建立当前人的信息,将其左右结点置为空,
2:然后让用户确定其是否有配偶,如果没有配偶,则当前程序结束,
3:如果有则建立其配偶信息,并将配偶结点赋给当前人的左结点;
4:再让用户确定其是否有子女,如果有则递归调用家谱建立函数建立子女结点,并将其赋给配偶结点的下一个右结点。
5:如无,则程序结束
void PrintFamily(FNODE *head) //家谱输出函数
1:首先判断当前结点是否为空,如果为空则结束程序;
2:如果不为空,则输出当前结点信息,
是否为空,如不为空则输出“和配偶信息。
”;
是否为空
6:如果不为空,则输出“,”,并递归调用输出兄弟信息
7程序结束
FNODE *findnode(FNODE *b,char p[]) //结点定位函数
1:当前结点是否为空,为空则返回空;
2:如果和查找信息相同,则返回当前结点;
3:如不然,则先后递归访问其左结点,再不是则递归访问右结点
void FindSon(FNODE *b,char p[]) //儿子查找函数
1:在家谱中定位到要查找的结点,如无则输出“查找不到此人”
2:判断其配偶结点与子女结点是否为空,为空则输出“无子女”
。
int FindAncestor(FNODE *head,char son[ ]) //祖先查找函数
1:先在家谱中定位到要查找的结点,如为空输出“不存在此人”,程序结束
2:先将父母结点入栈,当栈为空时程序结束,
3:栈不为空时,判断栈顶元素是否已访问过,
4:访问过,再判断是否为查找结点,如是则输出栈中保存的其祖先结点,并滤过其兄弟结点不输出;不是查找结点,则退栈一个元素
5:未访问过,则取当前栈顶元素,置访问标志——1,同时取其右结点
6:栈不为空或当前所取结点不为空时,转到2;
实验测试结果及结果分析
(一)测试结果
(二)结果分析
⬘ 数据结构报告 ⬘
摘要:大数据和智游都是当下的热点,没有大数据的智游无从谈“智慧”,数据挖掘是大数据应用于智游的核心,文章探究了在智游应用中,目前大数据挖掘存在的几个问题。
随着人民生活水平的进一步提高,旅游消费的需求进一步上升,在云计算、互联网、物联网以及移动智能终端等信息通讯技术的飞速发展下,智游应运而生。大数据作为当下的热点已经成了智游发展的有力支撑,没有大数据提供的有利信息,智游无法变得“智慧”。
旅游业是信息密、综合性强、信息依存度高的产业[1],这让其与大数据自然产生了交汇。,江苏省镇江市首先提出“智游”的概念,虽然至今国内外对于智游还没有一个统一的学术定义,但在与大数据相关的描述中,有学者从大数据挖掘在智游中的作用出发,把智游描述为:通过充分收集和管理所有类型和来源的旅游数据,并深入挖掘这些数据的潜在重要价值信息,然后利用这些信息为相关部门或对象提供服务[2]。这一定义充分肯定了在发展智游中,大数据挖掘所起的至关重要的作用,指出了在智游的过程中,数据的收集、储存、管理都是为数据挖掘服务,智游最终所需要的是利用挖掘所得的有用信息。
,我国提出用十年时间基本实现智游的目标[3],过去几年,国家旅游局的相关动作均为了实现这一目标。但是,在借助大数据推动智游的可持续性发展中,大数据所产生的价值却亟待提高,原因之一就是在收集、储存了大量数据后,对它们深入挖掘不够,没有发掘出数据更多的价值。
智游的发展离不开移动网络、物联网、云平台。随着大数据的不断发展,国内许多景区已经实现Wi—Fi覆盖,部分景区也已实现人与人、人与物、人与景点之间的实时互动,多省市已建有旅游产业监测平台或旅游大数据中心以及数据可视化平台,从中进行数据统计、行为分析、监控预警、服务质量监督等。通过这些平台,已基本能掌握跟游客和景点相关的数据,可以实现更好旅游监控、产业宏观监控,对该地的旅游管理和推广都能发挥重要作用。
但从智慧化的发展来看,我国的信息化建设还需加强。虽然通讯网络已基本能保证,但是大部分景区还无法实现对景区全面、透彻、及时的感知,更为困难的是对平台的建设。在数据共享平台的建设上,除了必备的硬件设施,大数据实验平台还涉及大量部门,如政府管理部门、气象部门、交通、电子商务、旅行社、旅游网站等。如此多的部门相关联,要想建立一个完整全面的大数据实验平台,难度可想而知。
大数据时代缺的不是数据,而是方法。大数据在旅游行业的应用前景非常广阔,但是面对大量的数据,不懂如何收集有用的数据、不懂如何对数据进行挖掘和利用,那么“大数据”犹如矿山之中的废石。旅游行业所涉及的结构化与非结构化数据,通过云计算技术,对数据的收集、存储都较为容易,但对数据的'挖掘分析则还在不断探索中。大数据的挖掘常用的方法有关联分析,相似度分析,距离分析,聚类分析等等,这些方法从不同的角度对数据进行挖掘。其中,相关性分析方法通过关联多个数据来源,挖掘数据价值。但针对旅游数据,采用这些方法挖掘数据的价值信息,难度也很大,因为旅游数据中冗余数据很多,数据存在形式很复杂。在旅游非结构化数据中,一张图片、一个天气变化、一次舆情评价等都将会对游客的旅行计划带来影响。对这些数据完全挖掘分析,对游客“行前、行中、行后”大数据的实时性挖掘都是很大的挑战。
,数据安全事件屡见不鲜,伴着大数据而来的数据安全问题日益凸显出来。在大数据时代,无处不在的数据收集技术使我们的个人信息在所关联的数据中心留下痕迹,如何保证这些信息被合法合理使用,让数据“可用不可见”[4],这是亟待解决的问题。同时,在大数据资源的开放性和共享性下,个人隐私和公民权益受到严重威胁。这一矛盾的存在使数据共享程度与数据挖掘程度成反比。此外,经过大数据技术的分析、挖掘,个人隐私更易被发现和暴露,从而可能引发一系列社会问题。
大数据背景下的旅游数据当然也避免不了数据的安全问题。如果游客“吃、住、行、游、娱、购”的数据被放入数据库,被完全共享、挖掘、分析,那游客的人身财产安全将会受到严重影响,最终降低旅游体验。所以,数据的安全管理是进行大数据挖掘的前提。
大数据背景下的智游离不开人才的创新活动及技术支持,然而与专业相衔接的大数据人才培养未能及时跟上行业需求,加之创新型人才的外流,以及数据统计未来3~5年大数据行业将面临全球性的人才荒,国内智游的构建还缺乏大量人才。
在信息化建设上,加大政府投入,加强基础设施建设,整合结构化数据,抓取非结构化数据,打通各数据壁垒,建设旅游大数据实验平台;在挖掘方法上,对旅游大数据实时性数据的挖掘应该被放在重要位置;在数据安全上,从加强大数据安全立法、监管执法及强化技术手段建设等几个方面着手,提升大数据环境下数据安全保护水平。加强人才的培养与引进,加强产学研合作,培养智游大数据人才。
[1]翁凯.大数据在智游中的应用研究[J].信息技术,2015,24:86-87.
[2]梁昌勇,马银超,路彩虹.大数据挖掘,智游的核心[J].开发研究,2015,5(180):134-139.
[3]张建涛,王洋,刘力刚.大数据背景下智游应用模型体系构建[J].企业经济,2017,5(441):116-123.
[4]王竹欣,陈湉.保障大数据,从哪里入手?[N].人民邮电究,2017-11-30.
⬘ 数据结构报告 ⬘
一.实验内容:
实现哈夫曼编码的生成算法。
二.实验目的:
1、使学生熟练掌握哈夫曼树的生成算法。
2、熟练掌握哈夫曼编码的方法。
三.问题描述:
已知n个字符在原文中出现的频率,求它们的哈夫曼编码。
1、读入n个字符,以及字符的权值,试建立一棵Huffman树。
2、根据生成的Huffman树,求每个字符的Huffman编码。并对给定的待编码字符序列进行编码,并输出。
四.问题的实现
(1)郝夫曼树的存储表示
typedef struct{
unsigned int weight;
unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree; //动态分配数组存储郝夫曼树
郝夫曼编码的存储表示
typedef char* *HuffmanCode;//动态分配数组存储郝夫曼编码
(2)主要的实现思路:
a.首先定义郝夫曼树的存储形式,这里使用了数组
b.用select()遍历n个字符,找出权值最小的两个
c.构造郝夫曼树HT,并求出n个字符的郝夫曼编码HC
总结
1.基本上没有什么太大的问题,在调用select()这个函数时,想把权值最小的两个结点的'序号带回HuffmanCoding(),所以把那2个序号设置成了引用。
2.在编程过程中,在什么时候分配内存,什么时候初始化花的时间比较长
3.最后基本上实现后,发现结果仍然存在问题,经过分步调试,发现了特别低级的输入错误。把HT[i].weight=HT[s1].weight+HT[s2].weight;中的s2写成了i
附:
//动态分配数组存储郝夫曼树
typedef struct{
int weight; //字符的权值
int parent,lchild,rchild;
}HTNode,*HuffmanTree;
//动态分配数组存储郝夫曼编码
typedef char* *HuffmanCode;
//选择n个(这里是k=n)节点中权值最小的两个结点
void Select(HuffmanTree &HT,int k,int &s1,int &s2)
{ int i;
i=1;
while(i<=k && HT[i].parent!=0)i++;
//下面选出权值最小的结点,用s1指向其序号
s1=i;
for(i=1;i<=k;i++)
{
if(HT[i].parent==0&&HT[i].weight
}
//下面选出权值次小的结点,用s2指向其序号
for(i=1;i<=k;i++)
{
if(HT[i].parent==0&&i!=s1)break;
}
s2=i;
for(i=1;i<=k;i++)
{
if(HT[i].parent==0&&i!=s1&&HT[i].weight
}
}
//构造Huffman树,求出n个字符的编码
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
{
int m,c,f,s1,s2,i,start;
char *cd;
if(n<=1)return;
m=2*n-1; //n个叶子n-1个结点
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); //0号单元未用,预分配m+1个单元
HuffmanTree p=HT+1;
w++; //w的号单元也没有值,所以从号单元开始
for(i=1;i<=n;i++,p++,w++)
{
p->weight=*w;
p->parent=p->rchild=p->lchild=0;
}
for(;i<=m;++i,++p)
{
p->weight=p->parent=p->rchild=p->lchild=0;
}
for(i=n+1;i<=m;i++)
{
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;
}
//从叶子到根逆向求每个字符的郝夫曼编码
HC=(HuffmanCode)malloc((n+1)*sizeof(char*)); //分配n个字符编码的头指针变量
cd=(char*)malloc(n*sizeof(char)); //分配求编码的工作空间
cd[n-1]='';//编码结束符
for(i=1;i<=n;i++) //逐个字符求郝夫曼编码
{
start=n-1; //编码结束符位置
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent) //从叶子到根逆向求编码
{
if(HT[f].lchild==c)cd[--start]='0';
else
cd[--start]='1';
}
HC[i]=(char*)malloc((n-start)*sizeof(char)); //为第i个字符编码分配空间
strcpy(HC[i],&cd[start]);//从cd复制编码到HC
}
free(cd); //释放工作空间
}
void main()
{ int n,i;
int* w; //记录权值
char* ch; //记录字符
HuffmanTree HT;
HuffmanCode HC;
cout<<"请输入待编码的字符个数n=";
cin>>n;
w=(int*)malloc((n+1)*sizeof(int)); //记录权值,号单元未用
ch=(char*)malloc((n+1)*sizeof(char));//记录字符,号单元未用
cout<<"依次输入待编码的字符data及其权值weight"<
for(i=1;i<=n;i++)
{
cout<<"data["<
⬘ 数据结构报告 ⬘
数据结构报告
数据结构是计算机科学中的关键概念,它对于计算机程序的设计和性能有重要影响。在本报告中,我们将探讨数据结构的基本概念、常见的数据结构类型以及它们的应用。
一、数据结构的基本概念
数据结构是指组织和存储数据的方式,它可以影响程序的运行效率和内存占用。数据结构主要包括以下几个基本概念:
1.数据元素:数据结构中的最小单位,也可以是一个单独的数据项。
2.数据项:数据元素中的不可分割的最小单位,通常是一个数据项与一个值相关联。
3.字段:数据元素中的一个数据项,可以是数据的一部分或者整个数据。
4.记录:一组字段的集合,可以看作是一个结构化数据元素。
5.文件:一组记录的集合,可以看作是一种逻辑上的存储方式。
二、常见的数据结构类型
1.线性结构
线性结构是最基本的数据结构之一,它包括线性表、栈和队列。线性表是一种有序的数据元素集合,其特点是数据元素之间存在一对一的关系。栈是一种限定在表尾进行插入和删除操作的线性表,遵循"后进先出"的原则。队列是一种限定在表头进行删除操作,在表尾进行插入操作的线性表,遵循"先进先出"的原则。
2.非线性结构
非线性结构包括树和图。树是由结点和边组成的集合,每个结点都有零个或多个子结点,且没有父结点的结点称为根结点。图是由结点和边组成的集合,结点之间的关系可以是任意的。
3.文件结构
文件结构是将数据组织成一种可供存储和访问的格式。常见的文件结构包括顺序文件、索引文件和散列文件。顺序文件是按照数据的逻辑顺序进行存储的文件,可以快速进行顺序查找。索引文件是通过建立索引来加速查找操作的文件,索引通常是一个键值对的集合。散列文件是通过散列函数将数据映射到存储位置进行存储和查找的文件。
三、数据结构的应用
数据结构在计算机科学的各个领域都有广泛的应用。以下是一些常见的应用场景:
1.数据库管理系统:数据库管理系统使用索引文件和散列文件等数据结构来存储和管理大量的数据。
2.图像处理:图像处理中的像素数据通常以数组的形式进行存储和处理。
3.路由算法:路由算法使用图数据结构来描述网络拓扑,并通过算法找到最佳的路由路径。
4.算法设计:在算法设计中,很多问题可以使用适当的数据结构来提高算法的效率。
总结:
数据结构是计算机科学中的核心概念,它对于程序的设计和性能有重要影响。通过了解和掌握不同类型的数据结构,我们可以选择适合的数据结构来存储和访问数据,提高程序的运行效率和内存占用。在实际应用中,数据结构被广泛用于数据库管理系统、图像处理、路由算法和算法设计等领域。
⬘ 数据结构报告 ⬘
21、在计算机中,组成一个字节的二进制位位数是( 8 )。
22、下列关于ASCII编码的叙述中,正确的是( 所有大写英文字母的ASCII码值都大于小写英文字母‘a’的ASCⅡ码值)
23、下列选项属于“计算机安全设置”的是( 停掉Guest账号 )。
24、CPU主要技术性能指标有( 字长、主频和运算速度 )。
25、下列设备组中,完全属于输入设备的一组是( 绘图仪,键盘,鼠标器 )
26、计算机系统软件中,最基本、最核心的软件是( 操作系统 )。
27、下列软件中,属于系统软件的是( Windows Vista )。
28、下列关于计算机病毒的叙述中,正确的是( 反病毒软件必须随着新病毒的出现而升级,提高查、杀病毒的功能 )。
29、如果删除一个非零无符号二进制偶整数后的2个O,则此数的值为原数( 1/4 )
30、高级程序设计语言的特点是( 高级语言数据结构丰富 )。
31、计算机硬件能直接识别、执行的语言是( 机器语言 )
32、计算机的系统总线是计算机各部件间传递信息的公共通道,它分(数据总线、控制总线和地址总线)。
33、微机硬件系统中最核心的部件是( CPU )
34、用“综合业务数字网”(又称“一线通”)接人因特网的优点是上网通话两不误,它的英文缩写是(ISDN)
35、当电源关闭后,下列关于存储器的说法中,正确的是(存储在ROM中的数据不会丢失 )
36、计算机指令由两部分组成,它们是(操作码和操作数)
37、有一域名为bit. edu. cn,根据域名代码的规定,此域名表示(教育机构)。
38、能保存网页地址的文件夹是( 收藏夹 )
39、按电子计算机传统的分代方法,第一代至第四代计算机依次是(电子管计算机,晶体管计算机、小、中规模集成电路计算机,大规模和超大规模集成电路计算机)
40、假设某台式计算机的内存储器容量为256MB,硬盘容量为40GB,硬盘的容量是内在容量的(160倍)
⬘ 数据结构报告 ⬘
1.属性与服务相同的对象构成类,类中的每个对象称为该类的一——·
2.在类的继承结构中,位于上层的类叫做一——,其下层的类则 叫做 类.
3.若设串S=“documentHash.doc\O”,则诙字符串S的长度为——·
4.线性表的链接存储只能通过—————————顺序访问。
5.设链栈中结点的结构为(data,link),栈顶 指针为top,则向该链栈插入、—个新结点*p
时,应依次执行—————————————和一————操作。
6.广义表的深度定义为广义表中括号被嵌套的——一·
7.在一棵高度为h的完全二又树中,最少含有——个结点.假定树根结点的高度为O.
8.从有序击(12,10,30,43,56,78,02,95)中折半搜索56和98元素时,其搜索长度分别为——和——·
9。n个(n>o)顶点的连通无向图中各顶点的度之和最少为————·
10.设图的顶点数为n,则求解最短路径的Dijkstra算法的时间复杂度为————·
11.给定一组数据对象的关键码为{46,79,56,38,40,84},则利用堆排序方法建立的初始最大堆的堆首和堆尾的关键码分别为——和——·L2.在索引表中,着一个索引项对应数据对象表中的一个表项,0C称此索引为稠密索引
若对应数据对象表中的若干表项,则称此索引为——一索引.
答案
1.实例
2.基类 派生(或于类)
3. 16
4.链接指针
5.p一>Link=top top=p
6.重数
7.2h
8. 3 2
9.2(n-1)
10。O(n2)
11.84 46
12。稀疏
⬘ 数据结构报告 ⬘
数据结构练习试题
一、单项选择题
1.关系数据模型的三个组成部分中,不包括( C )
A.完整性规则 B.数据结构 C.恢复D.数据操作
2. 五种基本关系代数运算是 ( A )
A. ∪,-,×,π和σ B. ∪,-,∞,π和σ
C. ∪,∩,×,π和σ D. ∪,∩,∞,π和σ
3.公司中有多个部门和多名职员,每个职员只能属于一个部门。一个部门可以有多名职员,从部门到职员的联系类型是( D )
A.多对多 B.一对一 C.多对一 D.一对多
4.关系代数表达式的优化策略中,首先要做的是( B )
A.对文件进行预处理 B.尽早执行选择运算
C.执行笛卡儿积运算 D.投影运算
5.下列四项中,不属于关系数据库特点的是( D )
A.数据冗余小 B.数据独立性高 C.数据共享性好 D.多用户访问
6. 下列聚合函数中不忽略空值 (null) 的是( C )
A. SUM (列名) B. MAX (列名) C. COUNT ( * ) D. AVG (列名)
7.SQL语言中,修改表结构的语句是( D )。
A、CREATE B、SELECT C、UPDATE D、ALTER
8.下列四项中说法不正确的是( C ) 共四页第二页
A.数据库减少了数据冗余 B.数据库中的数据可以共享
C.数据库避免了一切数据的重复 D.数据库具有较高的数据独立性
9.在关系数据库系统中,为了简化用户的查询操作。而又不增加数据的存储空间,常用的方法是创建( C )
A. 另一个表(table) B. 游标(cursor) C. 视图(view)D.索引(index)
10. 如果事务T获得了数据项Q上的.排它锁,则T对Q ( C )
A.只能读不能写 B.只能写不能读 C. 既可读又可写 D. 不能读不能写
二.填空题
1.数据库系统一般由数据库, _________, _应用系统_________ 。数据库管理员和用户构成。
2.数据库的存储结构改变了,由数据库管理员对_________映像作相应改变。可以使_模式_与应用程序保持不变,从而保证了数据的物理独立性。
3. DB并发操作通常会带来三类问题,它们是丢失更新、不可重复读和____________。
4. 事务必须具有的四个性质是:原子性、___________、____________和持久性。
5.用树型结构表示实体类型及实体间联系的数据模型称为_______________。
6.从关系规范化理论的角度讲,一个只满足1NF的关系可能存在的四方面问题是:数据冗余度大、修改异常、插入异常和______。
三、简答题
1、数据库
2、候选码
3、试述DBMS的主要功
4、数据模型的组成要素.
⬘ 数据结构报告 ⬘
概述
本次实验是针对数据结构课程的一项重要实践活动。通过完成这个实验,我们将深入了解和掌握各类数据结构的运作原理和实际应用。在实验过程中,我们通过编写代码、构建数据结构和进行算法分析等方式,对数据的存储、检索和处理等操作进行了全面的探索和研究。
实验内容
本次实验主要涉及以下几个方面的内容:
1. 数组
数组是最简单和最常用的一种数据结构。我们实现了基本的数组初始化、赋值和读取操作,还研究了各种不同类型的数组和多维数组的使用情况。通过这一部分的实验,我们深入理解了数组在内存中的存储和访问机制。
2. 链表
链表是一种动态数据结构,它的灵活性和高效性使得它在很多场景下比数组更加适用。我们实现了单链表和双链表,并比较了它们在插入和删除操作上的效率差异。通过这部分实验,我们深入了解了链表的结构和运作原理,以及如何通过指针来操作链表。
3. 栈和队列
栈和队列是两种非常常见的数据结构,它们在很多算法和应用中都起到了关键作用。我们实现了基本的栈和队列,并比较了它们在插入和删除操作上的效率差异。通过这部分实验,我们深入理解了栈和队列的特性以及它们的应用场景。
4. 树
树是一种非常重要和复杂的数据结构,它在很多高级算法和数据处理中都起到了关键作用。我们实现了二叉树和二叉搜索树,并研究了它们的遍历和搜索算法。通过这部分实验,我们深入了解了树的结构和运作原理,以及如何通过递归和迭代等方式来解决树相关的问题。
实验过程
在实验过程中,我们首先通过理论学习来了解各种数据结构的概念和特性。然后,我们使用编程语言来实现这些数据结构,并编写测试用例来验证它们的正确性和性能。在编码和调试过程中,我们遇到了很多问题,但通过团队合作和老师的指导,最终成功解决了这些问题。
实验结果
经过实验,我们成功实现了各种数据结构,并通过多次测试验证了它们的正确性和性能。我们还分别对数组、链表、栈和队列、树的各种操作进行了算法分析和性能测试。从实验结果可以看出,不同的数据结构在不同的场景中具有不同的优势和劣势,我们可以根据实际需求选择最适合的数据结构来提高程序的效率和性能。
实验总结
通过本次实验,我们对数据结构的概念和原理有了更加深入的理解,并学会了如何使用编程语言来实现和应用各种数据结构。实验过程中,我们也锻炼了问题分析和解决的能力,以及团队合作和沟通的能力。这些都对我们今后的学习和工作具有重要意义。
通过本次数据结构实验,我们不仅掌握了各种数据结构的运作原理和实际应用,还提高了我们的编程和算法设计能力。这将对我们今后的学习和工作产生积极影响。我们将继续学习和深入研究数据结构,为未来的科学研究和技术创新做出贡献。
⬘ 数据结构报告 ⬘
一、需求分析1、程序所实现的功能;2、程序的输入,包含输入的数据格式和说明;3、程序的输出,程序输出的形式;4、测试数据,如果程序输入的数据量比较大,需要给出测试数据;5、合作人及其分工二、设计说明1、主要的数据结构设计说明;2、程序的主要流程图;3、程序的主要模块,要求对主要流程图中出现的模块进行说明4、程序的主要函数及其伪代码说明(不需要完整的代码);5、合作人设计分工三、上机结果及体会1、合作人编码分工2、实际完成的情况说明(完成的功能,支持的数据类型等);3、程序的性能分析,包括时空分析;4、上机过程中出现的问题及其解决方案;5、程序中可以改进的地方说明;6、程序中可以扩充的功能及设计实现假想;说明:1、如果程序比较大,可以将设计说明分为概要设计和详细设计两部分。概要设计主要负责程序的流程、模块、抽象数据类型设计;详细设计负责程序的数据类型定义和主要函数的说明。2、设计说明中,不需要写出代码或者模块的详细代码,只需要写出主要函数的伪代码说明。
⬘ 数据结构报告 ⬘
数据结构报告
引言
数据结构是计算机科学中的一个重要概念,它是指数据元素之间的关系以及这些关系在计算机中的存储方式。数据结构的选择和设计直接影响到程序的运行效率和空间利用率。本报告将详细介绍数据结构的相关知识、应用及优化方法。
一、数据结构的概念和分类
数据结构是对计算机中数据的组织、存储和管理的方法的研究。它按照数据元素之间的关系可分为线性结构、非线性结构和文件结构。线性结构中的数据元素是一对一的关系,如数组、链表;非线性结构中的数据元素是一对多的关系,如树、图;文件结构是对数据进行存储和访问的方法,如顺序文件、索引文件。
二、常见数据结构的应用
1. 数组(Array):数组是一种线性结构,它可以存储多个相同类型的元素。在计算机科学中,数组被广泛应用于存储和访问数据,如矩阵运算、图像处理等。
2. 链表(Linked List):链表是一种线性结构,它通过指针将数据元素连接在一起。链表可以动态地调整大小,因此在需要频繁插入和删除元素的情况下,链表是一种常用的数据结构。
3. 栈(Stack):栈是一种具有特定操作限制的线性结构,它遵循先进后出(LIFO)的原则。栈常用于程序的内存分配、表达式求值等场景。
4. 队列(Queue):队列是一种具有特定操作限制的线性结构,它遵循先进先出(FIFO)的原则。队列常用于实现任务调度、消息传递等场景。
5. 树(Tree):树是一种非线性结构,它由节点和边组成。树状结构的应用非常广泛,如文件系统、数据库索引等。
6. 图(Graph):图是一种非线性结构,它由节点和边组成。图的应用涉及到网络、社交关系分析等领域。
三、数据结构的优化方法
1. 算法优化:选择合适的算法可以明显提高程序的执行效率。比如,在查找一个有序数组中的元素时,使用二分查找算法可以将时间复杂度降低为O(logN),而不是简单的线性查找算法的O(N)。
2. 空间优化:合理利用存储空间是数据结构优化的一个重要方面。比如,对于稀疏矩阵,可以采用压缩存储的方式,只保存非零元素,从而减少内存消耗。
3. 缓存优化:利用计算机中的缓存机制可以提高程序的访问速度。比如,将最常用的数据放在缓存中,减少从内存读取数据的时间。
4. 并行优化:利用并行计算的特性可以加快程序的执行速度。比如,将大规模的计算任务分解为多个子任务,分配给多个处理器同时执行。
结论
数据结构是计算机科学中非常重要的一门学科,它对程序的性能和空间利用率有着直接影响。在实际的软件开发中,根据具体的需求选择合适的数据结构和优化方法可以提高程序的效率和用户体验。因此,深入理解数据结构的概念和分类,并学会应用优化方法,对于开发高效的软件应用至关重要。
⬘ 数据结构报告 ⬘
Vector类似于一个数组,但与数组相比在使用上有以下两个优点。
1、使用的时候无需声明上限,随着元素的增加,Vector的长度会自动
增加。
2、Vector提供额外的方法来增加、删除元素,比数组操作高效。
Vector类有三个构造函数,分别如下:
public Vector();
该方法创建一个空的Vector。
public Vector(int initialCapacity);
该方法创建一个初始长度为initialCapacity的Vector。
public Vector(int intialCapacity,int capacityIncrement);
该方法创建一个初始长度为initialCapacity的Vector,当向量需要增长时,增加capacityIncrement个元素。
(1)Vector类中添加、删除对象的方法如下:
public void add(int index,Object elemtent)
在index位置添加对象element。
public boolean add(Object o)
在Vector的末尾添加对象o。
public Object remove(int index)
删除index位置的对象,后面的对象依次前提。
(2)Vector类中访问、修改对象的方法如下:
public Object get(int index)
返回index位置对象。
public Object set(int index,Object element)
修改index位置的对象为element。
(3)其它方法:
public String toString()
将元素转换成字符串。
public int size()
返回对象的长度。
例1:操作Vector对象,进行元素的添加、插入、修改和删除。程序输出结果如图1所示。源程序代码如下:
//程序文件名为UseVector.java
import java.util.Vector;//引入JDK的Vector类
public class UseVector
{
public static void main(String[] args)
{
Vector vScore=new Vector();
vScore.add("86");//添加元素
vScore.add("98");//添加元素
vScore.add(1,"99");//插入元素
//输出结果
for(int I=0;I
{
System.out.print(vScore.get(i)+" ");
}
vScore.set(1,"77");//修改第二个元素
vScore.remove(0);//删除第一个元素
System.out.println(" 修改并删除之后");
for(int I=0;I
{
System.out.print(vScore.get(i)+" ");
}
System.out.println(: 转换成字符串之后的输出 " +vScore.toString());
}
};
⬘ 数据结构报告 ⬘
StringBuffer类提供了一个字符串的可变序列,类似于String类,但它对存储的字符序列可以任意修改,使用起来比较String类灵活的多。它常用的构造函数为:
StringBuffer()
构造一个空StringBuffer对象,初始容量为16个字符。
StringBuffer(String str)
构造一个StringBuffer对象,初始内容为字符串str的拷贝。
对于StringBuffer类,除了String类中常用的像长度、字符串截取、字符串检索的方法可以使用之外,还有两个较为方便的方法系列,即append方法系列和方法系列。
(1)append方法系列根据参数的数据类型在StringBuffer对象的末尾直接进行数据添加。
public StringBuffer append(boolean b)
public StringBuffer append(char c)
public StringBuffer append(char[] str)
public Stringbuffer append(char[] str,int offset,int len)
public StringBuffer append(double d)
public StringBuffer append(float f)
public StringBuffer append(int i)
public StringBuffer append(long l)
public StringBuffer append(Object obj)
public StringBuffer append(String str)
public StringBuffer append(StringBuffer sb)
(2)方法系列根据参数的数据类型在StringBuffer的offset位置进行数据插入。
public StringBuffer (int offset,boolean b)
public StringBuffer (int offset,char c)
public StringBuffer (int offset,char[] str)
public StringBuffer (int index,char[] str,int offset,int len)
public StringBuffer (int offset,double d)
public StringBuffer (int offset,float f)
public StringBuffer (int offset,int i)
public StringBuffer (int offset,long l)
public StringBuffer (int offset,Object odj)
public StringBuffer (int offset,String str)
(3)下面这个方法用于将stringbuffer对象的数据转换成字符串:
public String toString()
例6:基于例5进行修改,使用StringBuffer对象得到如图6所示的输出界面。
//程序文件名为TestString.java
public class TestString
{
public static void main(String[] args)
{
StringBuffer str=new StringBuffer(" The substring begins at the specified beginIndex.");
StringBuffer str1=new StringBuffer("string");
String str2=new String();
int size=str.length();
int flag=str.indexOf("substring");
str2=str.substring(flag,flag+9);
StringBuffer strOut=new StringBuffer("字符串");
strOut.append(str);
strOut.append("总长度为:");
strOut.append(size);
int f=strOut.indexOf("总");
strOut.(f,' ');
System.out.println(strOut.toString());
if(str1.toString().equals(str2))
System.out.println("截取的字符串为:"+str1.toString());
else
System.out.println("截取的字符串为:"+str2):
}
}
⬘ 数据结构报告 ⬘
终于要放寒假了,我很想回家看看家里的父母和奶奶以及我的外婆等亲人,但也想到了大学的时光过的真如白驹过隙。大一开学似乎就在昨天,时间快的让我感觉好像我什么也没有学到,尤其是我最重要的专业课《数据结构》(至少到目前为止我认为是),更是学得一塌糊涂,书上讲的知识大多都是一知半解,很多知识点我甚至考试时都没有什么映像。很多人包括老师都说《数据结构》这门课程在我们计算机相关专业中是很重要的一门课程,如果他没有学好,是很难在这方面有大的提高的。
因此,为了加强我的相关方面的学习,我就觉定在寒假一个月左右时间内把《数据结构》重新学一遍,知道的要熟练,不知到的要知道,也要慢慢熟练,为自己以后更深入的学习打好基础。
对《数据结构》这本书,我大体上了解他的基本章节讲述,对绝大多数知识点我还是比较了解的,但运用起来不够熟练,掌握的不够好,而且后面几章中有一些重要的知识点我学的是非常不好,一方面是我自身资质愚钝,另一方面是由于在它上面花的时间少了。我打算趁这次寒假的时间把这本书按照顺序全面看一下,掌握的比较好的知识点就再熟悉几遍,掌握的不好的我会多花时间把它掌握,而且由于平时在学校都只是注重理论知识的学习,较少的上机编程,这次我会多花一些时间在上机编程上,养成好的编程习惯,争取做到至少评均每日一程,让编程成为我的一项兴趣爱好,要慢慢喜欢它,而不是像以前怕他,厌恶它,我相信付出必有回报,我现在吃苦,以后便会受益。
这几天我着重看了一下《数据结构》的前几章的内容,我都掌握的还不错,就是线性表中的一些编程不是很熟悉,特别是单链表,像他的一些诸如初始化、判空、判满、求长度、之类的算法我还是比较熟悉的,但有一些像插入、删除、倒置、合并的算法,我就感觉有点吃力了,所以我这几天就专门找了关于单链表的编程题目,好好做了不少,做完后,再反复看了一下书上的讲解,几天下来,感觉自己在这方面提高了不少,而且最重要的是自己对那方面的编程有了感觉,不象以前毫无头绪,不得不说这是一个进步,而且我现在正在强迫自己养成好的编程习惯,我发现好的编程方式就像写文章一样。首先,我们需要弄清楚写这篇文章的目的,这就是我们所说的程序的功能;然后你就要写提纲,把大致框架写出来,也就是我们编程中的要实现功能的所有有效的函数和程序结构;然后我们就按照提纲联系自己大脑中和书上的素材把文章写出来,也就是我们编程中把函数补充完整,以及各函数要连贯;最后就要检查自己的文章有没有错别字,以及文章有没有什么逻辑上的错误,也就是我们编程上的验证程序的语法错误和逻辑错误。虽然真正的写文章和编程比上述讲的要复杂的多,但大致的基本原理就是如此,我们若想学好编程,就必须养成这样的好习惯。
这几天在编程的过程中我真的是感触良深啊,由于有好的编程习惯,所以一般的程序基本上没有什么困难,就算是稍微困难的程序我只要按照步骤好好分析好好看,也会很快解决问题,但我遇到了一些问题着实棘手。有些程序编译的时候语法上没有什么错误,但一运行时会出现程序突然终止执行或者干脆不执行,更有甚者一个程序中某一个或某几个函数它不执行,我刚开始遇到这种情况真的是手足无措,不知从何入手,但慢慢的,我学会了分析程序,分析它在逻辑上是否行得通,在内存上是否有表示,慢慢的就解决了一些问题,像有些是应为内存提前释放掉了,有些是因为函数返回值错了倒置逻辑上出错了,等等,但这样的问题每一个都要比语法错误更难看出来,要花更多时间去发现去解决它,现在我越来越觉得调试程序也是一门重要的学问,像这些问题我少则花一天,多则好几天,有一个问题我至今多不知道如何解决,但我相信我会解决的,因为我徐楷是不会放弃的,不管有多难,我都会全力以赴做到最好。因为我现在越来越发现越是难的编程问题,越是让你花精力花时间的问题,当你成功解决它的那一刻,当它的运行结果是你心目中所想的结果的时候,那种内心的喜悦感、成就感让你感觉像吃了天上的蟠桃,喝了九重天的琼浆玉液一样好,现在我越来越喜欢编程了,它带给我成就感,喜悦感,而且让我的生活过的充实,更重要的时让我的心灵动起来,不至于生锈了。
今天是大年初一,我们中华名族传统节日中很重要的节日——春节,而且今年是龙年,中国人对龙有一种不一样的情节,我也不例外。今年春节过的还不错,在心中有那种节日气氛,虽然说天气冷冷的,但请朋好友的热情让我感觉格外温暖,今年春节期间除了春节外,我的亲戚还有不少喜事,确实增添了不少换了的气氛,但是也有一件悲伤的事情发生了,就是我们徐姓家族理最大辈的一位老人去世了,确实让我感觉很悲痛,但他是自然死亡,不是因为什么病痛,我得知这些后心也有点安了。由于过年几天天气冷,而且忙着过节,所以没话多少时间在编程上,我只是花了一些时间看了一下相关方面的书籍,温习一下旧知识,加深一下映像,我发现这几天由于心情难以平静下来,倒置编程都没啥效率了,心情起伏有很多因素。
我发现编程要有一个平静的心情,要有对新事物的一种强烈求知欲,只有如此,才能在算法上有所创新,有所发现。龙年春节这样的大节日对每一个炎黄子孙来说,心情都难以平定啊,不过过了一个年,自己长大了一岁,但感觉自己好像没啥进步,时光易逝啊,我们确实要珍惜现在的美好时光,不然的话就要重蹈“少壮不努力,老大徒伤悲”的覆辙了。
我的堂哥今天结婚,所以这几天我在他家里帮忙,因此基本上没有看《数据结构》这本书。不过并不意味着我没有在学习,因为我的堂哥他也是搞软件的,他在这里工作了几年,对这方面还比较了解,和他谈谈相关方面的东西可以让我以后奋斗的目标更加明确,而且可以少走很多弯路,他在软件行业工作,知道他需要什么方面的人才,所以他给了我很多建议,让我受益匪浅。我一直以来都很敬佩我堂哥,不仅因为他聪明,更重要的是因为他那中上进心,那种不怕吃苦的精神让我佩服,而我就比较缺乏这方面的气质,我的堂哥今年二十七八了,是响应国家晚婚晚育政策的当代好青年,而我的嫂子也是一个好姑娘,贤良淑德,温柔大方,很有礼貌,而且很勤快,他和我哥哥都是很优秀的人,我相信他们一定会很幸福的,因为他们都有一个好脾气,都很会为对方着想,这是感情得以长久维持的最主要因素。
我的哥哥一直以来都是我的榜样,很多方面,但尽管如此,我还是想超过他,而且坚信我可以,我相信皇天不负有心人,只要努力,就一定会有回报的,而且吃苦越多,回报就会越丰厚。
还有一点我觉得我应该在提高专业知识的同时,注意思想道德素质的培养,还要培养自己多方面的能力,让自己成为一个综合能力很高的当代大学生。
今天我家里要做新房子,我帮大人们做一些事,所以白天几乎没做什么关于学习方面的事,只是在晚上编了一下程序,感觉自己有很长时间没有复习这方面的东西,所以对他生疏了,特别是今天,遇到了很多问题,后来我发现了有很多问题都是由于我粗心造成的,本可以避免的,而且我又发现了我的一个很严重的缺点,做事太过于急于求成,特别是遇到困难的时候更是很容易急躁,有很多时候急躁迷失了我的心智,蒙蔽了我的双眼,让我不能很好的看到事情的本质,这对我的发展有很多坏处,我今后一定要改正这个坏习惯。做事力求稳,一步一个脚印。我还发现我对c和c++的一些小区别搞得还不是很清楚,有些概念搞得有点小问题,我发现我现在很喜欢用c++写程序,特别是用他里面的引用作函数的参数,太方便了,但有时候有些东西似乎必须用c写(至少在我现在所掌握的知识中),而只要有一个是c里面特殊的东西,就必须把头文件改成c的头文件,而如此便不能用c++了,就不能用他那很多方便的功能了。
但我想不管遇到什么问题,只要我们有不放弃的心,并且能够下决心去解决他,就一定会解决的,如果随随便便就解决了一个问题,那这个问题就没什么价值了,随随便便就成功了,那么这个成功带给我们的就没啥东西了,来的快的东西消失的也快,来的慢的东西才能保持长久。
今天我家正在拆房子,准备做新房子,我身为家中的一员,而且20岁了,理应帮帮忙,以前真是没做过这个活,今天一上来才真正感觉到那叫一个累啊,忙了一天到了晚上身体真的是散架了,我这才体会到父母的艰辛,以前老以为农村劳动只是体力劳动,不会很累,但我现在发现,如果没有坚强的意志力和好的身体真的很难坚持下来,我发现累的时候想想房子成功后的种种好处,就马上有了力量。生活中遇到了困难,我们就应该像这样想,想想成功后的那种成就感,喜悦感,你就马上有了坚持下去的勇气,相信世上无难事,只怕有心人,就没什么困难不能解决了。有时候我们不能怪上天,没有让我们生活在一个好家庭里,我们也不能怪父母,没让我们有个好生活,更不能怪生活,安排了太多困难在我们面前,你要相信,一个人若想成功,就必须经受挫折,逆若想有大的成功,就必须有解决大问题的勇气和能力,就必须经受常人难以忍受的挫折。
有时候,你要感激上次上苍,给你安排那么多的困难,因为他是在给你提供成功的机会,如果你能有如此的看法,你就离成功不远了。
我今天看了一本书,他的名字叫《智慧背囊》,因为我觉得人生需要智慧,成功更需要智慧。它里面都是以小故事开篇,再引申出一个道理。今天,我看到一个故事。我感觉很好。故事是这样的:
一个青年职员平时工作懒懒散散,在转正前一个月他问老板:“如果我兢兢业业工作一个月,我能转正吗?”老板答道:
“你的问题让我想到一个冷房间的温度计,你用热手捂着它,能使表上显示温度上升,不过房间一点也不会温暖。他告诉我们一个道理:今天的成就是昨天积累的,明天的成功是今天努力的结果。
其实,真正的成功是一个过程,就是把勤奋和努力融入到日常生活和工作中去。这要靠我们的意志,但更重要的是建立一个良好的生活习惯和工作习,就像我的曾经的老师说的一句话:“因为你有选择,你主载自己的人生。
”我们要知道冰冻三尺,非一日之寒。绳锯木断,水滴石穿。有时候,坚持就是成功。你不能指望一劳永逸地获得永久的成功。只有在梦中,你才能用暂时的努力获得永久的成功。
我们在生活中要不断鞭策自己,要有不达目的不罢休的精神,当然你的目的必须是好的,而且是适合自己,切勿强求,这个度要怎么把握就要靠我们细细斟酌了。
⬘ 数据结构报告 ⬘
参考答案
第一章、绪论
一、选择题 1 B;2 A; 3 B; 4 C ;5 C; 6 B;7 C;8 C; 9 D; 10 B。
二、填空题1、存储 ;2、无 ,1,无,1; 3、前驱,1,后继,任意多个;4、一对一,一对多,多对多;5、时间复杂度,空间复杂度;6、集合,线性结构,树形结构,图形结构;
7、顺序结构,链式结构,索引结构,散列结构;8、顺序。
三、问答题与算法题
1、3 ;
2、T1 ( n ) = 5n 2 -O ( n ) ; T2 ( n ) = 3 n 2 + O ( n ) ; T3 ( n ) = 8 n 2 + O(log n) ; T4 ( n ) = 1.5 n 2 + O ( n ) 。T4 ( n ) 较优,T3 ( n )较劣。
3、见课本。
第二章 线性表
一、选择题 1C;2A;3D;4B;5D;6B;7C;8B;9A;10C;11D;12D;13C;14C.
二、填空题 1、O ( 1 ), O ( n );2、单链表,双链表;3、地址,指针;4、4,2;5、便于访问尾结点和头结点;6、前驱;7、L->next== L且L->prior== L;8、顺序。
三、问答题与算法题
1、头指针:结点或头结点的指针变量。其作用是存放第一个结点或头结点的地址,从头指
针出发可以找到链表中所有结点的信息。
头结点:是附加在链表的第一个结点之前的一个特殊结点,其数据域一般不存放信息。
其作用是为了简化运算,将空表与非空表统一起来,将第一个结点与其他结点的处理统一起来。
首结点:是链表的第一个结点。
2、(1)基于空间的考虑。当要求存储的线性表长度变化不大,易于事先确定其大小时,为了节约存储空间,宜采用顺序表;反之,当线性表长度变化大,难以估计其存储规模时,采用动态链表作为存储结构为好。
(2)基于时间的考虑。若线性表的操作主要是进行查找,很少做插入和删除操作时,采用顺序表做存储结构为宜;反之, 若需要对线性表进行频繁地插入或删除等的操作时,宜采用链表做存储结构。并且,若链表的插入和删除主要发生在表的首尾两端,则采用尾指针表示的单循环链表为宜。
3、尾指针是指向终端结点的指针,用它来表示单循环链表可以使得查找链表的'开始结点和终端结点都很方便,设一带头结点的单循环链表,其尾指针为rear,则开始结点和终端结点的位置分别是rear->next->next 和 rear, 查找时间都是O(1)。若用头指针来表示该链表,则查找终端结点的时间为O(n)
4、S=P->Prior; P->Prior=S->Prior; S->Prior->Next=P; S->Prior=P; S->Next=P->Next; P->Next=S;S->Next->Prior=S;
5、:将开始结点摘下链接到终端结点之后成为新的终端结点,而原来的第二个结点成为新的开始结点,返回新链表的头指针
6、15,26,51,37,48,,55。
7、CreatList_L(LinkList &L int n) {
L= (LinkList) molloc (sizeof (Lnode));//头结点
L->next==NULL; q=L;
For(i=1;i<=n;++i)
41
{ P= (LinkList) molloc (sizeof (Lnode));
Scanf(&(p->data));
p->next=NULL; q->next=p; q=p;}
returen OK;
}
8、Void s(Sqlist &S, int x)
{int i=0; n=S.Length;
while(x if(i==n) S.elem[n]=x; //插在最后一个结点的后面 else {for(j=n-1;j>=i;j++) S.elem[j+1]=S.elem[j]; //元素后移 S.elem[i]=x; //插入 } } 9、int ListLength(LinkList L) {q=L->next; i=0; while(q) {i++; q=q->next; } return i; 10、int (LinkList &L, int x) { p=L->next; //p为定位指针 q=L; //q为定位指针的前导 while((p->data!=x) && p) { q=p; //q前进 p=p->next; //p前进 } if(!q) return ERROR; //查找失败 q->next=p->next ; free(p); return OK; } 11、void mergelist(linklist &La, linklist Lb) {pa=La->next; pb=Lb->next;pc=La; while (pa && pb) if (pa->data< pa->data) {pc->next=pa;pc=pa;pa=pa->next;} else if(pa->data== pa->data) {pc->next=pa; pc=pa; pa=pa->next; pb=pb->next;} else ({pc->next=pb;pc=pb;pb=pb->next;} pc->next=pa? pb:pb; } 12、Void invertlinklist(linklist &L) {if(!L) return OK; //空表 p=L->next; if(!p) return OK; //仅有一个结点的表 else{q=p->next; //q指向p的后继 42 p->next=NULL; while(q) { r=q->next ; //r指向q的后继 q->next=p; //逆置 p=q; //p前进 q=r; //q前进 } L=p; //第一个结点 } } 13、Void delDuplicate(int A[],int & n) { for(i=0;i for(j=i+1;j<=n-1;j++) if(a[i]==a[j]) {n--; for(k=j+1;k<=n-1;k++) a[k-1]=a[k]; } } 第三章 栈和队列 一、选择题1A;2D;3C;4C;5D;6C;7C;8B;9C;10C;11D,B;12D;13B。 二、填空题 1、栈顶;2、满,空,n;3、后进先出,先进先出;4、头;5、L->next==NULL,==S.base, -S.base==S.stacksize,L==NULL,Q.front==Q.rear,(Q.rear+1)%maxQsize ==Q.front; 6、Q.rear-Q.front+n)%n;7、1nC2n;8、n-1。 n?1 三、问答题与算法题 1、 1324; 2、(1) int push_L(Linkstack &s SelemType e) { p= (LinkStack) molloc (sizeof (Snode)); if(!p) return ERROR; p->data=e; p->next=s; s=p; Return Ok; } (2)int pop_L(Linkstack &s SelemType &e) { if(!S) return ERROR; q=s; e=s->data; s=s->next; free(q); Retuen Ok; } 43 3、(1)int EnQueue_L(Queueptr &QL QelemType e) { p= Queueptr} molloc (sizeof (Qnode)); if(!p) return ERROR; p->data=e; p->next=QL->next->next; QL->next->next= p; Retuen Ok; } (2)int DeQueue_L(Queueptr &QL QelemType &e) { if(QL->next==QL)} return ERROR; p= QL->next while(p->next!=QL) p =p->next; p->next=QL->next; e=QL->next; free(QL); QL=p; Return Ok; } 4、(1) 栈S元素反序存放; (2) 把栈s1复制到s2; (3) 把栈S中值等于m的元素删除; (4) 队列Q元素反序存放; (5) 链表中的元素反序存放; 5、Int hw4(LinkList L) { initstack(S); bool=1;n=0; p=L->next; while(p){n++; p=p->next;} //求串长 p=L->next; //p指向第一个结点 for(i=0; i while(p&&bool) {pop(S,ch); if(ch!=p->data) bool=0; p=p->next; } return bool; } 6、void ClearStack( LinkStack &S)。 {while(!S) {p=s; s=s->next; free(p); 44 } return OK; } 7、int Stacksize( LinkStack S)。 { n=0; p=s; While(!p) {n++; p=p->next; } return n; } 8、见4、(5) 第四章 串 一、选择题 1 B;2B;3D;4 B;5C;6 D。 二、填空题 1、空格串;2、静态分配的顺序串、动态分配顺序串、块连串;3、?? 4、块的大小; 5、2;6、StrAssing,StrCompare,StrLength,Concat,SubString;7、13,6;8、模式,目标(主)。 三、问答题与算法题 1、 ●空串是指不包含任何字符的串,它的长度为零。 空格串是指包含一个或多个空格的串,空格也是字符, 长度不为零。 ●串常量是指在程序中只可引用但不可改变其值的串。 串变量是可以在运行中改变其值的。 ●主串和子串是相对的,一个串中任意个连续字符组成的串就是这个串的子串,而包含 子串的串就称为主串。 ●目标串和模式串:在串匹配运算过程中,将主串称为目标串,而将需要匹配的子串称为 模式串,两者是相对的。 2、(1) "Stocktom, March51999";(2) 正数;(3) 正数;(4)18 3、void StrInsert(char *S, char *T, int i) {//将串T插入到串S的第i个位置上 char *Temp; if(i<=strlen(S)) {Temp=(char *)malloc(sizeof(char[Maxsize])); // 设置一个临时串 strcpy(Temp,&S[i]); //将第i位起以后的字符拷贝到临时串中 strcpy(&S[i], T); /将串T拷贝到串S的第i个位置处,覆盖后面的字符 strcat(S,Temp); //把临时串中的字符联接到串S后面 free( Temp ); } } 4、void StrDelete(char *S, int i , int m) //串删除 { char Temp[Maxsize]; //定义一个临时串 if(i+m 45
需要更多的数据结构报告网内容,请访问至:数据结构报告