算法与数据结构.docx

上传人:b****6 文档编号:6884580 上传时间:2023-01-12 格式:DOCX 页数:34 大小:394.72KB
下载 相关 举报
算法与数据结构.docx_第1页
第1页 / 共34页
算法与数据结构.docx_第2页
第2页 / 共34页
算法与数据结构.docx_第3页
第3页 / 共34页
算法与数据结构.docx_第4页
第4页 / 共34页
算法与数据结构.docx_第5页
第5页 / 共34页
点击查看更多>>
下载资源
资源描述

算法与数据结构.docx

《算法与数据结构.docx》由会员分享,可在线阅读,更多相关《算法与数据结构.docx(34页珍藏版)》请在冰豆网上搜索。

算法与数据结构.docx

算法与数据结构

数据结构与算法课程设计

 

题目:

集合运算问题;计算1的个数问题;递归替换问题;图的基本操作与实现

目录

摘要4

一.集合运算问题5

1.采用类语言定义相关的数据类型5

2.算法设计5

3.函数的调用关系图(如图1)6

4.调试分析7

5.测试结果7

6.源程序(带注释)9

二.计算1的个数问题17

1.采用类语言定义相关的数据类型17

2.算法设计17

3.函数的调用关系图17

4.调试分析17

5.测试结果18

6.源程序(带注释)18

三.递归替换问题19

1.数据结构设计19

2.算法设计20

3.函数的调用关系图21

4.调试分析22

5.测试结果22

6.源程序(带注释)22

四、图的基本操作与实现25

1.设计概要25

2.算法设计26

3.函数的关系调用图26

4.调试分析26

5.测试结果26

6.源程序(带注释)28

总结39

参考文献40

致谢41

摘要

集合运算问题:

使用链表来表示集合,完成集合的合并,求交集等操作。

初步完成总体设计,搭好框架,确定函数个数;完成最低要求;继续完成进一步要求;界面友好,函数功能要划分好;总体设计应画流程图;程序要加必要的注释;要提供程序测试方案。

计算1的个数问题:

N为正整数,计算从1到N的所有整数中包含数字1的个数。

比如,N=10,从1,2...10,包含有2个数字1。

相信很多人都能立刻得出以下的解法这是最直接的解法,但遗憾的是,时间复杂程度为O(N*logN)。

因为还需要循环判断当前的n的各位数,该判断的时间复杂程度为O(logN)。

接下来就应该思考效率更高的解法了。

说实话,这道题让我想起另外一道简单的算法题:

N为正整数,计算从1到N的整数和。

递归替换问题:

程序调用自身的编程技巧称为递归(recursion)。

递归做为一种算法在程序设计语言中广泛应用。

一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。

递归的能力在于用有限的语句来定义对象的无限集合。

一般来说,递归需要有边界条件、递归前进段和递归返回段。

当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

图的基本操作与实现:

图的广度优先遍历:

采取邻接矩阵结构,指定任意顶点x为初始顶点,利用顺序循环队列以保持访问过的结点的顺序1.首先访问初始结点v并标记结点v为已访问;2.结点v入队列;3.当队列非空时则继续执行,否则算法结束;4.出队列取得队头结点u;5.查找u的第一个邻接结点w6.若u的邻接结点w不存在则转到步骤3,否则循环执行下列步骤:

6.1若结点w尚未被访问,则访问结点w并标记结点w为已访问;6.2结点w入队列;6.3查找结点u的w邻接结点的下一个邻接结点w,转到步骤6

关键词:

集合运算;递归程序,十进制数;递归,无限集合;广度优先,深度优先。

一.集合运算问题

设计一个程序,实现两个集合的并集、交集、差集、显示输出等,要求结果集合中的元素不重复;实现一个集合的幂集的求解。

1.采用类语言定义相关的数据类型

定义一个结构体存储结构,用来生成求幂集的二叉树只在求幂集函数内使用

typedefstruct//根节点结构体(幂集使用)

{

intdata[MAX];

intlength;

}root;

定义一个二维数组,用来存储节点选择情况,其第一个下标表示是左孩子还是右孩子,第二个表示节点当前所处的层数

intc[2][MAX];//c构造数据池

2.算法设计

程序执行的命令包括:

定义单链表结点类型typedefstructLNode

(2)运用尾插法建立单链表voidCreatListR(LinkList*&L,ElemTypea[],intn)

(3)创建头结点,为头结点分配空间

(4)创建新结点

(5)建立有序链表voidSort(LinkList*&head)

(6)将两个集合的元素进行比较while语句

(7)删除有序链表中的重复元素voidshanchu(LinkList*&head)

(8)求交集voidjiao(structLnode**L1,structLnode**L2,structLnode**L3)

(9)求并集voidbing(structLnode**L1,structLnode**L2,structLnode**L3)

(10)输出单链表voidDisplay(LinkList*L)

3.函数的调用关系图(如图1)

图1-1

4.调试分析

a、输入集合数据的时候必须要一个一个输,不能依次输入很多,否则会引起错误

b、算法的时间复杂度O(n^2)。

5.测试结果

图1-2

图1-3

图1-4

6.源程序(带注释)

/*实现两个集合的并集、交集、差集,实现一个集合的幂集的求解。

程序中的线性表L1、L2分别为集合L1、L2,线性表L3为计算后的集合*/

#include

#defineMAXSIZE10//线性表的最大长度

typedefintElemType;

typedefstruct{//线性表的结构体

ElemTypedata[MAXSIZE];

intlength;

}SqList;

////////////////线性表的操作函数//////////////////////////////

voidInitList(SqList*L){//初始化线性表

L->data==NULL;

L->length=0;

}

intListInsert(SqList*L,inti,ElemTypee){//向表中插入元素

intk;

if(i<=L->length){//如果不在表尾插入

for(k=L->length-1;k>=i-1;k--){

L->data[k+1]=L->data[k];

}

L->data[i-1]=e;

L->length++;

return1;

}

else{//如果在表尾插入

L->data[i-1]=e;

L->length++;

return1;

}

}

voidErgList(SqList*L){//遍历线性表并依次返回元素

intj;

ElemTyperes_date;

for(j=0;jlength;j++){

res_date=L->data[j];

printf("%4d",res_date);

}

printf("\n");

}

////////////////该程序的操作函数/////////////////////////////////

intmenu(){//菜单函数

intm_cho;

system("cls");

printf("--------MENU--------\n");

printf("1->给集合L1和集合L2添加元素\n");

printf("2->查看集合L1,L2\n");

printf("3->求L1与L2的并集\n");

printf("4->求L1与L2的交集\n");

printf("5->求L1与L2的差集\n");

printf("6->求L1的冥集\n");

printf("7->求L2的冥集\n");

printf("8->退出系统\n");

printf("--------------------\n");

printf("--请输入序号:

[]\b\b");

scanf("%d",&m_cho);

if(1<=m_cho&&m_cho<=6)

returnm_cho;

else{

system("cls");

exit();

return0;

}

}

voidoperate1(SqList*L1,SqList*L2){//处理序号1

inti;

ElemTypeins_e[5];

printf("请输入集合L1中的元素(仅限整数):

\n");

for(i=0;i<5;i++){//接受集合L1的元素

scanf("%d",&ins_e[i]);

ListInsert(L1,i+1,ins_e[i]);

}

printf("请输入集合L2中的元素(仅限整数):

\n");

for(i=0;i<5;i++){//接受集合L2的元素

scanf("%d",&ins_e[i]);

ListInsert(L2,i+1,ins_e[i]);

}

}

voidoperate2(SqList*L1,SqList*L2){//处理序号2

printf("-------查看元素-------\n");

printf("集合L1:

");

ErgList(L1);

printf("集合L2:

");

ErgList(L2);

printf("----------------------\n");

}

voidoperate3(SqList*L1,SqList*L2,SqList*L3){//处理序号3

inti,j;

InitList(L3);//初始化L3

*L3=*L1;

for(i=0;ilength;i++){//将L2中的元素放入L3中且无重复元素

for(j=0;jlength;j++){

if(L3->data[j]==L2->data[i])//选择存在于L2但不存在于L3的元素

break;

else{

if(j==L3->length-1)

ListInsert(L3,L3->length+1,L2->data[i]);

else

continue;

}

}

}

printf("-------求并集结果-------\n");

ErgList(L3);

printf("-----------------------\n");

}

voidoperate4(SqList*L1,SqList*L2,SqList*L3){//处理序号4

inti,j;

ElemTyperes_date;

InitList(L3);//初始化L3

for(i=0;ilength;i++){//将属于L1同时也属于L2的元素赋值给L3

res_date=L1->data[i];

for(j=0;jlength;j++){

if(res_date==L2->data[j]){

L3->data[L3->length]=res_date;

L3->length++;

break;

}

}

}

printf("-------求交集结果-------\n");

ErgList(L3);

printf("-----------------------\n");

}

voidoperate5(SqList*L1,SqList*L2,SqList*L3){//处理序号5

inti,j;

ElemTyperes_date;

InitList(L3);//初始化L3

for(i=0;ilength;i++){//将属于L1但不属于L2的元素赋值给L3

res_date=L1->data[i];

for(j=0;jlength;j++){

if(res_date==L2->data[j]){

break;

}

else{

if(j==L2->length-1){

L3->data[L3->length]=res_date;

L3->length++;

}

else

continue;

}

}

}

printf("-------求差集结果-------\n");

ErgList(L3);

printf("-----------------------\n");

}

voidoperate6(SqList*L1,SqList*L3){//处理序号6

}

voidoperate7(SqList*L2,SqList*L3){//处理序号7

}

intmain(){

intc;

charres;

SqListL1,L2,L3;//定义线性表L1,L2,L3

InitList(&L1);//初始化线性表

InitList(&L2);

InitList(&L3);

start:

c=menu();

switch(c){//处理所选的操作

case1:

{

operate1(&L1,&L2);

printf(">>>元素输入成功!

0_0\n");

printf(">>>按ENTER键返回...");

scanf("%c",&res);

scanf("%c",&res);

gotostart;

}

case2:

{

operate2(&L1,&L2);

printf(">>>元素查看成功!

0_0\n");

printf(">>>按ENTER键返回...");

scanf("%c",&res);

scanf("%c",&res);

gotostart;

}

case3:

{

operate3(&L1,&L2,&L3);

printf(">>>L1与L2求并集成功!

0_0\n");

printf(">>>按ENTER键返回...");

scanf("%c",&res);

scanf("%c",&res);

gotostart;

}

case4:

{

operate4(&L1,&L2,&L3);

printf(">>>L1与L2求交集成功!

0_0\n");

printf(">>>按ENTER键返回...");

scanf("%c",&res);

scanf("%c",&res);

gotostart;

}

case5:

{

operate5(&L1,&L2,&L3);

printf(">>>L1与L2求差集成功!

0_0\n");

printf(">>>按ENTER键返回...");

scanf("%c",&res);

scanf("%c",&res);

gotostart;

}

case6:

{

operate6(&L1,&L3);

printf(">>>求L1的冥集成功!

0_0\n");

printf(">>>按ENTER键返回...");

scanf("%c",&res);

scanf("%c",&res);

gotostart;

}

case7:

{

operate7(&L2,&L3);

printf(">>>求L2的冥集成功!

0_0\n");

printf(">>>按ENTER键返回...");

scanf("%c",&res);

scanf("%c",&res);

gotostart;

}

}

return0;

}

二.计算1的个数问题

1.采用类语言定义相关的数据类型

2.算法设计

if(N==1) n=1;  

else if((N+1)%2==0) n=count(N/2)+1;//奇数情况    若N是奇数,那么它的二进制中1的个数等于N/2的二进制中1的个数加1,  

else if(N%2==0) n=count(N+1)-1;//偶数情况     若N是奇数,N-1是偶数,比N少一个最低位的1,1的个数就是N/2的二进制中1的个数-1 

 return n; 

3.函数的调用关系图

4.调试分析

调试过程中开始由于某个地方的分号没打上。

出现了错误的提示。

然后经过一番调试,找到了症结所在,测试数据时使用了多组数据,并用笔算了一下,看输出序列是否与实际有偏差,因为程序有时候会运行正确,但这并不确定输出正确,实践是检验真理的唯一标准。

5.测试结果

6.源程序(带注释)

#include

intcount(intN){

intn;

if(N==1)

n=1;

elseif((N+1)%2==0)

n=count(N/2)+1;//奇数情况,若N是奇数,那么它的二进制中1的个数等于N/2的二进制中1的个数加1;

elseif(N%2==0)

n=count(N+1)-1;//偶数情况,若N是奇数,,N-1是偶数,比N少一个最低位的1,1的个数就是N/2的二进制中1的个数-1

returnn;

}

voidmain()

{

intN;

printf("请输入数字:

");

scanf("%d,&N");

printf("二进制中1的个数:

%d\n",count(N));

}

 

三.递归替换问题

1.、数据结构设计

typedefstruct//创建结构体,让文件的读写方便

{

chardata[MAX];//数据项

}char1;

int

print(charch[MAX],intn)//递归函数

2.算法设计

{

FILE*fp,*fp1;

chars[MAX];//s,存储#后面的include

char1b[MAX];//b,文件中内容在内存中的存储位置

inti=0,k,d=0,j,flag;//switch参数,用于确认调用函数的参数

if((fp=fopen(ch,"rb+"))==NULL)

{

printf("文件打开失败!

\n");

exit(0);

}

while(!

feof(fp))

{

fread(&b[i],1,sizeof(char1),fp);

i++;

if(b[i-1].data[0]=='}')//结构体数组计数器

break;

}

k=i-1;//记录b大小,可以认为是对应文件的行数

fclose(fp);

3.函数的调用关系图

 

4.调试分析

5.测试结果

6.源程序(带注释)

#include

#include

#include

#defineMAX100

typedefstruct//创建结构体,让文件的读写方便

{

chardata[MAX];//数据项

}char1;

int

print(charch[MAX],intn)//递归函数

{

FILE*fp,*fp1;

chars[MAX];//s,存储#后面的include

char1b[MAX];//b,文件中内容在内存中的存储位置

inti=0,k,d=0,j,flag;//switch参数,用于确认调用函数的参数

if((fp=fopen(ch,"rb+"))==NULL)

{

printf("文件打开失败!

\n");

exit(0);

}

while(!

feof(fp))

{

fread(&b[i],1,sizeof(char1),fp);

i++;

if(b[i-1].data[0]=='}')//结构体数组计数器

break;

}

k=i-1;//记录b大小,可以认为是对应文件的行数

fclose(fp);

if((fp1=fopen("辅助.c","ab+"))==NULL)

{

printf("文件打开失败!

\n");

exit(0);

}

d=0;//s数组存取计数器

for(i=0;i

{

if(b[i].data[0]=='#')//发现include,递归调用print

{

for(j=2;j<9;j++)

{

s[d]=b[i].data[j];

d++;

}

if((strcmp(s,"include"))==0)

{

flag=b[i].data[19]-'0';

switch(flag)//带选择的递归调用

{

case1:

fp=print("filename1.c",1);break;

case2:

fp=print("filename2.c",2);break;

case3:

fp=print("filename3.c",3);break;

default:

break;

}

}

else//否则的话讲代码存入辅助文件

{

printf("%s\n",b[i].data);

fwrite(&b[i],1,sizeof(char1),fp);

fputc('\r',fp);

fputc('\n',fp);

}

}

else//否则的话讲代码存入辅助文件

{

printf("%s\n",b[i].data);

fwrite(&b[i],1,sizeof(char1),fp1);

fputc('\r',fp);

fputc('\n',fp);

}

}

close(fp1);

return0;

}

四、图的基本操作与实现

1.设计概要

(1)自选存储结构,输入含n个顶点(用字符表示顶点)和e条边的图G;

(2)求每个顶点的度,输出结果;

(3)指定任意顶点x为初始顶点,对图G作DFS遍历,输出DFS顶点序列(提示:

使用一个栈实现DFS);

(4)指定任意顶点x为初始顶点,对图G作BFS遍历,输出BFS顶点序列(提示:

使用一个队列实现BFS);

(5)输入顶点x,查找图G:

若存在含x的顶点,则删除该结点及与之相关连的边,并作DFS遍历(执行操作

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 唐诗宋词

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1