数据结构实验:栈与队列的储存与操作&&基于字符串匹配算法的病毒感染检测问题

实验二  栈与队列的储存与操作

说明:由于本次实验分数据结构(栈与队列)的基本操作、附加实验:基字符串模式匹配算法的病毒感染检测问题,同时栈的储存与操作又分为顺序栈和链栈两个部分,故该实验报告分为了:顺序栈的储存与操作、链栈的储存与操作、队列的储存与操作、附加实验等四个部分

一、顺序栈的储存与操作

(一)实验目的

1.理解栈是限定只能在栈顶进行操作的线性表;

2.理解栈的存储结构特点,掌握栈的存储分配要点;

3.掌握栈的基本操作及实现,深刻领会栈操作的后进先出特征,并能正确分析其时间复杂度,知道栈性能优于普通线性表及栈的常用情况。

(二)实验内容

实验具体内容:

1.  定义顺序栈的存储结构:(私有)数据封装(一维)数组(存储数据元素,位置/下标表示数据元素之间的逻辑关系,不占用存储空间)和栈顶指针(整型变量,存储栈顶下标),栈底默认为数组的某一端,不占用存储空间;

2.  顺序栈的基本操作

(1)初始化顺序栈;

(2)数据元素入栈;

(3)数据元素出栈;

(4)读栈顶元素;

(5)判定栈空/满操作;

(6)销毁顺序栈。

实验需求分析:

在理解顺序栈逻辑结构及储存特点的基础上,设计、编写一段完整代码,该代码能够详细定义顺序栈的储存结构,同时完成实验具体内容中所要求的顺序栈的基本操作。在此基础上,从算法思想及时间、空间复杂度的角度对代码进行优化,并获得关于“顺序栈的储存与操作”的最优化代码。

预期结果:

完成实验指导书中所要求的具体实验内容,并对其进行优化。

(三)算法思想与时间复杂度

顺序栈在应用中涉及生长方向和栈顶是否存储有效值共有4种情况,常见台式机的系统栈是向下生长、栈顶存储有效值。本次实验实现向上生长、栈顶存储有效值的顺序栈。

1. 初始化顺序栈:栈底端的边界外,栈底为低端0,栈顶即为-1;

2. 数据元素入栈:栈不满,先增加栈顶,再存储数据元素,时间复杂度为O(1);

3. 数据元素出栈:栈不空,先读数据元素,再减栈顶指针,时间复杂度为O(1);

4. 读栈顶元素:栈不空,读数据元素,不动栈顶指针,时间复杂度为O(1);

5. 判定栈空/满操作:栈顶为-1/数组长度减1。

(四)实验方法

1. 栈的存储结构和操作接口

//SeqStack.h

#ifndef  SEQSTACK_H

#define  SEQSTACK_H

const int StackSize=10;  //10只是示例性的数据,可以根据实际问题具体定义

template <class T>       //定义模板类SeqStack

class SeqStack

{

public:

    SeqStack( ) ;            //构造函数,栈的初始化

~SeqStack( );            //析构函数

    void Push(T x);          //将元素x入栈

    T Pop( );                //将栈顶元素弹出

    T GetTop( );          //取栈顶元素(并不删除)

bool Empty( );           //判断栈是否为空

private:

    T data[StackSize];      //存放栈元素的数组

    int top;                //栈顶指针,指示栈顶元素在数组中的下标

};

#endif

2. 栈操作的实现

//SeqStack.cpp

#include "SeqStack.h"

/*

 * 前置条件:栈不存在

 * 输    入:无

 * 功    能:栈的初始化

 * 输    出:无

 * 后置条件:构造一个空栈

 */

template <class T>

SeqStack<T>::SeqStack( )

{

top= -1;

}

/*

 * 前置条件:栈已存在

 * 输    入:无

 * 功    能:销毁栈

 * 输    出:无

 * 后置条件:释放栈所占用的存储空间

 */

template <class T>

SeqStack<T>::~SeqStack( )

{

}

/*

 * 前置条件:栈已存在

 * 输    入:元素值x

 * 功    能:在栈顶插入一个元素x

 * 输    出:如果插入不成功,抛出异常

 * 后置条件:如果插入成功,栈顶增加了一个元素

 */

template <class T>

void SeqStack<T>::Push(T x)

{

    if (top== StackSize-1) throw "上溢";

    top++;

    data[top]=x;

}

/*

 * 前置条件:栈已存在

 * 输    入:无

 * 功    能:删除栈顶元素

 * 输    出:如果删除成功,返回被删元素值,否则,抛出异常

 * 后置条件:如果删除成功,栈顶减少了一个元素

 */     

template <class T>

T SeqStack<T>::Pop( )

{

    T x;

    if (top==-1) throw "下溢";

    x=data[top--];

    return x;

}

/*

 * 前置条件:栈已存在

 * 输    入:无

 * 功    能:读取当前的栈顶元素

 * 输    出:若栈不空,返回当前的栈顶元素值

 * 后置条件:栈不变

 */

template <class T>

T SeqStack<T>::GetTop( )

{

if (top==-1) throw "下溢";

else return data[top];

}

/*

 * 前置条件:栈已存在

 * 输    入:无

 * 功    能:判断栈是否为空

 * 输    出:如果栈为空,返回1,否则,返回0

 * 后置条件:栈不变

 */

template <class T>

bool SeqStack<T>::Empty( )

{

if(top==-1) return 1;

else return 0;

}

3. 调试运行

//SeqStackMain.cpp

#include <iostream>      //引用输入输出流

using namespace std;

#include "SeqStack.cpp"  //引入成员函数文件

void main()

{    

    SeqStack<int> a;      //创建模板类的实例

    if (a.Empty( )){

cout<<"栈空,执行入栈操作:"<<endl;

     cout<<"对15和10执行入栈操作:"<<endl;

    try

{

a.Push(15);

       a.Push(10);   

}

catch(char* wrong)

{

cout<< wrong;

}

cout<<"栈顶元素为:"<<endl;   //取栈顶元素

cout<<a.GetTop( )<<endl;

    cout<<"执行出栈操作:"<<endl;

    cout<<a.Pop( )<<endl;          //执行出栈操作

        cout<<"栈顶元素为:"<<endl;

    cout<<a.GetTop( )<<endl;

}

else{

cout<<"栈不空"<<endl;

}

}

(五)实验体会与收获

通过这次实验,我掌握了顺序栈的储存与操作,巩固了C++相关的程序设计方法与技术,并且意识到熟练掌握课本知识是实验的基础,不把课本上的相关知识学深学透,实验便无从着手,另外在做实验的过程锻炼思考问题并动手解决的能力很重要。

(六)附:程序源代码

#include<iostream>
#include<stdlib.h>
#define STACK_INIT_SIZE  100//存储空间初始分配量。 
#define STACKINCREMENT 10//存储空间分配增量。 
using namespace std;

typedef int elemtype;
typedef struct {
	elemtype* base;//在栈构造之前和销毁之后,base的值为NULL。 
	elemtype* top;//栈顶指针。 
	int stacksize;//当前已分配的存储空间,以元素为单位。 
}Stack;


void Initstack(Stack& s);//1.初始化栈
void Destroystack(Stack& s);//2.销毁栈
void Clearstack(Stack& s);//3.清空栈
int StackEmpty(Stack s);//4.栈判空
int Stacklength(Stack s);//5.求栈长度
elemtype GetTop(Stack s);//6.获取栈顶元素
void Push(Stack& s, elemtype e);//7.插入一个元素
elemtype Pop(Stack& s);//8.删除一个元素
elemtype Stackvisit(Stack& s, int i);//9.输出所有元素
void conversion(Stack& jinzhi, int choose, int num);//10.进制转换

int main()
{
	Stack zhan;
	zhan.base = NULL;
	zhan.top = NULL;
	elemtype yuansu;

	int in = 1;
	cout << endl;
	while (in == 1)
	{
		cout << "1.初始化栈" << endl;
		cout << "2.销毁栈" << endl;
		cout << "3.清空栈" << endl;
		cout << "4.栈判空" << endl;
		cout << "5.求栈长度" << endl;
		cout << "6.获取栈顶元素" << endl;
		cout << "7.插入一个元素" << endl;
		cout << "8.删除一个元素" << endl;
		cout << "9.输出所有元素" << endl;
		cout << "10.进制转换" << endl;
		cout << "☆☆☆退出,输入一个负数!☆☆☆" << endl;
		int select;
		cout << "请输入您的选择:";
		cin >> select;
		switch (select)
		{
		case 1://1.初始化栈.
			system("cls");
			Initstack(zhan);
			if (!zhan.base)
			{
				cout << "存储空间分配失败,请重新操作!" << endl;
			}
			else
			{
				cout << "您已经成功初始化一个栈!" << endl;
			}
			cout << endl;
			break;
		case 2://2.销毁栈
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				Destroystack(zhan);
				cout << "您已成功销毁栈!" << endl;
			}
			cout << endl;
			break;
		case 3://3.清空栈
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				if (zhan.base == zhan.top)
				{
					cout << "栈为空,不用清空!" << endl;
				}
				else
				{
					Clearstack(zhan);
					cout << "已经成功清空栈!" << endl;
				}
			}
			cout << endl;
			break;
		case 4://4.栈判空
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				if (StackEmpty(zhan) == 0)
				{
					cout << "栈为空!" << endl;
				}
				else
				{
					cout << "栈不为空!" << endl;
				}
			}
			cout << endl;
			break;
		case 5://5.求栈长度
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				cout << "栈的长度为:" << Stacklength(zhan) << endl;
			}
			cout << endl;
			break;
		case 6://6.获取栈顶元素
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				if (zhan.base == zhan.top)
				{
					cout << "这是一个空栈,不存在元素!" << endl;
				}
				else
				{
					cout << "栈顶元素为:" << GetTop(zhan) << endl;
				}
			}
			cout << endl;
			break;
		case 7://7.插入一个元素
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				cout << "请输入您要插入的元素:";
				cin >> yuansu;
				if (zhan.top - zhan.base >= zhan.stacksize)//栈满,追加存储空间。 
				{
					zhan.base = (elemtype*)realloc(zhan.base, (zhan.stacksize + STACKINCREMENT) * sizeof(elemtype));
					if (!zhan.base) {
						cout << "存储空间分配失败!请重新操作。" << endl;
					}
					else
					{
						zhan.top = zhan.base + zhan.stacksize;
						zhan.stacksize += STACKINCREMENT;
						cout << "内存空间分配成功!" << endl;
					}
				}
				Push(zhan, yuansu);
				cout << "入栈成功!" << endl;
			}
			cout << endl;
			break;
		case 8://8.删除一个元素
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				if (zhan.base == zhan.top)
				{
					cout << "栈为空,没有元素可以出栈!" << endl;
				}
				else
				{
					cout << "元素" << Pop(zhan) << "出栈成功!" << endl;
				}
			}
			cout << endl;
			break;
		case 9://9.输出所有元素
			system("cls");
			if (zhan.base == NULL)
			{
				cout << "还未初始化栈,请您先初始化!" << endl;
			}
			else
			{
				if (zhan.base == zhan.top)
				{
					cout << "栈为空,没有元素可以输出!" << endl;
				}
				else
				{
					cout << "栈中的元素(从栈底到栈顶)为:";
					for (int i = zhan.top - zhan.base; i > 0; i--)
					{
						cout << Stackvisit(zhan, i) << " ";
					}

				}
			}
			cout << endl << endl;
			break;
		case 10://10.进制转换
			system("cls");
			int  num;
			cout << "请您输入一个十进制整数:";
			cin >> num;
			if (num <= 0)
			{
				cout << "您输入的数据不合法!" << endl;
			}
			else
			{
				int choose;
				Stack jinzhi;//构造进制转换的栈。 
				jinzhi.base = NULL;
				jinzhi.top = NULL;
				cout << endl;
				cout << "1.转化成二进制" << endl;
				cout << "2.转化成八进制" << endl;
				cout << "3.转化成十六进制" << endl << endl;
				cout << "请输入您的选择:";
				cin >> choose;
				switch (choose)
				{
				case 1:
					conversion(jinzhi, choose, num);
					cout << endl;
					cout << "转化结果为:";
					while (StackEmpty(jinzhi) == 1)
					{
						cout << Pop(jinzhi);
					}
					cout << endl;
					break;
				case 2:
					conversion(jinzhi, choose, num);
					cout << "转化结果为:";
					while (StackEmpty(jinzhi) == 1)
					{
						cout << Pop(jinzhi);
					}
					cout << endl;
					break;
				case 3:
					conversion(jinzhi, choose, num);
					cout << "转化结果为:";
					while (StackEmpty(jinzhi) == 1)
					{
						num = Pop(jinzhi);
						if (num >= 10)
						{
							switch (num)
							{
							case 10:
								cout << "A";
								break;
							case 11:
								cout << "B";
								break;
							case 12:
								cout << "C";
								break;
							case 13:
								cout << "D";
								break;
							case 14:
								cout << "E";
								break;
							case 15:
								cout << "F";
								break;
							}
						}
						else
						{
							cout << num;
						}
					}
					cout << endl;
					break;

				default:
					cout << "您输入的选择不正确哦!" << endl;
					break;

				}
			}
			cout << endl;
			break;

		default:
			system("cls");
			if (select < 0)//退出程序
			{
				in = -999;
				cout << "☆☆☆您已经退出程序,欢迎下次使用!☆☆☆" << endl;
				break;
			}
			else
			{
				cout << "您的选择有误,请重新输入!" << endl << endl;
			}
			break;
		}
	}
}
//1.初始化栈
void Initstack(Stack& s)
{
	s.base = (elemtype*)malloc(STACK_INIT_SIZE * sizeof(elemtype));
	s.top = s.base;
	s.stacksize = STACK_INIT_SIZE;
}
//2.销毁栈
void Destroystack(Stack& s)
{
	s.stacksize = 0;
	s.base = NULL;
	s.top = NULL;
	free(s.base);
	free(s.top);
}
//3.清空栈
void Clearstack(Stack& s)
{
	s.stacksize = 0;
	s.base = s.top;
}
//4.栈判空
int StackEmpty(Stack s)
{
	if (s.base == s.top)
	{
		return 0;//栈为空。 
	}
	else
	{
		return 1;//栈不为空。 
	}
}
//5.求栈长度
int Stacklength(Stack s)
{
	elemtype* p = s.top;
	int i = 0;//计数。 
	while (p != s.base)
	{
		p--;
		i++;
	}
	return i;
}
//6.获取栈顶元素
elemtype GetTop(Stack s)
{
	return *(s.top - 1);
}
//7.插入一个元素
void Push(Stack& s, elemtype e)
{
	*s.top = e;
	s.top++;
}
//8.删除一个元素
elemtype Pop(Stack& s)
{
	s.top--;
	return *s.top;
}
//9.输出所有元素
elemtype Stackvisit(Stack& s, int i)
{
	elemtype* p = s.top;
	for (int j = 1; j <= i; j++) {
		p--;
	}
	return *p;
}
//10.进制转换 
void conversion(Stack& jinzhi, int choose, int num)
{
	Initstack(jinzhi);
	int njinzhi;
	switch (choose)
	{
	case 1:
		njinzhi = 2;
		break;
	case 2:
		njinzhi = 8;
		break;
	case 3:
		njinzhi = 16;
		break;
	}
	while (num)
	{
		Push(jinzhi, num % njinzhi);
		num = num / njinzhi;
		//n=(n div d)*d + n mod d
		//十进制n和其他进制d的转换机制。div为整除运算,mod为求余运算。
	}
}

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liocric

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值