《软件技术基础》开放式考试试题.docx
《《软件技术基础》开放式考试试题.docx》由会员分享,可在线阅读,更多相关《《软件技术基础》开放式考试试题.docx(18页珍藏版)》请在冰豆网上搜索。
![《软件技术基础》开放式考试试题.docx](https://file1.bdocx.com/fileroot1/2023-1/2/717b5c0a-6e35-41c0-bf18-dc42d757afb6/717b5c0a-6e35-41c0-bf18-dc42d757afb61.gif)
《软件技术基础》开放式考试试题
2010级电气工程及自动化、自动化专业
《软件技术基础》课程开放式考试试题
任课教师:
王初阳
姓名:
闫俊鹏
学号:
100611327
递交日期:
2012.04.23
成绩:
试题
1.总结和比较线性表、堆栈、队列、二叉树、树、图的各种存储结构,并说明它们是如何使用数组和指针的。
(10分)
答:
A)线性表:
线性表的四种存储结构即顺序存储,单链表存储,循环链表存储和双向循环链表存储结构。
其特点为:
(1)线性表中所有元素所占的存储空间是连续的。
(2)线性表中各数据元素在存储空间中是按逻辑顺序依次存放的。
在顺序存储结构下可以进行插入、删除、查找、排序、分解、合并、复制、逆转等操作。
存储时,其插入、删除、顺序输出都是通过数组来实现的。
B)堆栈:
栈是限定在一端进行插入与删除的线性表。
堆栈遵循“先进后出”的原则组织数据的,栈是限定在一端进行插入和删除的线性表,包括栈顶指针和栈底指针,入栈、退栈和读栈都是在栈顶指针执行,当栈顶指针和栈底指针相等时表示为空栈,它具有记忆作用。
堆栈一般可以实现入栈、退栈、读栈顶等运算。
栈有两种存储结构顺序存储结构和链式存储结构。
C)队列:
是指允许在一端进行插入、而在另一端进行删除的线性表。
队列遵循“先进先出”的原则进行入队、退队等运算的,队列的顺序存储结构一般采用循环队列的方式。
既包括入队和退队两种基本运算。
每进行性一次入队运算,队尾指针就进一;每进行一次退队运算,排头指针就进一。
队列有两种存储结构即顺序存储结构和链式存储结构。
它有头指针和尾指针。
队列中插入的元素只能在队尾指针插入,删除的元素只能在队头指针删除,一般采取循环队列的形式,在“上溢”时不能入队,在“下溢”时不能退队。
D)二叉树:
二叉树是非线性结构,即每个数据节点至多有一个前驱,但可以有多个后继。
它可采用顺序存储结构和链式存储结构。
顺序存储结构,就是用一组连续的存储单元存放二叉树中的节点。
链式存储结构,是指用链表来表示一颗二叉树,即用链表指示元素的逻辑关系。
二叉树的每一个结点有一个数据域和两个指针域,两个指针域分别指向左子树和右子树。
它的遍历都是通过指针来实现的。
E)树:
双亲链表表示法
双亲链表表示法利用树中每个结点的双亲唯一性,在存储结点信息的同时,为每个结点附设一个指向其双亲的指针,惟一地表示任何-棵树。
孩子链表表示法
孩子链表表示法是为树中每个结点设置一个孩子链表,并将这些结点及相应的孩子链表的头指针存放在一个向量中。
孩子兄弟链表表示法
孩子兄弟链表表示法是指在存储结点信息的同时,附加两个分别指向该结点最左孩子和右邻兄弟的指针域,即可得树的孩子兄弟链表表示。
注意:
这种存储结构的最大优点是:
它和二叉树的二叉链表表示完全一样。
可利用二叉树的算法来实现对树的操作。
F)图:
如果数据元素集合中的各数据元素之间存在任意的前后件关系,则此数据结构称为图。
图的存储结构有关联矩阵、求值矩阵、邻接表、和临界多重表。
关联矩阵:
关联矩阵可以首先用一个长度为n的一维数组D来存放图中各数据节点信息,再用一个二维数组R来存放图中各节点的关联信息。
其中R称为图的关联矩阵。
在关联矩阵R中,每当一个元素R(i,j)=1时,d(i)是d(j)的前件,当R(i,j)=0时,d(i)不是d(j)的前件。
求值矩阵:
假设有值图有n个节点,则求值矩阵是一个n阶矩阵,其中第i行、第j列的元素V(i,j)表示有值图中第i个结点到第j个结点的求值函数f(di,dj),当第i个结点到dj个结点不存在边时,可以置与求值函数的一切函数值不同的其他值,实际应用中由于一般的求值函数的函数值为正数,因此,当第i个节点到第j个节点不存在边时,置V(i,j)为-1。
邻接表:
也称为“顺序——索引——链接”存储结构,首先,每个存储结点都有一个指针域和一个数据域两个域。
数据域来存放各节点的信息,指针域用于链接相应节点的后件。
其次,对于图中的每一个节点构造一个单链表。
邻接多重表:
在图中每一条边连接了两个节点,每条边用一个存储节点表示,每个存储结点由五个域组成,分别为标志域、两个指针域和与该边关联的两个结点。
2.斐波那契数列问题。
(1)编写求解斐波那契数列中第n个数的递归和非递归c/c++函数;
(2)编写main函数,测试n={10,20,30,40,50}时,上述递归和非递归c/c++函数的执行时间。
(10分)
/*所用的计时器为计算机CPU的计数器,因为第50个数太大了,所以得出的值是错的*/
#include
#include
#include
longdigui(intn)//递归算法,从上往下算
{
longs;
if(n==0||n==1)//递归终止条件
returnn;
else
returns=digui(n-1)+digui(n-2);//根据公式来递归调用
}
longfdigui(intn)//非递归算法,从下往上算
{
longs,i,k,j;
k=0;
j=1;
if(n==0||n==1)
returns=n;
elsefor(i=2;i<=n;i++)//根据公式求得此算法
{
s=k+j;
k=j;
j=s;
}
returns;
}
intmain()
{
LARGE_INTEGERstart,end;
intn,i;
longs;
inta[5]={10,20,30,40,50};
printf("非递归:
\n");
for(i=0;i<5;i++)
{
QueryPerformanceCounter(&start);//得出用cpu计数器表示的时间,开始
s=fdigui(a[i]);//非递归
QueryPerformanceCounter(&end);//得出用cpu计数器表示的时间,开始
printf("第%d个数是:
%ld",a[i],s);
printf("所用时间:
%d\n",end.QuadPart-start.QuadPart);//算出所用时间
}
printf("递归:
\n");//同上
for(i=0;i<5;i++)
{
QueryPerformanceCounter(&start);
s=digui(a[i]);
QueryPerformanceCounter(&end);
printf("第%d个数是:
%ld",a[i],s);
printf("所用时间:
%d\n",end.QuadPart-start.QuadPart);
}
}
3.括号匹配问题。
(1)编写c/c++函数,验证一个字符串形式的表达式中的括号是否匹配,其中括号包括圆括号、方括号和花括号。
(2)编写main函数从键盘读入表达式,并调用你编写的函数。
(10分)
//输入的表达式如果匹配则输出yes,否则输出no
#include
#include
#include
typedefstruct{
charch[100];
intlength;
}biaoda;//一个栈
intcheck(biaoda*p)
{
ints=1;
inti;
biaodaa;
a.length=0;
for(i=0;ilength;i++)
{
if(p->ch[i]=='('||p->ch[i]=='['||p->ch[i]=='{')//将各个左括号存入栈中
{
a.ch[a.length]=p->ch[i];
a.length++;
}
else
{if(p->ch[i]==')'||p->ch[i]==']'||p->ch[i]=='}')//如果是右括号
if(p->ch[i]==']'&&a.ch[a.length-1]!
='['||p->ch[i]==')'&&a.ch[a.length-1]!
='('||p->ch[i]=='}'&&a.ch[a.length-1]!
='{')//检查是否与栈末尾的左括号匹配
s=0;
elsea.length--;//匹配的话则出栈一次
}
if(s==0)
break;
}
if(a.length!
=0)
s=0;
if(s==0)//s为0表示不匹配,否则匹配
printf("NO\n");
else
printf("YES\n");
}
intmain()
{
biaoda*p;
p=(biaoda*)malloc(sizeof(biaoda));
p->length=0;
printf("请循环输入表达式,以00结束:
");//可以检测多个公式
while(gets(p->ch))
{if(p->ch[0]=='0'&&p->ch[1]=='0')//输入公式
break;
p->length=strlen(p->ch);//栈的长度
check(p);
}
}
4.排序问题。
(1)编写简单插入排序和基于二分查找的插入排序算法的c/c++函数;
(2)设待排序数据个数为n,为每个n设计10个随机实例,然后测试当n大于多少时,二基于二分查找的插入排序的平均运行时间比简单插入排序算法的平均运行时间少四分之一。
平均运行时间指对每个n的10个随机实例上的运行时间的平均值。
(15分)
#include
#include
#include
#include
#include
#defineMaxSize100
typedefstruct{
intdata[MaxSize];
intlength;
}Num;//含有一个数组的结构体
voidDirectInsertSort(Num*p)//简单插排法
{
intk,key,i,j;
if(p->length==0)//检验是否为空
{
return;
}
for(i=1;ilength;i++)//从第一个元素开始,将排好的元素放在左边,未排好的放在右边,并依次将右边的插入左边
{
for(j=0;j
{
if(p->data[i]data[j])//从左边开始找,直到找到比插入值大的值
{
key=p->data[i];
for(k=i;k>j;k--)//将插入位置后的数依次后移一位
{
p->data[k]=p->data[k-1];
}
p->data[j]=key;//插入值
break;
}
}
}
}
voidBInsertSort(Num*p)//二分插排法
{
inti,j,low,high,mid,key;
for(i=1;ilength;i++)
{
key=p->data[i];//将R[i]暂存到key
low=0;
high=i-1;
while(low<=high)//在[low..high]中折半查找有序插入的位置
{
mid=(low+high)/2;//折半
if(keydata[mid])
high=mid-1;//插入点在低半区
else
low=mid+1;//插入点在高半区
}
for(j=i-1;j>=high+1;j--)
p->data[j+1]=p->data[j];//记录后移
p->data[high+1]=key;//插入
}
}
intmain()
{
Num*p,*q;//声明两个指针,分别被两种算法用
ints,n=2,i=0,f;
LARGE_INTEGERstart,end;
floatatime1,atime2,avtime1,avtime2;//声明各种时间
p=(Num*)malloc(sizeof(Num));
p->length=0;
q=(Num*)malloc(sizeof(Num));
q->length=0;
printf("首先检验排序法正确不:
\n请输入元素,以00结束:
");//检验排序法
scanf("%d",&s);
while(s!
=00)
{
p->data[p->length++]=s;
scanf("%d",&s);//输入元素
}
printf("\n排序后:
");
BInsertSort(p);//排序
for(s=0;slength;s++)//输出排序后的序列
{
printf("%d",p->data[s]);
}
printf("\n");
p->length=0;
while
(1)
{atime1=0;
atime2=0;
for(i=0;i<10;i++)//循环生成十个有n个数的序列
{
for(s=0;s{
f=(123*rand())%100;
p->data[p->length++]=f;
q->data[q->length++]=f;
}
QueryPerformanceCounter(&start);//用的是CPU的计数器,较为精确
DirectInsertSort(p);
QueryPerformanceCounter(&end);
atime1+=(end.QuadPart-start.QuadPart);
QueryPerformanceCounter(&start);
BInsertSort(q);
QueryPerformanceCounter(&end);
atime2+=end.QuadPart-start.QuadPart;//atime2,atime1是两种算法的运行总时间
}
avtime1=atime1/10;//平均时间
avtime2=atime2/10;
if(avtime2/avtime1<=0.75)//判断是否达到条件
{
printf("当n大于等于%d时,基于二分查找的插入排序的平均运行时间比简单插入排序算法的平均运行时间少四分之一\n",n);
break;//符合条件的话中断循环
}
n++;
}
}
5.二叉树的层次遍历。
设二叉树的存储结构为二叉链表,数据元素类型为整数,
(1)编写二叉树前序建立二叉树的c/c++函数;
(2)编写该二叉树的层次遍历的代码;(3)编写main函数,从文件读入二叉树的前序序列,建立二叉树,并输出层次遍历序列。
(15分)
#include
#include
#defineMaxSize64
typedefstructBiTreeNode{
intdata;
structBiTreeNode*lchild;
structBiTreeNode*rchild;
}BiTreeNode;//节点的结构体
BiTreeNode*createBiTree(){//先序生成二叉树
BiTreeNode*pt;//根节点
intn;
scanf("%d",&n);//输入节点信息
if(n==00)
pt=NULL;//如果输入为00,则返回空值
else{
pt=(BiTreeNode*)malloc(sizeof(BiTreeNode));
pt->data=n;//赋值
pt->lchild=createBiTree();//循环调用
pt->rchild=createBiTree();
}
returnpt;
}
voidLevelOrder(BiTreeNode*b)//层次遍历函数
{
BiTreeNode*p;
BiTreeNode*qu[MaxSize];//建立一个地址数组队列,用来存放节点地址
intfront,rear;
front=rear=-1;
rear++;
qu[rear]=b;//首先存入根节点
while(front!
=rear)//一边存地址,一边存地址,直到全部输出
{
front=(front+1)%MaxSize;
p=qu[front];
printf("%d",p->data);
if(p->lchild!
=NULL)//依次将数组中各个节点的孩子存入数组
{
rear=(rear+1)%MaxSize;
qu[rear]=p->lchild;
}
if(p->rchild!
=NULL)
{
rear=(rear+1)%MaxSize;
qu[rear]=p->rchild;
}
}
}
intmain()
{
BiTreeNode*root;
printf("建立先序二叉树,请输入元素,其中00即为空,且对叶子的孩子也要输入00表示为空,请注意输入:
\n");
root=createBiTree();//建立二叉树
printf("层次遍历:
");
LevelOrder(root);//层次遍历
printf("\n");
}
6.树的层次遍历一。
设树的存储结构为孩子链表,数据元素类型为整数,
(1)编写建立树的c/c++函数;
(2)编写该树的层次遍历的代码;(3)编写main函数,从文件读入并建立树,并输出层次遍历序列。
(20分)
/*输入时请注意不要输错,此代码不能纠错*/
#include
#include
typedefstructcnode
{
intchild;
structcnode*next;
}link;
typedefstruct{
intdata;
link*headptr;
}ctree;
ctreeT[50];
intcreatTree()
{
intn=0,s,m;
link*p,*q;
T[0].headptr=(link*)malloc(sizeof(link));
T[0].headptr->child=1;
T[0].headptr->next=NULL;
printf("请输入你想要生成的树的所有节点值,默认以第一个节点为根节点,以00结束:
");
scanf("%d",&s);//输入各节点元素
while(s!
=00)//输入为00表示输入结束
{
T[++n].data=s;
T[n].headptr=NULL;
scanf("%d",&s);
}
printf("各个元素的序号--值映射是:
");
for(s=1;s<=n;s++)
printf("%d--%d\t",s,T[s].data);//序号--值的映射关系
printf("\n请分别输入各个节点(用序号表示)的孩子的序号,以0结束:
\n");
for(s=1;s<=n;s++)//这个循环表示输入各个节点的孩子
{
printf("%d:
",s);
scanf("%d",&m);
while(m!
=0)//用0表示输入结束
{
p=(link*)malloc(sizeof(link));
p->child=m;
p->next=NULL;
if(T[s].headptr==NULL)
{
T[s].headptr=p;
q=p;
}
else
{
q->next=p;
q=p;
}
scanf("%d",&m);
}
}
returnn;
}
intmain()
{
intn,rear,i,front;
link*p;
p=NULL;
n=creatTree();//生成树的结点个数
intcheck[50]={0};//表示对应的结点是否被访问过
check[0]=1;
ctreeT1[50];//用来顺序存储层次遍历出的树的各个结点
printf("层次遍历:
");
T1[0]=T[0];
T1[1]=T[1];
check[1]=1;
front=1;
rear=1;
/*依次将层次遍历出的树的各个结点放入数组T1*/
for(;rear{
p=T[front].headptr;
while(p!
=NULL)
{
if(check[p->child]==0)
{
T1[++rear]=T[p->child];
check[p->child]=1;//表示被访问过,1表示访问过
}
p=p->next;
if(p==NULL)
break;
}
front++;
}
for(i=1;i<=n;i++)//输出遍历结果
printf("%d",T1[i].data);
}
7.完全二叉树的存储结构变换。
给定一个数组存储的完全二叉树,
(1)编写c/c++函数将完全二叉树的数组存储结构转换为二叉链表;
(2)编写main函数,验证你的转换函数。
(20分)
#include
#include
typedefstruct{
ints[100];
intlength;
}tree;//用数组存储的二叉树
typedefstructnode{
intdata;
structnode*lchild;
structnode*rchild;
}linklist;//用链表存储的二叉树的结点
linklist*change(tree*p)//转换二叉树的存储结构
{
inti;
linklist*q[100];