东北大学数据结构实验报告

东北大学数据结构实验报告
东北大学数据结构实验报告

. /

实验报告

课程名称:数据结构班级:实验成绩:

实验名称:顺序表和链表的应用学号:批阅教师签字:

实验编号:实验一:实验日期:2017-11-25

指导教师:组号:实验时间:18:30~22:30

一、实验目的

(1)掌握线性表的基本操作(插入、删除、查找)以及线性表合并等运算在顺序存储结构、链式存储结构上的实现。重点掌握链式存储结构实现的各种操作。

(2)掌握线性表的链式存储结构的应用。

二、实验内容与实验步骤

(1)实验内容:

实现约瑟夫环,约瑟夫环(Joseph)问题的一种描述是:编号为1、2、3……n的n个人按照顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数的上限值m,从第一个人开始按照顺时针的方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他的顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。设计一个程序求出出列顺序。

(2)抽象数据类型和设计的函数描述,说明解决设想。

首先定义一个链表,用其中的data项存储每个人的编号,用password项存储每个人所持有的密码,并且声明一个指针。之后使用CreatList_CL函数来创建一个循环链表,在其中的data和password中存入编号和密码,最后使最后一个节点的next指向L,使其能够形成循环队列。定义了函数Display来显示链表当中的内容,以确定存储的数据没有错误。定义了函数Delete_L来实现约瑟夫环中依次删除的功能,依次比较,如果某个人所持的密码和m值相等,则删除这个结点,并且输出此时该结点的编号和密码,实现出列的功能。

(3)简短明确地写出实验所采用的存储结构,并加以说明。

该实验我主要采用的是线性表的链式存储结构,首先定义了链表的结构,其中包括data 项和password项,分别存储每个人的编号和所持密码,还声明了指向下一个结点的指针,该指针可以连接各个结点,并且将最后一个结点的指针指向第一个结点使之成为一个循环链表。

三、实验环境

操作系统:Windows 7

调试软件名称:Visio Studio2017

上机地点:信息楼B405

四、实验过程与分析

(1)主要的函数或操作内部的主要算法,分析这个算法的时、空复杂度,并说明设计的巧妙之处。

本实验中主要的函数包括创建链表、显示链表内容和出列过程四个部分。主要函数的代码如下:

创建链表:

typedef int Datatype;

typedef struct node//链表的定义

{

Datatype data;

int password;

struct node *next;

}ListNode,*CLinkList;

void CreatList_CL(CLinkList *L,int n)//创建一个链表

{

int i,pin;

CLinkList p,q;

(*L)=(CLinkList)malloc(sizeof(ListNode));

if((*L)==NULL)

printf("error\n");

else

(*L)->next=NULL;

q=*L;

for(i=0;i

{

p=(CLinkList)malloc(sizeof(ListNode));

if(p==NULL)

printf("error\n");

printf("请输入第%d个人的密码:",i+1);

scanf("%d",&pin);

p->data=i+1;

p->password=pin;

q->next=NULL;

q->next=p;

q=p;

}

q->next=(*L)->next;//指向L结点,形成

}

创建这个链表的时间复杂度为O(n),空间复杂度为O(n2)。

显示链表中的信息内容:

void Display(CLinkList *L,int n)

{

int i;

CLinkList p;

p=(*L)->next;

printf("\n显示链表内容\n");

for(i=0;i

{

printf("编号:%2d 密码:%d\n",p->data,p->password);

p=p->next;

}

}

该算法的时间复杂度为O(n),空间复杂度为O(n2)。

删除结点,完成出列功能:

void Delete_L(CLinkList *L,int n,int m)

{

int i=0,j;

CLinkList p,q;

q=(*L);

p=(*L)->next;

printf("\n删除的顺序:\n");

while(i

{

for(j=0;j

{

q=p;

p=p->next;

}

printf("编号:%d 密码:%d\n",p->data,p->password);

m=p->password;

q->next=p->next;

free(p);

p=q->next;

n--;

}

}

该算法的时间复杂度为O(n2),空间复杂度为O(n2)。

该设计的巧妙之处在于并不需要额外的空间来存储数据,因而空间复杂度较低,而且线性表的链式存储结构可以用物理位置上的邻接关系来表示结点间的逻辑关系,这样使读者在阅读代码的过程中可以更加方便和便于理解。它可以随机存取表中的任一结点,还可以免插入和删除操作带来的大量的结点的移动,能给结点动态分配内存,这样就不存在存储空间不足的情况,而且循环链表还可以方便的从链表的最后一个结点遍历到链表的第一个结点。使操作更加方便。

(2)你在调试过程中发现了怎样的问题?又做了怎样的改进

1)在最开始的调试阶段,我发现链表插入结束之后,不能按照正常情况下输出链表的内容,只能正常显示第一个人的数据,在显示第二个人的信息是数据为乱码。之后我发现,在插入链表的过程中,我是在执行循环插入数据的循环中将结点的指针指向了第一个结点,因而,在进行链表显示的过程中,第二个结点的内容不是正常的数据。之后我将q->next=(*L)->next;这条指令放到了整个插入循环的外部,这样表示在插入所有数据之后,

最后一个结点的指针指向了第一个结点,形成了一个循环队列,此时链表的数据显示正确。

2)再次调试时,我发现人员出列时,只有第一个人出列正常,在第二个人出列时程序自动终止,不能正常显示之后出列的人的信息,并且程序自动终止运行,经过检查我发现在经过一次删除后,没有将指针指向下一个结点,因而出现问题。经过更改,程序运行正常。

3)在实验的开始阶段,数据遍历总是出现问题,经过查找资料我发现了约瑟夫环头结点的特殊性,因此我不再使用头结点,程序便恢复正常了。

(2)测试结果

五、实验结果总结

回答以下问题:

(1)你的测试充分吗?为什么?你是怎样考虑的?

答:我认为我的测试充分,因为我随机选用了很多组不同的数据进行测试,并且每次测试的结果都是正确的答案,这样选取的数据具有很强的随机性,具有代表性,因而我认为我的测试比较充分。

(2)你的存储结构的选取是不是很适合这个应用?为什么?

答:我认为我选取的线性链式存储结构适合这个应用,因为首先此题中描述的情景中表示人们按照顺时针的方向进行排队,此时头尾相连,这与循环链表的结构十分相似,使用循环链表的结构,这样可以很方便的从链表的最后一个结点访问到链表的第一个结点,并且这样的存储方式是用物理位置上的邻接关系来表示结点间的逻辑关系,根据这个特点,该种结构可以随机存取表中的任一结点,而且它也可以避免插入和删除操作带来的大量结点的移动,并且可以随时分配空间和释放空间,这样可以减少空间的使用量,并且可以做到灵活的扩充空间,这样的结构很适合这个应用。

(3)用一段简短的代码及说明论述你的应用中有关插入和删除元素是如何做的?

答:插入元素:首先定义了两个临时指针p和q来分别表示新插入结点的指针和第一个结点的指针,在每次插入之前应该动态的分配内存,输入要输入的信息,并且将各种数据存储到链表中相应的项里,将前一个结点的next赋值为空,再将前一个结点的指针指向下一个结点,此时完成一个元素的插入。依次类推,运用循环来实现所有人的数据的插入,关键代码如下:

p=(CLinkList)malloc(sizeof(ListNode));

if(p==NULL)

printf("error\n");

printf("请输入第%d个人的密码:",i+1);

scanf("%d",&pin);

p->data=i+1;

p->password=pin;

q->next=NULL;

q->next=p;

q=p;

删除元素:进行循环来实现每个元素出列的功能,首先每个人进行循环,一次进行报数,在报到m-1之前都不进行删除元素这个动作,在m时,把此时结点中的password中的数值赋给m然后运用q->next=p->next;将结点删除,同时释放结点p,将人数减1,以此类推完成所有的删除操作,直到所有的元素出列,关键代码如下:while(i

{

for(j=0;j

{

q=p;

p=p->next;

}

printf("编号:%d 密码:%d\n",p->data,p->password);

m=p->password;

q->next=p->next;

free(p);

p=q->next;

n--;

}

(4)在你的应用中是否用到了头结点?你觉得使用头结点为你带来方便了吗?

答:在我的应用中我没有用到头结点。在实验的一开始,我使用了头结点,但是使用头结点给数据的遍历带来了困难,因此我便放弃使用头结点。

(5)源程序的大致的执行过程是怎样的?

答:首先用编译器编写一个.c的文件,然后编译生成.obj的文件,通过连接将目标文件连接生成一个.exe文件,之后运行文件就可以执行了。

六、附录

(1)实验设想和建议

这次实验提高了我对数据结构中关于循环链表和顺序表的理解,提高了我的编程能力,学校以后最好可以增加实验课的课时,这样我们可以更大程度的提高自己的编程能力。另外我认为该实验不仅可以使用使用链表指针来实现,还可以使用数组来模拟链表来实现约瑟夫环,用数组的下标来指向前一个和后一个元素,之后进行删除来实现约瑟夫环。

(2)参考资料:《数据结构(第二版)》闫玉宝编著清华大学出版社

实验报告

课程名称:数据结构班级:实验成绩:

实验名称:栈、队列、字符串和数组学号:批阅教师签字:

实验编号:实验二:实验日期:2017-11-20

指导教师:组号:实验时间:18:30~22:30

一、实验目的

(1)掌握栈、队列、串和数组的抽象数据类型的特征。

(2)掌握栈、队列、串和数组的抽象数据类型在计算机中的实现方法。

(3)学会使用栈、队列来解决一些实际的应用问题。

二、实验内容与实验步骤

(1)实验内容:

假设表达式中除了变量名、常量和运算符外,还可以允许两种括号:圆括号和中括号,其嵌套的次序随意,编写程序检验输入的表达式中括号的的顺序是否合法。

(2)描述抽象数据类型或设计的函数描述,说明为什么要使用这种抽象数据类型,并说明解决设想。

抽象数据类型或函数描述:首先定义了一个结构体并且声明为栈类型,在其中定义了空间基地址的指针、栈顶指针以及栈存储空间的大小。之后设计了Creat _Stack的函数,用此函数来创建一个空栈,这样可以使用堆栈来实现括号匹配的功能,又设计了一个名为Stack_Full的函数了来判断栈是否已满,若栈未满才可继续之后的压栈功能,如果堆栈已满,则需要使用realloc来动态分配空间,扩大栈的存储空间。我还设计了一个名为empty的函数,用它来判断堆栈是否为空,堆栈为空或不为空时分别返回0或1。之后设计了名为push 和pop的函数来实现括号的入栈和出栈,之后设计了名为Match的函数,来判断括号是否匹配,设计了名为clean的函数来清空堆栈,这样可以连续判断不同的多项式的括号是否匹配。

解决设想:对于本题,首先我使用了栈结构,利用栈中数据“先进后出”的特点来实现对括号是否匹配的检验。实现过程基本如下:从左到右依次扫描多项式,如果遇到左括号便将左括号入栈,在所有左括号入栈之后便可以扫描到右括号,如果扫描到的右括号和栈顶的左括号可以匹配时,将左括号出栈,以此类推,最后判断栈是否为空,若为空,则括号匹配,否则括号不匹配。

三、实验环境

操作系统:Windows 7

调试软件名称:Visio Studio2017

上机地点:信息楼B405

四、实验过程与分析

(1)实现时,主要的函数或操作内部的主要算法,分析这个算法的时、空复杂度,并说明设计的巧妙之处。

主要函数或操作内部的主要算法:

typedef struct//栈的声明

{

char *base;//指示存储数据元素的空间基地址的指针

char *top;//栈顶指针

int stacksize;//栈存储空间大小,以数据元素为单位

}SStack;

void Creat_Stack(SStack *s)//创建空栈

{

s->base=(char*)malloc(sizeof(char)*size);

if(s->base==NULL)

printf("error\n");

else

{

s->top=s->base;

s->stacksize=size;

}

}

上面的算法用来建立栈,该算法的时间复杂度为O(1),空间复杂度为O(n)。

int Stack_Full(SStack *s)//判断栈是否为满

{

if(s->top-s->base>=100)

return 1;

else

return 0;

}

int empty(SStack *s)//判断栈是否为空

{

if(s->base==s->top)

return 0;

else

return 1;

}

上面的算法分别用来判断栈是否已满,栈是否为空栈,上面两个算法的时间复杂度和空间复杂度均为O(1)。

void push(SStack *s,char *str)//入栈

{

if(Stack_Full(s)!=0)

printf("full\n");

}

else

*s->top++=*str;

}

void pop(SStack *s,char *str)//出栈

{

if(s->base==s->top)

printf("The stack is empty\n");

else

*str=*--s->top;

}

上面两个算法用来实现数据的入栈和出栈,时空复杂度均为O(1)。void Match(SStack *s,char *str)

{

int i,j;

char t;

j=strlen(str);

for(i=0;i

{

if(str[i]=='('||str[i]=='[')

push(s,str);

}

for(i=0;i

{

if(str[i]==')')

{

if(*s->top=='(')

{

pop(s,&t);

}

else

s->top=s->top-1;

}

if(str[i]==']')

{

if(*s->top=='[')

{

pop(s,&t);

}

else

s->top=s->top-1;

}

if(empty(s)==0)

printf("括号匹配!\n");

else

printf("括号不匹配!\n");

}

该Match函数的作用即判断括号是否匹配,是本程序的核心函数,若假设输入的表达式的长度为n,则此函数中进行了两次循环,一次为扫描左括号使其全部入栈,另外一次为扫描右括号并且判断新扫描出来的右括号与栈顶的左括号是否匹配。在整个过程中执行了2n次循环,因此此程序的时间复杂度为O(n)。对于空间复杂度,本算法存储了长度为n的表达式,因而该算法的空间复杂度为O(n)。

设计的巧妙之处:在本程序中我使用了栈这种抽象数据类型,栈的“先进后出”的特点与检验括号是否匹配的“期限待的急迫程度相吻合,设计顺序栈来解决括号匹配问题。如果单从括号检验这个目的考虑可以有多种方法来实现该实验目的,而使用栈来实现括号匹配的检测,简化了程序的设计,比较容易理解和实现,并且可以提高时间效率。

(2)你在调试过程中发现了怎样的问题?又做了怎样的改进?

1)在开始程序编译时,编译器总是提醒函数的形式参数的写法有问题,之后我发现,我在栈声明时将SStack未声明为指针类型,而我在形式参数中将参数写成了SStack s,因而出现错误,所以我将其更改为SStack *s,这个问题得以解决。

2)之后,编译器进行编译时,编译器提醒我在调用empty,match等函数时,实际参数的输入有问题,使得编译不能够通过,经过检查我发现我在写这些函数时,形式参数定义为char *s,因而我便在实际参数中代表字符串的参数前加取地址&符号,这个问题便解决了。

3)在进行编译时还出现了这样的警告,说我的小于号没有定义或者没有匹配,经过检查我发现我在循环中将其中一个条件写成

(3)你的抽象数据类型的实现是否具有可扩展性?

我的抽象数据类型具有可扩展性,因为栈的大小可以修改,如果栈已满,则可以增加空间,因此具有可扩展性。

(4)测试结果

五、实验结果总结

回答以下问题:

(1)你的测试充分吗?为什么?你是怎样考虑的?

答:我认为我的测试充分,因为我的表达式是随机给出的,这样选择的数据具有随机性,具有很强的代表性,并且每次的结果正确,因此我认为我的测试比较充分。

(2)为什么你要选用栈或队列或字符串或数组等抽象数据类型作为你应用的数据结构?

答:我使用了栈这种抽象数据类型作为我应用的数据结构,栈是一个只能访问表的尾端数据的数据集合,是一种在表的一端进行插入和删除操作的线性表,数据具有“先进后出”的特点,而这种特点和括号匹配中检验括号的“期限待的极限程度”这个特点相符合,因此选用栈这种数据结构可以简化程序,更好的理解和实现程序,提高了程序运行的时间效率。

(3)用一段简短的代码及说明论述你的应用中主要的函数的主要处理部分。

答:下面的代码部分为Match函数中的主要处理部分,使用了两个循环来处理输

入的表达式,第一个循环是用来从左到右扫描表达式遇到“(”或者“[”就将括

号入栈,第二个循环是用来扫描表达式,如果遇到“)”或“]”就将其与栈顶的

括号进行匹配,如果匹配,就将栈顶的左括号弹出,如果不匹配就将栈顶指针向

下移动,直到所有的括号操作完成,如果栈为空,那么该表达式的括号是匹配的,

否则括号不匹配。

j=strlen(str);

for(i=0;i

{

if(str[i]=='('||str[i]=='[')

push(s,str);

}

for(i=0;i

{

if(str[i]==')')

{

if(*s->top=='(')

{

pop(s,&t);

}

else

s->top=s->top-1;

}

if(str[i]==']')

{

if(*s->top=='[')

{

pop(s,&t);

}

else

s->top=s->top-1;

}

}

(4)你的应用中采用的是顺序的还是链式的存储结构?为什么要选用这种存储结构。

答:我的应用中采用的是顺序的链式存储结构,因为对于栈这种抽象的数据类型,有着“先进后出”的特点,这种特性和表达式中括号匹配的过程相符合,因此我采用了这种存储结构。

(5)源程序的大致的执行过程是怎样的?

答:先用编译器编写一个.c的文件,然后编译生成.obj的文件,通过连接将目标文件连接生成一个.exe文件,之后运行文件就可以执行了。

六、附录

实验参考的资料《数据结构(第二版)》闫玉宝编著清华大学出版社

思考题

(a)栈和队列在计算机系统中有哪些应用?写出你知道的系统中,这两种抽象数据类型的应用。

答:在计算机系统中,使用栈的应用有表达式的计算,迷宫以及括号匹配等。使用队列的应用有打印文档,售票系统,解决主机与外部设备之间速度不匹配问题,解决多用户引起的资源竞争问题等

(b)在程序调用的时侯,需要进行函数的切换,你认为函数在进行切换时系统要做那些工作?

答:对于函数的切换,主要是一个压栈的过程,先以一种约定的方式把参数压栈,然后根据函数地址调用函数,函数执行后根据约定的方式出栈取得参数。

实验报告

课程名称:数据结构班级:实验成绩:

实验名称:栈、队列、字符串和数组学号:批阅教师签字:

实验编号:实验三:实验日期:2017-12-7

指导教师:组号:实验时间:18:30~22:30

一、实验目的

(1)理解分治法的思想。

(2)掌握用分治法解决问题

二、实验内容

(1)仔细阅读备选实验的题目,选择一个(可选多个)作为此次实验题目,设计的程序要满足正确性,代码中有关键的注释,书写格式清晰,简洁易懂,效率较高,利用C++的模板,设计的程序通用性好,适合各种合理输入,并能对不合理输入做出正确的提示。

(2)归并排序

★问题描述

目前的网上拍卖系统会显示很多待拍卖的物品,通常这些系统具有按照某个关键字对打出的广告进行排序列出的功能,并且能够按照用户

输入的某个关键字进行过虑,找到某些特定的物品。

★编程任务

定义一个Advertisement类,该类中至少包含该物品的数量,名称,联系人,最好有开拍时间及关闭时间,根据用户输入的关键字比如名称,mail,时间等,利用非递归的归并排序对所有的广告进行排序,并列出

所有排好序的广告。

★数据输入

由文件input.txt提供输入的所有广告信息。程序中由用户输入要排序的关键字。

★结果输出

程序运行结束时,排好序的广告输出到文件output.txt中,并为每

个广告添加序号。

输入文件示例输出文件示例

input.txt output.txt

Coat(物品名称)

3(数量)

amail.

Skirt

5

bmail.

Cap

7

cmail.

Bag

12

amail.

Title(用户输入按照title排序)1

Bag

12

amail.

2

Cap

7

cmail.

3

Coat(物品名称)

3(数量)

amail.

4

Skirt

5

bmail.

三、实验环境

操作系统:Windows 7

调试软件名称:Visio Studio2017

上机地点:信息楼B405

四、问题分析

(1)分析要解决的问题,给出你的思路,可以借助图表等辅助表达。

答:归并操作的工作原理如下:

1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的

序列

2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置

3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动

指4.针到下一位置

5. 重复步骤3直到某一指针达到序列尾

6. 将另一序列剩下的所有元素直接复制到合并序列尾

(2)分析利用你的想法解决该问题可能会有怎样的时空复杂度。

时间O(nlogn) 空间O(n)

五、问题解决

(1)描述你在进行实现时,主要的函数或操作内部的主要算法;分析这个算法的时、空复杂度,并说明你设计的巧妙之处,如有创新,将其清

晰的表述.

算法设计:

void MergeSort(int* data, int n){

int step = 1;

while(step < n){

for(int i = 0; i <= n-step-1; i += 2*step)

Merge(data, i, i+step, step, n);

// 将i和i+step这两个有序序列进行合并

// 序列长度为step

// 当i以后的长度小于或者等于step时,退出

step *= 2;

}

}

void Merge(int* data, int a, int b, int length, int n){

int right;

if(b+length-1 >= n-1)

right = n-b;

else

right = length;

int* temp = new int[length+right];

int i = 0,j = 0;

while(i<=length-1&&j<=right-1){

if(data[a+i] <= data[b+j]){

temp[i+j] = data[a+i]; i++;

}

else{

temp[i+j] = data[b+j];

j++;

}

}

if(j == right){// a中还有元素,且全都比b中的大,a[i]还未使

memcpy(data+a+i+j, data+a+i,(length-i)*sizeof(int));

}

memcpy(data+a, temp, (i+j)*sizeof(int) );

delete temp;

}

时间复杂度:时空复杂度:如果输入数据本来就是按非降次序排列的,则根

本不会进入while循环,这就是最好情况,计算时间是O(n)。

(2)针对你所选的问题,你认为应该特别注意哪些方面的处理?比如循环何时结束等。

答:对于什么时候将i和i+step这两个有序序列进行合并以及当i以后的长度小于或者等于step时退出要注意处理。

(3)你在调试过程中发现了怎样的问题?又做了怎样的改进?

在调试过程中,我发现对于相同值的两个物品无法进行排序,这是由于我的算法在设计过程中没有考虑到这种情况,所以在设计标记数组的时候我就设计了能将两个相同值的物品区分开来。

六、实验结果总结

本次实验从写归并排序到实现广告类的排序,都是由自己独立完成,有一整晚没有睡觉都在写这个实验,所以对本次实验的实现过程比较熟悉,而且还增加了对于商品时间的显示和排序。很久没有用C++的我有点儿生疏,刚开始写起来有点慢,但是还是很好得完成了任务,程序中几乎没有任何的BUG。

但是通过本次实验我既加深了对于C++的熟悉程度,也了解到了很多关于归并排序的知识,这些知识对于我以后的程序开发会有比较大的作用,所以我觉得这次实验对我的作用是比较大的。

1.程序运行截图:

实验报告

课程名称:数据结构班级:实验成绩:

实验名称:栈、队列、字符串和数组学号:批阅教师签字:

实验编号:实验四:实验日期:2017-12-18

指导教师:组号:实验时间:18:30~22:30

一、实验目的

(1)熟练掌握动态规划思想及教材中相关经典算法。

(2)掌握用动态规划解题的基本步骤,能够用动态规划解决一些问题。

二、实验内容与实验步骤

(1)仔细阅读备选实验的题目,选择一个(可选多个)作为此次实验题目,设计的程序要满足正确性,代码中有关键的注释,书写格式清晰,简洁易懂,

效率较高,利用C++的模板,设计的程序通用性好,适合各种合理输入,并能对不合理输入做出正确的提示。

(2)可供选择的题目有以下2个:

(i)找零钱问题(难度系数为3)

★问题描述

设有n种不同面值的硬币,各硬币的面值存于数组T[1:n]中。现要用这些面值的硬币来找钱,可以实用的各种面值的硬币个数不限。当只用

硬币面值T[1],T[2],…,T[i]时,可找出钱数j的最少硬币个数记为C(i,j)。

若只用这些硬币面值,找不出钱数j时,记C(i,j)=∞。

★编程任务

设计一个动态规划算法,对1≤j≤L,计算出所有的C( n,j )。算法中只允许实用一个长度为L的数组。用L和n作为变量来表示算法的计算

时间复杂性

★数据输入

由文件input.txt提供输入数据。文件的第1行中有1个正整数n (n<=13),表示有n种硬币可选。接下来的一行是每种硬币的面值。

由用户输入待找钱数j。

★结果输出

程序运行结束时,将计算出的所需最少硬币个数输出到文件output.txt中。

输入文件示例输出文件示例

input.txt output.txt

3

3

1 2 5

9

三、实验环境

操作系统:Windows 7

调试软件名称:Visio Studio2017

上机地点:信息楼B405

四、问题分析

分析要解决的问题,给出你的思路,可以借助图表等辅助表达。

答:这个问题用动态规划来解,归结到动态规划上面就变成了无限背包问题(因为收银台的硬币默认是无穷的,但一种改进版本可以考察有限硬币的情况)。

区别在于,现在我们需要求一个最少的硬币数而不是最大值。但是选择的情况也是相同的,即每次选择都可以选择任何一种硬币。

首先,找零钱问题具有最优子结构性质:

兑换零钱问题的最优子结构表述:对于任意需要找的钱数j ,一个利用T[n]中的n 个不同面值钱币进行兑换零钱的最佳方案为P(T(1),j),

P(T(2),j),...,P(T(n),j),即此时的最少钱币个数∑==n

1j)

P(T(k),),(k j n C ,则

P(T(2),j),...,P(T(n),j)一定是利用T[n]中n 个不同的面值钱币对钱数j=j-P(T(1),j)* T(1)进行兑换零钱的最佳方案。

其次,找零钱问题具有重叠于问题性质:

当n=1时,即只能用一种钱币兑换零钱,钱币的面值为T[0],有

b)当n>1时,

若j>T[n],即第n 种钱币面值比所兑换零钱数小,因此有

}

1])[,({),(min 1+-=≤≤k T j n C j n C n

k 。当k 为

n)

i (1k 0≤≤时,C(n,j)达到最小值,有

P(T(k0),j)=P(T(

k ),j-T(

k ))+1

若j=T[n],即用n 种钱币兑换零钱,第n 种钱币面值与兑换零钱数j 相等,此时有C(n,j)=C(n,T[n])=1;

{

]

[,1]

[,0])[,(),(n T i n T i n T i P j i P =≠=

=

若j

从以上讨论可知该问题具有重叠子问题性质。 根据分析建立正确的递归关系。

0]1[%≠T j {

0]1[%0

]1[%≠=T j T j {∞=]

1[/),1(T j j C

答:

{

T[i];j 0 j)1,-C(i T[i]

j 1)T[i])-j C(i,j),1,-min(C(i j)C(i,<≤≥+=

分析利用你的想法解决该问题可能会有怎样的时空复杂度。

答:算法的时间复杂度主要取决于程序的两个循环,所以算法的时间复杂度

)O(n 2;算法执行过程中引入了一个二维数组,随着输入规模的增大,所需要的空间复杂度为:

)O(n 2

五、问题解决

(1) 根据对问题的分析,写出解决办法。

答:设数组T[]中存放的是n 种钱币递增的不同面值,所要找的钱数为M,M 由用户输入;数组C[j]表示利用数T[n]兑换零钱数为j 时所用的最少钱币个数,即最优值;P[i][j](1<=i<=n)表示按照上述最优值兑换零钱J 时用到钱币面值为第i 种钱币的个数。

(2) 描述你在进行实现时,主要的函数或操作内部的主要算法;分析这个

算法的时、空复杂度,并说明你设计的巧妙之处,如有创新,将其清晰的表述。

#include

using namespace std; int main(){ int c ;

int a25=0,a10=0,a5=0,a2=0,a1=0; cout<<"请输入要找的零钱:"<>c;

a25=(c/25);

a10=(c%25)/10;

a5=(c%25)%10/5;

a2=(c%25)%10%5/2;

a1=(c%25)%10%5%2;

cout<<"需要找以下几种零钱:"<

cout<<"25分的"<

cout<<"10分的"<

cout<<"5分的"<

cout<<"2分的"<

cout<<"1分的"<

时间复杂度:

从上面算法可知,最优值c[』]的计算过程中,最外层为循环for(j=1;j<=M;j++)嵌套着while(k>1&&flag==0)循环,而

while(k>1&flag==0)循环中又嵌套着三个并列的for循环。因此本算法最坏情况下的复杂度是O(M*2n);最好的情况当然是里面for循环的条件不满足而不执行,此时的复杂度为O(M*n)。其中:M表示需要兑换的零钱数,对于M来说,该值一般不是很大,对于钱币来说,M会小于100元,即10 000分;n表示钱币的种类,n值一般不会很大.如钱币总的有13种(从1分,2分,?,100元)。经过以上分析,如是最坏情况时的复杂度应为O(M*2n),则该值对于内存和运行速度较小的自动售货机等的应用前景则不会很好。但本算法中的递归结构在M>T[n]时,

1

])

[

,

(

j),

C(n min

k

1

+

-

=

k

T

j

n

C

n。可见对于钱币j=M时,求c(n,j)时,并

不要求对从1≤i≤j,的所有情况都要求c(n,i)+1,而是只求

1

])

[

,

(+

-k

T

j

n

C。其中:1≤k≤n。钱币一般只有13种左右,因此其效

数据结构实验报告格式

《数据结构课程实验》大纲 一、《数据结构课程实验》的地位与作用 “数据结构”是计算机专业一门重要的专业技术基础课程,是计算机专业的一门核心的关键性课程。本课程较系统地介绍了软件设计中常用的数据结构以及相应的存储结构和实现算法,介绍了常用的多种查找和排序技术,并做了性能分析和比较,内容非常丰富。本课程的学习将为后续课程的学习以及软件设计水平的提高打下良好的基础。 由于以下原因,使得掌握这门课程具有较大的难度: (1)内容丰富,学习量大,给学习带来困难; (2)贯穿全书的动态链表存储结构和递归技术是学习中的重点也是难点; (3)所用到的技术多,而在此之前的各门课程中所介绍的专业性知识又不多,因而加大了学习难度; (4)隐含在各部分的技术和方法丰富,也是学习的重点和难点。 根据《数据结构课程》课程本身的技术特性,设置《数据结构课程实验》实践环节十分重要。通过实验实践内容的训练,突出构造性思维训练的特征, 目的是提高学生组织数据及编写大型程序的能力。实验学时为18。 二、《数据结构课程实验》的目的和要求 不少学生在解答习题尤其是算法设计题时,觉得无从下手,做起来特别费劲。实验中的内容和教科书的内容是密切相关的,解决题目要求所需的各种技术大多可从教科书中找到,只不过其出现的形式呈多样化,因此需要仔细体会,在反复实践的过程中才能掌握。 为了帮助学生更好地学习本课程,理解和掌握算法设计所需的技术,为整个专业学习打好基础,要求运用所学知识,上机解决一些典型问题,通过分析、设计、编码、调试等各环节的训练,使学生深刻理解、牢固掌握所用到的一些技术。数据结构中稍微复杂一些的算法设计中可能同时要用到多种技术和方法,如算法设计的构思方法,动态链表,算法的编码,递归技术,与特定问题相关的技术等,要求重点掌握线性链表、二叉树和树、图结构、数组结构相关算法的设计。在掌握基本算法的基础上,掌握分析、解决实际问题的能力。 三、《数据结构课程实验》内容 课程实验共18学时,要求完成以下六个题目: 实习一约瑟夫环问题(2学时)

数据结构实验答案1

重庆文理学院软件工程学院实验报告册 专业:_____软件工程__ _ 班级:_____软件工程2班__ _ 学号:_____201258014054 ___ 姓名:_____周贵宇___________ 课程名称:___ 数据结构 _ 指导教师:_____胡章平__________ 2013年 06 月 25 日

实验序号 1 实验名称实验一线性表基本操作实验地点S-C1303 实验日期2013年04月22日 实验内容1.编程实现在顺序存储的有序表中插入一个元素(数据类型为整型)。 2.编程实现把顺序表中从i个元素开始的k个元素删除(数据类型为整型)。 3.编程序实现将单链表的数据逆置,即将原表的数据(a1,a2….an)变成 (an,…..a2,a1)。(单链表的数据域数据类型为一结构体,包括学生的部分信息:学号,姓名,年龄) 实验过程及步骤1. #include #include #include #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define ElemType int #define MAXSIZE 100 /*此处的宏定义常量表示线性表可能达到的最大长度*/ typedef struct

{ ElemType elem[MAXSIZE]; /*线性表占用的数组空间*/ int last; /*记录线性表中最后一个元素在数组elem[ ]中的位置(下标值),空表置为-1*/ }SeqList; #include "common.h" #include "seqlist.h" void px(SeqList *A,int j); void main() { SeqList *l; int p,q,r; int i; l=(SeqList*)malloc(sizeof(SeqList)); printf("请输入线性表的长度:"); scanf("%d",&r); l->last = r-1; printf("请输入线性表的各元素值:\n"); for(i=0; i<=l->last; i++) { scanf("%d",&l->elem[i]); } px(l,i); printf("请输入要插入的值:\n");

《数据结构》实验1实验报告

南京工程学院实验报告 <班级>_<学号>_<实验X>.RAR文件形式交付指导老师。 一、实验目的 1. 掌握查找的不同方法,并能用高级语言实现查找算法; 2. 熟练掌握二叉排序树的构造和查找方法。 3. 了解静态查找表及哈希表查找方法。 二、实验内容 设计一个算法读入一串整数,然后构造二叉排序树,进行查找。 三、实验步骤 1. 从空的二叉树开始,每输入一个结点数据,就建立一个新结点插入到当前已生成的二叉排序树中。 2. 在二叉排序树中查找某一结点。 3.用其它查找算法进行排序。

四、程序主要语句及作用 程序1的主要代码 public class BinarySearchTreeNode //二叉查找树结点 { public int key; public BinarySearchTreeNode left; public BinarySearchTreeNode right; public BinarySearchTreeNode(int nodeValue) { key = nodeValue; left = null; right = null; } public void InsertNode(BinarySearchTreeNode node)//插入结点 { if (node.key > this.key) { if (this.right == null) { this.right = node; return; } else this.right.InsertNode(node); } else { if (this.left == null) { this.left = node; return; } else this.left.InsertNode(node); } } public bool SearchKey(int searchValue) { if (this.key == searchValue) return true; if (searchValue > this.key) { if (this.right == null) return false; else return this.right.SearchKey(searchValue); } else { if (this.left == null) return false; else return this.left.SearchKey(searchValue); }

40875][东北大学]20年7月考试《数据结构Ⅱ》考核作业(答案)

东北大学继续教育学院 数据结构II 试卷(作业考核线上1) A 卷 学习中心:奥鹏远程教育沈阳学习中心(直属)[32]院校学号:C09024011930344 姓名何家强 (共 6 页) [ A]1.抽象数据类型的三个组成部分分别为 A.数据对象、数据关系和基本操作 B.数据元素、逻辑结构和存储结构 C.数据项、数据元素和数据类型 D.数据元素、数据结构和数据类型 [ B]2.要求相同逻辑结构的数据元素具有相同的特性,其含义为 A. 数据元素具有同一的特点 B. 不仅数据元素包含的数据项的个数相同,而且其对应数据项的类型要一致 C. 每个数据元素都一样 D. 仅需要数据元素包含的数据项的个数相同 [ D]3.下列各式中,按增长率由小至大的顺序正确排列的是 A.n,n!,2n ,n3/2 B.n3/2,2n,n logn,2100 C.2n,log n,n logn,n3/2 D.2100,logn, 2n, n n [B ]4. 在下列哪种情况下,线性表应当采用链表表示为宜 A.经常需要随机地存取元素 B.经常需要进行插入和删除操作 C.表中元素需要占据一片连续的存储空间 D.表中元素的个数不变 [ C]5.设指针p指向双链表的某一结点,则双链表结构的对称性是 A. p->prior->next=p->next->next; B. p->prior->prior=p->next->prior; C. p->prior->next=p-> next->prior; D. p->next->next= p->prior->prior;

[D ]6. 已知指针p和q分别指向某带头结点的单链表中第一个结点和最后一个结点。假设指 针s指向另一个单链表中某个结点,则在s所指结点之后插入上述链表应执行的语句为 A. s->next=q;p->next=s->next; B. s->next=p;q->next=s->next; C. p->next=s->next;s->next=q; D. q->next=s->next;s->next=p; [A ]7. 栈和队列的共同特点是 A.只允许在端点处插入和删除元素 B.都是先进后出 C.都是先进先出 D.没有共同点 [D ]8. 对于链队列,在进行插入运算时. A. 仅修改头指针 B. 头、尾指针都要修改 C. 仅修改尾指针 D.头、尾指针可能都要修改 [B ]9.设有一个顺序栈的入栈序列是1、2、3,则3个元素都出栈的不同排列个数为 A.4 B.5 C. 6 D. 7 [D ]10.设一个栈的输入序列为A,B,C,D,则借助一个栈所得到的输出序列不可能是 A.A,B,C,D B.D,C,B,A C. A,C,D,B D. D,A,B,C [ C]11.表达式a*(b+c)-d的后缀表达式是 A.abcd*+- B.abc*+d- C.abc+*d- D.-+*abcd [B ]12.某二叉树的先序序列和后序序列正好相反,则该二叉树的特点一定是 A. 空或只有一个结点 B.高度等于其结点数 C. 任一结点无左孩子 D.任一结点无右孩子 [ B]13.下面的说法中正确的是 (1)任何一棵二叉树的叶子结点在种遍历中的相对次序不变。 (2)按二叉树定义,具有三个结点的二叉树共有6种。 A.(1),(2) B.(1) C.(2) D.(1),(2)都错 [ B]14.树有先序遍历和后序遍历,树可以转化为对应的二叉树。下面的 说法正确的是 A.树的后序遍历与其对应的二叉树的先序遍历相同 B.树的后序遍历与其对应的二叉树的中序遍历相同 C.树的先序序遍历与其对应的二叉树的中序遍历相同 D.以上都不对 [D ]15.下列说法正确的是 (1)二又树按某种方式线索化后,任一结点均有前趋和后继的线索 (2)二叉树的先序遍历序列中,任意一个结点均处于其子孙结点前 (3)二叉排序树中任一结点的值大于其左孩子的值,小于右孩子的值 A.(1)(2)(3) B.(1)(2) C.(1)(3) D.都不对 [D ]16. 二叉树的第k层的结点数最多为 A.2k-1 B.2K+1

数据结构实验报告

数据结构实验报告 一.题目要求 1)编程实现二叉排序树,包括生成、插入,删除; 2)对二叉排序树进行先根、中根、和后根非递归遍历; 3)每次对树的修改操作和遍历操作的显示结果都需要在屏幕上用树的形状表示出来。 4)分别用二叉排序树和数组去存储一个班(50人以上)的成员信息(至少包括学号、姓名、成绩3项),对比查找效率,并说明在什么情况下二叉排序树效率高,为什么? 二.解决方案 对于前三个题目要求,我们用一个程序实现代码如下 #include #include #include #include "Stack.h"//栈的头文件,没有用上 typedefintElemType; //数据类型 typedefint Status; //返回值类型 //定义二叉树结构 typedefstructBiTNode{ ElemType data; //数据域 structBiTNode *lChild, *rChild;//左右子树域 }BiTNode, *BiTree; intInsertBST(BiTree&T,int key){//插入二叉树函数 if(T==NULL) { T = (BiTree)malloc(sizeof(BiTNode)); T->data=key; T->lChild=T->rChild=NULL; return 1; } else if(keydata){ InsertBST(T->lChild,key); } else if(key>T->data){ InsertBST(T->rChild,key); } else return 0; } BiTreeCreateBST(int a[],int n){//创建二叉树函数 BiTreebst=NULL; inti=0; while(i

《数据结构》实验报告

苏州科技学院 数据结构(C语言版) 实验报告 专业班级测绘1011 学号10201151 姓名XX 实习地点C1 机房 指导教师史守正

目录 封面 (1) 目录 (2) 实验一线性表 (3) 一、程序设计的基本思想,原理和算法描述 (3) 二、源程序及注释(打包上传) (3) 三、运行输出结果 (4) 四、调试和运行程序过程中产生的问题及采取的措施 (6) 五、对算法的程序的讨论、分析,改进设想,其它经验教训 (6) 实验二栈和队列 (7) 一、程序设计的基本思想,原理和算法描述 (8) 二、源程序及注释(打包上传) (8) 三、运行输出结果 (8) 四、调试和运行程序过程中产生的问题及采取的措施 (10) 五、对算法的程序的讨论、分析,改进设想,其它经验教训 (10) 实验三树和二叉树 (11) 一、程序设计的基本思想,原理和算法描述 (11) 二、源程序及注释(打包上传) (12) 三、运行输出结果 (12) 四、调试和运行程序过程中产生的问题及采取的措施 (12) 五、对算法的程序的讨论、分析,改进设想,其它经验教训 (12) 实验四图 (13) 一、程序设计的基本思想,原理和算法描述 (13) 二、源程序及注释(打包上传) (14) 三、运行输出结果 (14) 四、调试和运行程序过程中产生的问题及采取的措施 (15) 五、对算法的程序的讨论、分析,改进设想,其它经验教训 (16) 实验五查找 (17) 一、程序设计的基本思想,原理和算法描述 (17)

二、源程序及注释(打包上传) (18) 三、运行输出结果 (18) 四、调试和运行程序过程中产生的问题及采取的措施 (19) 五、对算法的程序的讨论、分析,改进设想,其它经验教训 (19) 实验六排序 (20) 一、程序设计的基本思想,原理和算法描述 (20) 二、源程序及注释(打包上传) (21) 三、运行输出结果 (21) 四、调试和运行程序过程中产生的问题及采取的措施 (24) 五、对算法的程序的讨论、分析,改进设想,其它经验教训 (24) 实验一线性表 一、程序设计的基本思想,原理和算法描述: 程序的主要分为自定义函数、主函数。自定义函数有 InitList_Sq、Out_List、ListInsert_Sq、ListDelete_Sq、LocateElem_Sq 、compare。主函数在运行中调用上述的自定义函数,每个自定义函数实现程序的每部分的小功能。 1.程序设计基本思想 用c语言编译程序,利用顺序存储方式实现下列功能:根据键盘输入数据建立一个线性表,并输出该线性表;然后根据屏幕菜单的选择,可以进行数据的插入、删除、查找,并在插入或删除数据后,再输出线性表;最后在屏幕菜单中选择结束按钮,即可结束程序的运行。 2.原理 线性表通过顺序表现,链式表示,一元多项式表示,其中链式表示又分为静态链表,双向链表,循环链表等,在不同的情况下各不相同,他可以是一个数字,也可以是一个符号,通过符号或数字来实现程序的运行。 3.算法描述

数据结构实验总结报告

数据结构实验总结报告 一、调试过程中遇到哪些问题? (1)在二叉树的调试中,从广义表生成二叉树的模块花了较多时间调试。 由于一开始设计的广义表的字符串表示没有思考清晰,处理只有一个孩子的节点时发生了混乱。调试之初不以为是设计的问题,从而在代码上花了不少时间调试。 目前的设计是: Tree = Identifier(Node,Node) Node = Identifier | () | Tree Identifier = ASCII Character 例子:a(b((),f),c(d,e)) 这样便消除了歧义,保证只有一个孩子的节点和叶节点的处理中不存在问题。 (2)Huffman树的调试花了较长时间。Huffman编码本身并不难处理,麻烦的是输入输出。①Huffman编码后的文件是按位存储的,因此需要位运算。 ②文件结尾要刷新缓冲区,这里容易引发边界错误。 在实际编程时,首先编写了屏幕输入输出(用0、1表示二进制位)的版本,然后再加入二进制文件的读写模块。主要调试时间在后者。 二、要让演示版压缩程序具有实用性,哪些地方有待改进? (1)压缩文件的最后一字节问题。 压缩文件的最后一字节不一定对齐到字节边界,因此可能有几个多余的0,而这些多余的0可能恰好构成一个Huffman编码。解码程序无法获知这个编码是否属于源文件的一部分。因此有的文件解压后末尾可能出现一个多余的字节。 解决方案: ①在压缩文件头部写入源文件的总长度(字节数)。需要四个字节来存储这个信息(假定文件长度不超过4GB)。 ②增加第257个字符(在一个字节的0~255之外)用于EOF。对于较长的文件,

会造成较大的损耗。 ③在压缩文件头写入源文件的总长度%256的值,需要一个字节。由于最后一个字节存在或不存在会影响文件总长%256的值,因此可以根据这个值判断整个压缩文件的最后一字节末尾的0是否在源文件中存在。 (2)压缩程序的效率问题。 在编写压缩解压程序时 ①编写了屏幕输入输出的版本 ②将输入输出语句用位运算封装成一次一个字节的文件输入输出版本 ③为提高输入输出效率,减少系统调用次数,增加了8KB的输入输出缓存窗口 这样一来,每写一位二进制位,就要在内部进行两次函数调用。如果将这些代码合并起来,再针对位运算进行一些优化,显然不利于代码的可读性,但对程序的执行速度将有一定提高。 (3)程序界面更加人性化。 Huffman Tree Demo (C) 2011-12-16 boj Usage: huffman [-c file] [-u file] output_file -c Compress file. e.g. huffman -c test.txt test.huff -u Uncompress file. e.g. huffman -u test.huff test.txt 目前的程序提示如上所示。如果要求实用性,可以考虑加入其他人性化的功能。 三、调研常用的压缩算法,对这些算法进行比较分析 (一)无损压缩算法 ①RLE RLE又叫Run Length Encoding,是一个针对无损压缩的非常简单的算法。它用重复字节和重复的次数来简单描述来代替重复的字节。尽管简单并且对于通常的压缩非常低效,但它有的时候却非常有用(例如,JPEG就使用它)。 变体1:重复次数+字符 文本字符串:A A A B B B C C C C D D D D,编码后得到:3 A 3 B 4 C 4 D。

数据结构实验-互联网域名查询实验报告

实验报告 实验课程:数据结构 实验项目:实验三互联网域名查询 专业:计算机科学与技术 班级: 姓名: 学号: 指导教师:

目录一、问题定义及需求分析 (1)问题描述 (2)实验任务 (3)需求分析 二、概要设计: (1)抽象数据类型定义 (2)主程序流程 (3) 模块关系 三、详细设计 (1)数据类型及存储结构 (2)模块设计 四、调试分析 (1)调试分析 (2)算法时空分析 (3)经验体会 五、使用说明 (1)程序使用说明 六、测试结果 (1)运行测试结果截图 七、附录 (1)源代码

一、问题定义及需求分析 (1)实验目的 互联网域名查询 互联网域名系统是一个典型的树形层次结构。从根节点往下的第一层是顶层域,如cn、com等,最底层(第四层)是叶子结点,如www等。因此,域名搜索可以看成是树的遍历问题。 (2)实验任务 设计搜索互联网域名的程序。 (3)需求分析: 1)采用树的孩子兄弟链表等存储结构。 2)创建树形结构。 3)通过深度优先遍历搜索。 4)通过层次优先遍历搜索。 二、概要设计: 采用孩子兄弟链表存储结构完成二叉树的创建; 主程序流程: 创建根节点域名输入域名拆分根据孩子兄弟链表表示的树进行插入调用层次优先遍历输出遍历结果调用深度优先遍历输出遍历结果结束程序 模块关系: 输入域名 创建孩子兄弟树 层次优先遍历输出结果 深度优先遍历输出结果 结束 三、详细设计 孩子兄弟链表结构: typedef struct CSNode{ ElemType data[10]; struct CSNode *firstchild, *nextsibling; }*CSTree;

数据结构实验报告全集

数据结构实验报告全集 实验一线性表基本操作和简单程序 1.实验目的 (1)掌握使用Visual C++ 6.0上机调试程序的基本方法; (2)掌握线性表的基本操作:初始化、插入、删除、取数据元素等运算在顺序存储结构和链表存储结构上的程序设计方法。 2.实验要求 (1)认真阅读和掌握和本实验相关的教材内容。 (2)认真阅读和掌握本章相关内容的程序。 (3)上机运行程序。 (4)保存和打印出程序的运行结果,并结合程序进行分析。 (5)按照你对线性表的操作需要,重新改写主程序并运行,打印出文件清单和运行结果 实验代码: 1)头文件模块 #include iostream.h>//头文件 #include//库头文件-----动态分配内存空间 typedef int elemtype;//定义数据域的类型 typedef struct linknode//定义结点类型 { elemtype data;//定义数据域 struct linknode *next;//定义结点指针 }nodetype; 2)创建单链表

nodetype *create()//建立单链表,由用户输入各结点data域之值,//以0表示输入结束 { elemtype d;//定义数据元素d nodetype *h=NULL,*s,*t;//定义结点指针 int i=1; cout<<"建立一个单链表"<> d; if(d==0) break;//以0表示输入结束 if(i==1)//建立第一个结点 { h=(nodetype*)malloc(sizeof(nodetype));//表示指针h h->data=d;h->next=NULL;t=h;//h是头指针 } else//建立其余结点 { s=(nodetype*) malloc(sizeof(nodetype)); s->data=d;s->next=NULL;t->next=s; t=s;//t始终指向生成的单链表的最后一个节点

数据结构实验报告(2015级)及答案

数据结构实验报告(2015级)及答案

《数据结构》实验报告 专业__信息管理学院______ 年级__2015级___________ 学号___ _______ 学生姓名___ _ _______ 指导老师____________ 华中师范大学信息管理系编

I 实验要求 1.每次实验中有若干习题,每个学生至少应该完成其中的两道习题。 2.上机之前应作好充分的准备工作,预先编好程序,经过人工检查无误后,才能上机,以提高上机效率。 3.独立上机输入和调试自己所编的程序,切忌抄袭、拷贝他人程序。 4.上机结束后,应整理出实验报告。书写实验报告时,重点放在调试过程和小节部分,总结出本次实验中的得与失,以达到巩固课堂学习、提高动手能力的目的。 II 实验内容 实验一线性表 【实验目的】 1.熟悉VC环境,学习如何使用C语言实现线性表的两种存储结构。 2.通过编程、上机调试,进一步理解线性表的基本概念,熟练运用C语言实现线性表基本操作。 3.熟练掌握线性表的综合应用问题。 【实验内容】 1.一个线性表有n个元素(n

的顺序不变。设计程序实现。要求:采用顺序存储表示实现;采用链式存储表示方法实现;比较两种方法的优劣。 2. 从单链表中删除指定的元素x,若x在单链表中不存在,给出提示信息。 要求: ①指定的值x由键盘输入; ②程序能处理空链表的情况。 3.设有头结点的单链表,编程对表中的任意值只保留一个结点,删除其余值相同的结点。 要求: ①该算法用函数(非主函数)实现; ②在主函数中调用创建链表的函数创建一个单链表, 并调用该函数,验证算法的正确性。 LinkedList Exchange(LinkedList HEAD,p)∥HEAD是单链表头结点的指针,p是链表中的一个结点。本算法将p所指结点与其后 继结点交换。 {q=head->next;∥q是工作指针,指向链表中当前待处理结点。 pre=head;∥pre是前驱结点指针,指向q的前驱。 while(q!=null && q!=p){pre=q;q=q->next;} ∥

东北大学数据结构上机实验报告3

实验三树和图应用 一、实验目的 光纤管道铺设施工问题 问题描述 设计校园内有N个教学楼及办公楼,要铺设校园光纤网,如何设计施工方案使得工程总的造价为最省。 二、实验要求 设计校园光纤网铺设的最小生成树模拟程序。 1)采用邻接表或邻接矩阵存储结构。 2)分别采用普利姆算法和克鲁斯卡尔算法实现。 输入形式 对应的教学楼、办公楼数目n,各边权值即每栋楼之间的距离 输出形式 最小生成树,即总路程最小的路 程序功能 设计校园光纤网铺设的最小生成树模拟程序 三、设计概要 流程图 抽象数据类型的定义 class prims { private:

int n; //节点的个数 int graph_edge[99][4]; //图的边 int g; //图中边的个数 int tree_edge[99][4]; //树的边 int t; //树的边的个数 int s; //源节点 int T1[50],t1; // 第一部分 int T2[50],t2; //第二部分 public: void input(); int findset(int); void algorithm(); void output(); }; 各程序模块之间的调用关系 四、详细设计 定义prims类 private中进行对图的创建 public: void input(); int findset(int); void algorithm();

void output(); 开始界面 实现prims类中图的初始化 分别输入图中的顶点个数、图的边及其权值 算法构造 t=0;//初始化边的个数为0 t1=1; T1[1]=1; //资源节点 t2=n-1; int i; for(i=1;i<=n-1;i++) T2[i]=i+1; cout<<"\n\n*****运算开始*****\n\n\n"; while(g!=0 && t!=n-1) { int min=99; int p; int u,v,w; for(i=1;i<=g;i++) { if(findset(graph_edge[i][1])!=findset(graph_edge[i][2])) //如果u和v在不同的部分{ if(min>graph_edge[i][3]) { min=graph_edge[i][3]; u=graph_edge[i][1]; v=graph_edge[i][2]; w=graph_edge[i][3]; p=i; } } } for(int l=p;l

数据结构实验报告模板

2009级数据结构实验报告 实验名称:约瑟夫问题 学生姓名:李凯 班级:21班 班内序号:06 学号:09210609 日期:2010年11月5日 1.实验要求 1)功能描述:有n个人围城一个圆圈,给任意一个正整数m,从第一个人开始依次报数,数到m时则第m个人出列,重复进行,直到所有人均出列为止。请输出n个人的出列顺序。 2)输入描述:从源文件中读取。 输出描述:依次从显示屏上输出出列顺序。 2. 程序分析 1)存储结构的选择 单循环链表 2)链表的ADT定义 ADT List{ 数据对象:D={a i|a i∈ElemSet,i=1,2,3,…n,n≧0} 数据关系:R={< a i-1, a i>| a i-1 ,a i∈D,i=1,2,3,4….,n} 基本操作: ListInit(&L);//构造一个空的单链表表L ListEmpty(L); //判断单链表L是否是空表,若是,则返回1,否则返回0. ListLength(L); //求单链表L的长度 GetElem(L,i);//返回链表L中第i个数据元素的值; ListSort(LinkList&List) //单链表排序 ListClear(&L); //将单链表L中的所有元素删除,使单链表变为空表 ListDestroy(&L);//将单链表销毁 }ADT List 其他函数: 主函数; 结点类; 约瑟夫函数 2.1 存储结构

[内容要求] 1、存储结构:顺序表、单链表或其他存储结构,需要画示意图,可参考书上P59 页图2-9 2.2 关键算法分析 结点类: template class CirList;//声明单链表类 template class ListNode{//结点类定义; friend class CirList;//声明链表类LinkList为友元类; Type data;//结点的数据域; ListNode*next;//结点的指针域; public: ListNode():next(NULL){}//默认构造函数; ListNode(const Type &e):data(e),next(NULL){}//构造函数 Type & GetNodeData(){return data;}//返回结点的数据值; ListNode*GetNodePtr(){return next;}//返回结点的指针域的值; void SetNodeData(Type&e){data=e;}//设置结点的数据值; void SetNodePtr(ListNode*ptr){next=ptr;} //设置结点的指针值; }; 单循环链表类: templateclass CirList { ListNode*head;//循环链表头指针 public: CirList(){head=new ListNode();head->next=head;}//构造函数,建立带头节点的空循环链表 ~CirList(){CirListClear();delete head;}//析构函数,删除循环链表 void Clear();//将线性链表置为空表 void AddElem(Type &e);//添加元素 ListNode *GetElem(int i)const;//返回单链表第i个结点的地址 void CirListClear();//将循环链表置为空表 int Length()const;//求线性链表的长度 ListNode*ListNextElem(ListNode*p=NULL);//返回循环链表p指针指向节点的直接后继,若不输入参数,则返回头指针 ListNode*CirListRemove(ListNode*p);//在循环链表中删除p指针指向节点的直接后继,且将其地址通过函数值返回 CirList&operator=(CirList&List);//重载赋

数据结构实验报告-答案

数据结构(C语言版) 实验报告

专业班级学号姓名 实验1 实验题目:单链表的插入和删除 实验目的: 了解和掌握线性表的逻辑结构和链式存储结构,掌握单链表的基本算法及相关的时间性能分析。 实验要求: 建立一个数据域定义为字符串的单链表,在链表中不允许有重复的字符串;根据输入的字符串,先找到相应的结点,后删除之。 实验主要步骤: 1、分析、理解给出的示例程序。 2、调试程序,并设计输入数据(如:bat,cat,eat,fat,hat,jat,lat,mat,#),测 试程序的如下功能:不允许重复字符串的插入;根据输入的字符串,找到相应的结点并删除。 3、修改程序: (1)增加插入结点的功能。 (2)将建立链表的方法改为头插入法。 程序代码: #include"" #include"" #include"" #include"" typedef struct node . . 示意图:

head head head 心得体会: 本次实验使我们对链表的实质了解更加明确了,对链表的一些基本操作也更加熟练了。另外实验指导书上给出的代码是有一些问题的,这使我们认识到实验过程中不能想当然的直接编译执行,应当在阅读并完全理解代码的基础上再执行,这才是实验的意义所在。

实验2 实验题目:二叉树操作设计和实现 实验目的: 掌握二叉树的定义、性质及存储方式,各种遍历算法。 实验要求: 采用二叉树链表作为存储结构,完成二叉树的建立,先序、中序和后序以及按层次遍历 的操作,求所有叶子及结点总数的操作。 实验主要步骤: 1、分析、理解程序。 2、调试程序,设计一棵二叉树,输入完全二叉树的先序序列,用#代表虚结点(空指针), 如ABD###CE##F##,建立二叉树,求出先序、中序和后序以及按层次遍历序列,求 所有叶子及结点总数。 实验代码 #include"" #include"" #include"" #define Max 20 ertex=a; irstedge=NULL; irstedge; G->adjlist[i].firstedge=s; irstedge; R[i] 留在原位

数据结构实验一 实验报告

班级::学号: 实验一线性表的基本操作 一、实验目的 1、掌握线性表的定义; 2、掌握线性表的基本操作,如建立、查找、插入和删除等。 二、实验容 定义一个包含学生信息(学号,,成绩)的顺序表和链表(二选一),使其具有如下功能: (1) 根据指定学生个数,逐个输入学生信息; (2) 逐个显示学生表中所有学生的相关信息; (3) 根据进行查找,返回此学生的学号和成绩; (4) 根据指定的位置可返回相应的学生信息(学号,,成绩); (5) 给定一个学生信息,插入到表中指定的位置; (6) 删除指定位置的学生记录; (7) 统计表中学生个数。 三、实验环境 Visual C++ 四、程序分析与实验结果 #include #include #include #include #define OK 1 #define ERROR 0 #define OVERFLOW -2

typedef int Status; // 定义函数返回值类型 typedef struct { char num[10]; // 学号 char name[20]; // double grade; // 成绩 }student; typedef student ElemType; typedef struct LNode { ElemType data; // 数据域 struct LNode *next; //指针域 }LNode,*LinkList; Status InitList(LinkList &L) // 构造空链表L { L=(struct LNode*)malloc(sizeof(struct LNode)); L->next=NULL; return OK;

数据结构实验二-

实 验 报 告 一、实验目的 1) 加深对图的表示法和图的基本操作的理解,并可初步使用及操作; 2) 掌握用图对实际问题进行抽象的方法,可以解决基本的问题; 3) 掌握利用邻接表求解非负权值、单源最短路径的方法,即利用Dijkstra 算法求最短 路径,同时掌握邻接表的建立以及使用方法,能够解决相关的问题; 4) 学会使用STL 中的map 抽象实际问题,掌握map ,List,,priority_queue 等的应 用。 二、实验内容与实验步骤 (1) 实验内容: 使用图这种抽象的数据结构存储模拟的欧洲铁路路线图,通过Dijkstra 算法求出欧洲旅行最少花费的路线。该实验应用Dijkstra 算法求得任意两个城市之间的最少路费,并给出路费最少的路径的长度和所经过的城市名。 (2) 抽象数据类型及设计函数描述 1) 抽象数据类型 class City : 维护一个城市的信息,包括城市名name ,是否被访问过的标记visted ,从某个城市到达该城市所需的总费用total_fee 和总路径长度total_distance ,求得最短路径后路径中到达该城市的城市名from_city 。 class RailSystem : 用邻接表模拟欧洲铁路系统,该邻接表使用数据结构map 实现,map 的key-value 课程名称:数据结构 班级: 实验成绩: 实验名称:欧洲旅行 学号: 批阅教师签字: 实验编号:实验二 姓名: 实验日期:2013 年6 月 18 日 指导教师: 组号: 实验时间:

值对的数据类型分别为string和list<*Service>,对应出发城市名和该城市与它能 够到达的城市之间的Service链表。 class Service: 为铁路系统模拟了两个城市之间的直接路线,包括两个城市之间直接到达的费用 fee,两城市之间的直接距离distance。 部分设计函数描述 ●RailSystem(const string& filename) 构造函数,调用load_services(string const &filename)函数读取数据 ●load_services(string const &filename) 读取传入的文件中的数据并建立上述两个map以模拟欧洲铁路路线图 ●reset(void) 遍历cities图,初始化所有城市的信息:visted未访问,total_distance最大 值,total_fee费用最大值,from_city为空 ●~RailSystem(void) 析构函数,用delete将两个map中所有使用new操作符开辟的空间删除 ●void output_cheapest_route(const string& from, const string& to, ostream& out); 输出两城市间的最少费用的路径,调用calc_route(string from, string to)函 数计算最少费用 ●calc_route(string from, string to) 使用Dijkstra算法计算from和to两个城市间的最少费用的路径 (3)采用的存储结构 1)map > outgoing_services 用来保存由一个城市出发可以直接到达的城市名及这两个城市之间的路径信息。 2)list 以service为指针的list表,保存两城市间的路径。 3)map cities 用来保存所有城市信息,通过城市名查找该城市有关信息。 4)priority_queue, Cheapest> candidates 存储候选的遍历城市,City*是优先队列存储的对象类型,vector是该对象的向量集合,Cheapest是比较规则。 三、实验环境 操作系统:Windows 8 调试软件:Microsoft visual studio 2012 上机地点:综合楼311 机器台号:笔记本

数据结构实验报告-答案.doc

数据结构实验报告-答案 数据结构(C语言版)实验报告专业班级学号姓名实验1实验题目:单链表的插入和删除实验目的:了解和掌握线性表的逻辑结构和链式存储结构,掌握单链表的基本算法及相关的时间性能分析。 实验要求:建立一个数据域定义为字符串的单链表,在链表中不允许有重复的字符串;根据输入的字符串,先找到相应的结点,后删除之。 实验主要步骤:1、分析、理解给出的示例程序。 2、调试程序,并设计输入数据(如:bat,cat,eat,fat,hat,jat,lat,mat,#),测试程序的如下功能:不允许重复字符串的插入;根据输入的字符串,找到相应的结点并删除。 3、修改程序:(1)增加插入结点的功能。 (2)将建立链表的方法改为头插入法。 程序代码:#include“stdio.h“#include“string.h“#include“stdlib.h“#include“ctype. h“typedefstructnode//定义结点{chardata[10];//结点的数据域为字符串structnode*next;//结点的指针域}ListNode;typedefListNode*LinkList;//自定义LinkList单链表类型LinkListCreatListR1();//函数,用尾插入法建立带头结点的单链表LinkListCreatList(void);//函数,用头插入法建立带头结点的单链表ListNode*LocateNode();//函数,按值查找结点voidDeleteList();//函数,删除指定值的结点voidprintlist();//函数,打印链表中的所有值voidDeleteAll();//函数,删除所有结点,释放内存

相关文档
最新文档