XXXX大学信息学院
课程设计报告
教师签名:xxxxx
题目1实验报告
1.数据结构定义
因为该算法需要用到循环队列、堆和线性表,因此采用以下数据类型:
typedef struct
{
QElemType *base; // 初始化的动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue;//循环队列
typedef struct
{
int *elem;
int length;
int listsize;
}SqList;//堆排序
2.算法说明
void HeapAdjust(int flag,SqList &H,int s,int m)
void HeapSort(int flag,SqList &H)//对H进行堆排序;
Status InitQueue(SqQueue &Q)//构造一个空队列Q,该队列预定义大小为MAXQSIZE;
Status EnQueue(SqQueue &Q,QElemType e) //插入元素e为Q的新的队尾元素;
Status DeQueue(SqQueue &Q, QElemType &e) // 若队列不空, 则删除Q的队头元素, 用e 返回其值, 并返回OK; 否则返回ERROR;
Status GetHead(SqQueue Q, QElemType &e)// 若队列不空,则用e返回队头元素,并返回OK,否则返回ERROR;
Status QueueLength(SqQueue Q) // 返回Q的元素个数;
Status QueueTraverse(SqQueue Q)// 若队列不空,则从队头到队尾依次输出各个队列元素,并返回OK;否则返回ERROR.
3.用户使用说明
运行程序,根据屏幕上的文字提示一步步操作。
4.个人测试结果(截图)
部分测试结果截图
题目2实验报告
用堆栈实现汉诺塔问题的非递归求解抽象数据类型栈(stack)的定义:栈是限定仅在表尾进行插入或删除操作的线性表。
栈又称为后进先出的线性表(简称LIFO结构),对栈来说,表尾端称为栈顶(top),相应的,表头端称为栈底(bottom),不含元素的空表称为空栈。
栈有两种存储表示方法:顺序栈和链栈,本次实验采用栈的顺序存储结构。
n阶汉诺塔问题的描述:假设有3个分别命名为X,Y和Z的塔座,在塔座X上插有n 个直径大小各不相同、依小到大编号为1,2,…,n的圆盘。
现要求将X塔座上的n个圆盘移至Z塔座上并仍按同样顺序叠排,圆盘移动时必须遵循下列规则:
(1)每次只能移动一个圆盘;
(2)圆盘可以插在X、Y和Z中的任一塔座上;
(3)任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。
该道题可以用递归的的方法解决,算法思想如下:
假如只有一个圆盘,即n=1,只需将编号为1的圆盘从X移到Z;
假如n>1,移动的过程可分解为三个步骤:第一步把X上的n-1个圆盘移到Y上,Z 作辅助塔;第二步把X上的一个圆盘移到Z上;第三步把Y上的n-1个圆盘移到Z上,X作辅助塔;其中第一步和第三步是类同的。
C代码的实现如下:
if(n==1)
move(x,z);
else
{
hanoi(n-1,x,z,y);
move(first,third);
hanoi(n-1,y,x,z);
}
下面给出用堆栈实现汉诺塔的非递归解法:
void hanoi(st ta[], long max)//移动汉诺塔的主要函数
{
int k = 0;
int i = 0;
int ch;
while (k < max)
{//按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
ch = ta[i%3].Pop();
ta[(i+1)%3].Push(ch);
cout << ++k << ": " << ta[i%3].name <<
"--->" << ta[(i+1)%3].name << endl;
i++;//把另外两根柱子上可以移动的圆盘移动到新的柱子上
if (k < max)
{//把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小圆盘if (ta[(i+1)%3].Top() == 0 ||
ta[(i-1)%3].Top() > 0 &&
ta[(i+1)%3].Top() > ta[(i-1)%3].Top())
{
ch = ta[(i-1)%3].Pop();
ta[(i+1)%3].Push(ch);
cout << ++k << ": " << ta[(i-1)%3].name
<< "--->" << ta[(i+1)%3].name << endl;
}
else
{
ch = ta[(i+1)%3].Pop();
ta[(i-1)%3].Push(ch);
cout << ++k << ": " << ta[(i+1)%3].name
<< "--->" << ta[(i-1)%3].name << endl;
}
}
}
}
为了保证递归函数正确执行,系统需设立一个“递归工作栈”作为整个递归函数运行期间使用的数据存储区。
每一层递归所需信息构成一个“工作记录”,其中包括所有的实在参数、所有的局部变量以及上一层的返回地址。
每进入一层递归,就产生一个新的工作记录压入栈顶。
每退出一层递归,就从栈顶弹出一个工作记录,则当前执行层的工作记录必是递归工作栈栈顶的工作记录,称这个记录为“活动记录”,并称指示活动记录的栈顶指针为“当前活动指针”。
递归函数结构清晰,程序易懂,而且它的正确性容易得到证明,因此,利用允许递归调用的语言进行程序设计时,给用户编制程序和调试程序带来了很大方便。
不过因为对这样一类递归问题编程时,不需要用户而由系统来管理递归工作栈,不便于用户理解栈的工作原理,也增加了系统的负担,因为递归算法语句虽少,但需要大量的栈空间,运行效率不高;用非递归的方法解决汉诺塔的问题,仅用少量的存储空间克服了递归算法的不足,兼顾了时间与空间的复杂度,提供了解决汉诺塔问题的新方法,缺点是理解起来可能比较困难,可读性也不是很好。
部分测试结果截图:。