C语言实现数据结构:栈和队列

第一次上机实验报告

作业题目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定义和宏定义等

代码注释要求:

  1. 对关键的算法实现代码有必要的注释
  2. 函数说明格式:

*****************************************************

函数名:

函数功能:

输入参数:

       类型,参数名,含义

输出参数:

       返回值,含义

文件提交要求:

将两道题目各自的完整工程(包含该工程下所有目录和文件)和此文档一起打包,以组内学生姓名作为文件名,上传提交。例如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;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值