草庐IT

顺序栈的基本操作(超详细)

waggghhhh 2023-05-03 原文

目录

前言

一、顺序栈的定义

二、顺序栈的c++语言结构描述表示

三、顺序栈中基本操作的实现

3.1顺序栈的初始化 

3.2判断顺序栈是否为空

3.3求顺序栈的长度

3.4清空顺序栈

3.5销毁顺序栈

3.6顺序栈的入栈

3.7顺序栈的出栈

3.8求栈顶元素

3.9遍历顺序栈 

 四、顺序栈的代码实现

五、测试结果

五、总结


前言

本文参考王卓老师的数据结构视频和严蔚敏老师的《数据结构》


一、顺序栈的定义

栈:操作受限的线性表,限定仅在表尾进行插入和删除操作的线性表,即后进先出。这一端被称为栈顶,相对地,把另一端称为栈底。

顺序栈:用顺序结构存储的栈

例子:类似子弹压入弹夹,后放入的子弹可以先从弹夹弹出来。

特点:简单方便,但是容易溢出(上溢或者下溢)

二、顺序栈的c++语言结构描述表示

代码如下(示例):

typedef struct sqstack{
    int *top;//栈顶指针
    int *base;//栈底指针
    int stackSize;//栈的最大容量 
}stack;

三、顺序栈中基本操作的实现

3.1顺序栈的初始化 

数组用c++的new来动态开辟

当内存不够的时候,也即是s.base为空,则直接结束

不为空的时候,则栈的栈顶指针与栈底指针都指向同一位置

代码如下(示例):

void initStack(stack &s)
{
	s.base=new int[MaxSize];
	if(!s.base)	exit(0);//内存分配失败,结束
	s.top=s.base;//初始的时候栈的top与base相等 
	s.stackSize=MaxSize;//栈的最大容量	
} 

3.2判断顺序栈是否为空

栈顶指针与栈底指针都指向同一位置,即s.base==s.top的时候,则栈为空,返回1

否则,不为空,返回0

 代码如下(示例):

int isEmpty(stack s)
{
	if(s.base==s.top)
		return 1;//表示为空,无元素
	return 0;//不为空	
} 

3.3求顺序栈的长度

长度即为有多少个元素,可以用s.top-s.base

 代码如下(示例):

int stackLength(stack s)
{
	return s.top-s.base;
}

3.4清空顺序栈

当s.base不为空的时候,让s.top(栈顶指针)直接指向s.base(栈底),则把所有的元素逻辑上清空了

而当s.base为空的时候,则栈已经被销毁了,无需清空

 代码如下(示例):

void CleanStack(stack &s)
{
	if(s.base)
	{
		s.top=s.base;
		cout<<"成功清空"<<endl;
	}
	else
		cout<<"栈已经被销毁,无需清空"<<endl;
}

3.5销毁顺序栈

从物理层次销毁

也即是用delete将整个s.base从内存中删除

 代码如下(示例):

void DestoryStack(stack &s)
{
	if(s.base)
	{
		delete s.base;
		s.stackSize=0;
		s.base=NULL;
		s.top=NULL;
		cout<<"成功销毁"<<endl;
	}
	else
		cout<<"栈已经被销毁,无需销毁"<<endl;
}

3.6顺序栈的入栈

首先判断栈是否已经满了,如果满了则无法入栈,否则可以入栈

 代码如下(示例):

void push(stack &s,int e)
{
	if((s.top-s.base)==s.stackSize)
		cout<<"栈满了,无法添加新元素"<<endl;
	else
	{
		*(s.top)=e;
		s.top++;	
		cout<<"添加成功"<<endl;
	}	
} 

3.7顺序栈的出栈

首先判断栈是否为空,如果为空,则无法出栈,否则可以出栈 

  代码如下(示例):

void pop(stack &s,int &e)
{
	if(isEmpty(s))
	{
		cout<<"栈为空,无法弹出"<<endl;
	}	
	else
	{
		s.top--;
		e=*(s.top);
		cout<<"成功弹出"<<endl; 
	}
} 

3.8求栈顶元素

 先判断栈是否为空,为空则无法求栈顶元素,否则可以求栈顶元素

  代码如下(示例):

int top(stack s)
{
	if(isEmpty(s))
	{
		cout<<"栈为空,没有栈顶元素"<<endl;
		return -1;
	}
	else
	{
		s.top--;
		return *(s.top);
	}
}

3.9遍历顺序栈 

从栈底开始遍历 

  代码如下(示例):

void traverse(stack s)
{
	int length=stackLength(s);
	
	if(length>0)
	{
		cout<<"顺序栈的元素为:(从栈底开始遍历)"<<endl;
		for(int i=0;i<length;i++)
			cout<<s.base[i]<<" ";
	}	
	else
		cout<<"顺序栈为空"<<endl;
} 

 四、顺序栈的代码实现

#include <iostream>
using namespace std;
const int MaxSize=100;
typedef struct sqstack{
	int *top;//栈顶指针
	int *base;//栈底指针
	int stackSize;//栈的最大容量 
}stack;
void initStack(stack &s)
{
	s.base=new int[MaxSize];
	if(!s.base)	exit(0);//内存分配失败,结束
	s.top=s.base;//初始的时候栈的top与base相等 
	s.stackSize=MaxSize;//栈的最大容量	
} 
int isEmpty(stack s)
{
	if(s.base==s.top)
		return 1;//表示为空,无元素
	return 0;//不为空	
} 
int stackLength(stack s)
{
	return s.top-s.base;
}
void CleanStack(stack &s)
{
	if(s.base)
	{
		s.top=s.base;
		cout<<"成功清空"<<endl;
	}
	else
		cout<<"栈已经被销毁,无需清空"<<endl;
}
void DestoryStack(stack &s)
{
	if(s.base)
	{
		delete s.base;
		s.stackSize=0;
		s.base=NULL;
		s.top=NULL;
		cout<<"成功销毁"<<endl;
	}
	else
		cout<<"栈已经被销毁,无需销毁"<<endl;
}
//入栈
void push(stack &s,int e)
{
	if((s.top-s.base)==s.stackSize)
		cout<<"栈满了,无法添加新元素"<<endl;
	else
	{
		*(s.top)=e;
		s.top++;	
		cout<<"添加成功"<<endl;
	}	
} 
//出栈
void pop(stack &s,int &e)
{
	if(isEmpty(s))
	{
		cout<<"栈为空,无法弹出"<<endl;
	}	
	else
	{
		s.top--;
		e=*(s.top);
		cout<<"成功弹出"<<endl; 
	}
} 
int top(stack s)
{
	if(isEmpty(s))
	{
		cout<<"栈为空,没有栈顶元素"<<endl;
		return -1;
	}
	else
	{
		s.top--;
		return *(s.top);
	}
}
void traverse(stack s)
{
	int length=stackLength(s);
	
	if(length>0)
	{
		cout<<"顺序栈的元素为:(从栈底开始遍历)"<<endl;
		for(int i=0;i<length;i++)
			cout<<s.base[i]<<" ";
	}	
	else
		cout<<"顺序栈为空"<<endl;
} 
void menu()
{
	cout<<"**********************************"<<endl;
	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 main()
{
	int choice;
	stack s;
	int e1,e2;
	while(1)
	{
		menu();
		cin>>choice;
		switch(choice)
		{
			case 1:
				initStack(s);
				cout<<"初始化成功"<<endl;
				break;
			case 2:
				if(isEmpty(s))
					cout<<"栈为空"<<endl;
				else
					cout<<"栈不为空"<<endl; 
				break;
			case 3:
				cout<<"栈的长度为"<<stackLength(s)<<endl;
				break;
			case 4:
				CleanStack(s);
				break;
			case 5:
				DestoryStack(s);
				break;	
			case 6:
				cout<<"请输入想要入栈的元素值:"<<endl;
				cin>>e1;
				push(s,e1);
				break;
			case 7:
				pop(s,e2);
				cout<<"弹出的元素为"<<e2<<endl;
				break;
			case 8:
				if(top(s)!=-1)
					cout<<"栈顶元素为"<<top(s)<<endl;
				break;
			case 9:
				traverse(s);
				cout<<endl;
				break;
			case 10:
				cout<<"成功退出"<<endl;
				exit(0);
			default:
				cout<<"输入有误,请重新输入"<<endl;
				break;			
		}	
	}
} 

五、测试结果

                                          图一

                                        图二 

                                        图三

 

                                        图四 

 

                                         图五

                                         图六

                                         图七

                                          图八

                                           图九

                                            图十

                                             图十一

六、总结

        栈是一种操作受限的线性表,虽然操作受限,但是与线性表有点类似,只不过栈的插入和删除都在表尾而已。而我在本文中实现的顺序栈有点类似顺序表。我们也需要注意到顺序栈虽然实现简单,但是其容易发生溢出,在栈满的时候,还要入栈,则会上溢,而在栈空的时候,还要出栈,则会下溢,针对这个问题,我将在下一篇文章的链栈解决这个问题。

有关顺序栈的基本操作(超详细)的更多相关文章

  1. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  2. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  3. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  4. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  5. ruby-on-rails - 使用 HTTParty 的非常基本的 Rails 4.1 API 调用 - 2

    Rails相对较新。我正在尝试调用一个API,它应该向我返回一个唯一的URL。我的应用程序中捆绑了HTTParty。我已经创建了一个UniqueNumberController,并且我已经阅读了几个HTTParty指南,直到我想要什么,但也许我只是有点迷路,真的不知道该怎么做。基本上,我需要做的就是调用API,获取它返回的URL,然后将该URL插入到用户的数据库中。谁能给我指出正确的方向或与我分享一些代码? 最佳答案 假设API为JSON格式并返回如下数据:{"url":"http://example.com/unique-url"

  6. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  7. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

  8. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  9. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  10. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

随机推荐