第一次上机实验报告
作业题目1:栈的基本操作
程序运行结果截图,需测试各种情况。写出测试过程中遇到的主要问题及所采用的解决措施。
运行结果截图:
主要问题:因为没有提前用elemtype定义,所以在代码编写过程中比较拖沓
解决办法:挨个修改代码中的int类型和char类型,以求得统一
代码:
function.h
#pragma once
#include"stack.h"
void menu();
int InitStack(SqStack& S, int n);
int StackTraverse(SqStack S);
int StackLength(SqStack S);
int GetTop(SqStack S);
int Push(SqStack& S, int e);
int Pop(SqStack& S);
stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef struct {
int* base;
int* top;
int stacksize;
}SqStack;
function.cpp
#include"function.h"
void menu()
{
printf("[1]创建栈\n");
printf("[2]判断是否为空栈\n");
printf("[3]入栈\n");
printf("[4]出栈\n");
printf("[5]取栈顶元素\n");
printf("[6]返回栈的长度\n");
printf("[0]退出\n");
}
int InitStack(SqStack& S, int n) //创建
{
S.base = (int*)malloc(STACK_INIT_SIZE * sizeof(int));
if (!S.base)
{
printf("存储分配失败\n");
return 0;
}
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
printf("输入栈的元素:\n");
for (int i = 1; i <= n; i++)
{
scanf("%d", &*S.top);
S.top++;
}
}
int StackTraverse(SqStack S)//遍历
{
if (S.top == S.base)
{
printf("栈为空\n");
return 0;
}
int* p;
p = S.top;
while (p > S.base)
{
p--;
printf("%d ", *p);
}
printf("\n");
}
int StackLength(SqStack S)//长度
{
int length = 0;
if (S.top == S.base)
{
printf("栈元素的个数为:%d\n", length);
return 0;
}
int* p;
p = S.top;
while (p > S.base)
{
p--;
length++;
}
printf("栈元素的个数为:%d\n", length);
}
int GetTop(SqStack S)//显示栈顶
{
if (S.top == S.base)
{
printf("栈为空\n");
return 0;
}
int* p;
p = S.top;
p--;
printf("%d ", *p);
printf("\n");
}
int Push(SqStack& S, int e)//入栈
{
if (S.top - S.base >= S.stacksize)
{
S.base = (int*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(int));
if (!S.base)
{
printf("存储分配失败\n");
return 0;
}
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top++ = e;
}
int Pop(SqStack& S)//出栈
{
int e;
if (S.top == S.base)
{
printf("栈为空\n");
return 0;
}
else
{
e = *--S.top;
printf("出栈元素为:%d\n", e);
}
}
stack.cpp
#include"function.h"
int main()
{
SqStack S;
int select, i, e, n;
while (1)
{
printf("\n请输入你的操作:\n");
menu();
scanf("%d", &select);
switch (select)
{
case 1:
printf("输入栈的长度:\n");
scanf("%d", &n);
InitStack(S, n);
StackTraverse(S);
break;
case 2:
if (S.top == S.base)
{
printf("栈为空\n");
break;
}
else
{
printf("栈非空\n");
break;
}
case 3:
printf("输入入栈元素\n");
scanf("%d", &e);
Push(S, e);
StackTraverse(S);
break;
case 4:
Pop(S);
StackTraverse(S);
break;
case 5:
printf("栈顶元素为:");
GetTop(S);
StackTraverse(S);
break;
case 6:
StackLength(S);
break;
case 0:
return 0;
default:
printf("输入错误\n");
break;
}
}
return 0;
}
作业题目2:队列的基本操作
程序运行结果截图,需测试各种情况。写出测试过程中遇到的主要问题及所采用的解决措施。
运行结果截图:
主要问题:c++使用不熟练
解决办法:进行百度,学习c++里基本输入输出操作
代码:
line.h
#pragma once
#include<iostream>
#include<cstdlib>
using namespace std;
struct QNode {
int data;
QNode* next;
};
typedef QNode* QueuePtr;
struct LinkQueue {
QueuePtr front;
QueuePtr rear;
};
源.cpp
#include"line.h"
//初始化队列
bool InitQueue(LinkQueue &Q) {
Q.front = Q.rear = new QNode;
if (!Q.front) {
cout << "初始化失败" << endl;
return false;
}
Q.front->next = NULL;
cout << "初始化成功" << endl;
return true;
}
//销毁队列
void DestroyQueue(LinkQueue &Q) {
while (Q.front) {
Q.rear = Q.front->next;
delete (Q.front);
Q.front = Q.rear;
}
cout << "队列已被销毁" << endl;
}
//判断是否为空
bool EmptyQueue(LinkQueue Q) {
if (Q.front == Q.rear) {
cout << "队列为空" << endl;
return true;
}
cout << "队列不为空" << endl;
return false;
}
//入队
void EnQueue(LinkQueue &Q, int value) {
QueuePtr p = new QNode;
p->data = value;
p->next = NULL;
Q.rear->next = p;
Q.rear = p;
cout << value << " 已经入队" << endl;
}
//出队(一)
void DeQueue(LinkQueue &Q, int &value) {
if (Q.front == Q.rear) {
cout << "队列为空" << endl;
return;
}
QueuePtr p = Q.front->next;
//vlaue保存被删的结点数据
value = p->data;
Q.front->next = p->next;
if (Q.rear == p) {//如果p指向的是尾结点
Q.rear = Q.front;
}
delete p;
cout << value << " 已经出队" << endl;
}
//出队(二)
void DeQueue2(LinkQueue &Q, int &value) {
if (Q.front == Q.rear) {
cout << "队列为空" << endl;
return;
}
QueuePtr p = Q.front;
Q.front = Q.front->next;
value = p->data;
delete p;
cout << value << " 已经出队" << endl;
}
//队列元素个数
void GetLength(LinkQueue Q, int &length) {
length = 0;
QueuePtr p = Q.front;
while (p != Q.rear) {
p = p->next;
length++;
}
cout << "队列元素个数" << length << "个" << endl;
}
//显示队列元素
void VisitQueue(LinkQueue Q) {
if (Q.front == Q.rear) {
cout << "队列为空" << endl;
return;
}
QueuePtr p = Q.front;
while (p != Q.rear) {
p = p->next;
cout << p->data << " ";
}
cout << endl;
}
void show() {
cout << "+---------------------------+" << endl;
cout << "| 1->初始化队列 |" << endl;
cout << "| 2->判断队列是否为空 |" << endl;
cout << "| 3->入队 |" << endl;
cout << "| 4->出队 |" << endl;
cout << "| 5->显示队列元素 |" << endl;
cout << "| 6->销毁队列 |" << endl;
cout << "| 7->队列元素个数 |" << endl;
cout << "+---------------------------+" << endl;
}
int main() {
LinkQueue Q;
int action, value, length;
show();
while (cin >> action) {
switch (action) {
case 1:
system("cls");
InitQueue(Q);
break;
case 2:
system("cls");
EmptyQueue(Q);
break;
case 3:
system("cls");
cout << "请输入入队的元素" << endl;
cin >> value;
EnQueue(Q, value);
break;
case 4:
system("cls");
DeQueue(Q, value);
break;
case 5:
system("cls");
VisitQueue(Q);
break;
case 6:
system("cls");
DestroyQueue(Q);
break;
case 7:
system("cls");
GetLength(Q, length);
}
system("pause");
show();
}
}
作业题目3:火车车厢的调度模拟
1.题目描述:
设火车车厢分为3类:硬座、硬卧、软卧,分别用ABC表示。下图描述车厢调度的示意图,图中右端为排列无序的车厢,左端为调度后的车厢排列,使得所有软卧车厢中最前面,所有硬卧车厢中中间,所有硬座车厢中最后。选择合适的存储结构,编程模拟上述车厢调度过程,右端车辆进入用相应的字符串给出,例如“BBACBCAABBCAA”,得到“CCCBBBBBAAAAA”的输出。
2.问题分析:
(1)程序的功能要求;用栈和队列实现字符串的重新排列
(2)程序的界面设计:显示:任意输入一串字符,其中A表示硬座,B表示硬卧,C表示软卧
(3)程序的错误处理:当输入的数不为char类型时,无输出值
1.数据类型设计:
struct Stack {
ElemType* stack;
int top1, top2;//表示栈顶元素的位置
}S;
typedef struct qNode
{
char data;
struct qNode* next;
} QNode, * QueuePtr;
typedef struct {
QNode* front;//队头指针
QNode* rear;//队尾指针
}LinkQueue;
2.算法设计(算法的基本思想、具体步骤,各程序模块之间的层次(调用)关系流程图等):用一个队列和两个栈,若是“A”或者“B”,则分别进入两栈,最后遍历到最后一个“C”之后,再进行入队列并且输出的操作。
3.测试分析
设计测试范例(测试数据包括正确的输入、边界条件、含有错误的输入等),列出程序的测试结果(附截图),测试结果的分析与讨论。可列出测试过程中遇到的主要问题及所采用的解决措施。
4.心得
对实验设计与实现过程的回顾和分析,说明程序的改进思想、经验和体会。
写代码要思路清晰,不然会把自己绕进去。
在前期的设定一定要清晰,不然会给后期带来极大的麻烦。
5.附录
列出程序文件清单,及文件功能。
头文件:
LinkQueue:放函数的操作
源文件:
TRAIN.cpp:放主函数的操作以及结构类型定义,typedef定义和宏定义等
代码注释要求:
- 对关键的算法实现代码有必要的注释
- 函数说明格式:
*****************************************************
函数名:
函数功能:
输入参数:
类型,参数名,含义
输出参数:
返回值,含义
文件提交要求:
将两道题目各自的完整工程(包含该工程下所有目录和文件)和此文档一起打包,以组内学生姓名作为文件名,上传提交。例如Stu1_Stu2.zip
代码:
LinkQueue.h
#pragma once
Status InitStack(Stack& S)//构造一个空栈
{
S.stack = (ElemType*)malloc(MaxSize * sizeof(ElemType));
if (!S.stack) exit(OVERFLOW);
S.top1 = -1;
S.top2 = MaxSize;
return OK;
}
/***************************
函数名:InitStack
函数功能:构造一个空栈
输入参数:Stack,S,栈
类型,参数名,含义
输出参数:Status,创建好的S栈
返回值,含义
****************************/
Status Push(Stack& S, int k, ElemType e)//进栈。当k=1或2时对应向栈1或栈2的顶端插入元素e
{
if (S.top1 == S.top2 - 1) {
printf("存储空间已用完!\n");
return ERROR;
}
if (k == 1) {
S.top1++;
S.stack[S.top1] = e;
}
else if (k == 2) {
S.top2--;
S.stack[S.top2] = e;
}
return OK;
}
/***************************
函数名:Push
函数功能:进栈。当k=1或2时对应向栈1或栈2的顶端插入元素e
输入参数:Stack,S,栈
int,k,进栈位置
ElemType,e,进栈元素
类型,参数名,含义
输出参数:Status,创建好的S栈
返回值,含义
****************************/
Status Pop(Stack& S, int k, ElemType& e)//出栈。若栈不为空,根据k的值删除栈1或栈2的栈顶元素,用e返回其值
{
if (k == 1) {
if (S.top1 == -1) {
return ERROR;
}
e = S.stack[S.top1];
S.top1--;
return OK;
}
else if (k == 2) {
if (S.top2 == MaxSize) {
return ERROR;
}
e = S.stack[S.top2];
S.top2++;
return OK;
}
else {
printf("k的值不正确!");
return ERROR;
}
}
/***************************
函数名: Pop
函数功能:出栈。若栈不为空,根据k的值删除栈1或栈2的栈顶元素,用e返回其值
输入参数:Stack,S,栈
int,k,出栈位置
ElemType,e,出栈元素
类型,参数名,含义
输出参数:Status,创建好的S栈
返回值,含义
****************************/
Status InitQueue(LinkQueue& q)//构造一个空队列q
{
q.front = q.rear = (QueuePtr)malloc(sizeof(QNode));
if (!q.front) exit(OVERFLOW);
q.front->next = NULL;
return OK;
}
/***************************
函数名:InitQueue
函数功能:构造一个空队列q
输入参数:LinkQueue,q,创建好的队列
类型,参数名,含义
输出参数:Status,创建好的q队列
返回值,含义
****************************/
Status EnQueue(LinkQueue& q, ElemType e)//插入元素e为q的新的队尾元素
{
QueuePtr p = (QueuePtr)malloc(sizeof(QNode));
if (!p)
exit(OVERFLOW);
p->data = e;
p->next = NULL;
q.rear->next = p;
q.rear = p;
return OK;
}
/***************************
函数名:EnQueue
函数功能:插入元素e为q的新的队尾元素
输入参数:LinkQueue,q,插入的队列
ElemType,e,插入的元素
类型,参数名,含义
输出参数:Status,创建好的q队列
返回值,含义
****************************/
Status DeQueue(LinkQueue& q, ElemType& e)//若队列不空,则删除q的队头元素,用e返回其值,并返回OK;否则返回ERROR
{
if (q.front == q.rear)
return ERROR;
QueuePtr p;
p = q.front->next;
e = p->data;
q.front->next = p->next;
if (q.rear == p)
q.rear = q.front;
free(p);
return OK;
}
/***************************
函数名:DeQueue
函数功能:若队列不空,则删除q的队头元素,用e返回其值,并返回OK;否则返回ERROR
输入参数:LinkQueue,q,等待被删除的队列
ElemType,e,已经被删除的队头元素
类型,参数名,含义
输出参数:Status,创建好的q队列
返回值,含义
****************************/
Status DestroyQueue(LinkQueue& q)//销毁队列q
{
while (q.front)
{
q.rear = q.front->next;
free(q.front);
q.front = q.rear;
}
return OK;
}
/***************************
函数名:DestroyQueue
函数功能:销毁队列q
输入参数:LinkQueue,q,等待销毁的队列
类型,参数名,含义
输出参数:Status,创建好的q队列
返回值,含义
****************************/
TRAIN.cpp
#include<stdio.h>
#include<stdlib.h>
typedef char ElemType;
typedef int Status;
#define OK 1
#define ERROR 0
#define MaxSize 20
#define OVERFLOW -2
struct Stack {
ElemType* stack;
int top1, top2;//表示栈顶元素的位置
}S;
typedef struct qNode
{
char data;
struct qNode* next;
} QNode, * QueuePtr;
typedef struct {
QNode* front;//队头指针
QNode* rear;//队尾指针
}LinkQueue;
#include "LinkQueue.h"
int main() {
LinkQueue q;
InitQueue(q);//构造一个空队列Q
InitStack(S);//构造一个空栈S
char a[100], e;
int i = 0, m = 0, n = 0;//m表示字符'B'的个数,n表示字符'A'的个数
printf("任意输入一串字符,其中A表示硬座,B表示硬卧,C表示软卧\n");
scanf("%s", a);
while (a[i] == 'A' || a[i] == 'B' || a[i] == 'C') {
if (a[i] == 'B') {//字符'B'进入栈1
e = a[i];
m++;
Push(S, 1, a[i]);
}
if (a[i] == 'A') {//字符'A'进入栈2
e = a[i];
n++;
Push(S, 2, a[i]);
}
i++;
if (m + n == MaxSize) {
printf("共享栈存储空间已用完!\n");
exit(0);
}
if (a[i] == 'C') {
e = a[i];
EnQueue(q, e);//字符'C'进队列
}
}
while (Pop(S, 1, e))//栈1中的元素依次出栈进队列
EnQueue(q, e);
while (Pop(S, 2, e))//栈2中的元素依次出栈进队列
EnQueue(q, e);
if (q.front == q.rear)//空队列
return 0;
QueuePtr p = q.front->next;
while (p != q.rear) //非空队列
{
printf("%c", p->data);
p = p->next;
}
printf("%c", p->data);
printf("\n");
return 0;
}