【数据结构与算法】栈

【数据结构——栈】个人总结摘要(C++版)

目录

一、 栈的基本概念

1.栈的定义

2.栈的顺序存储结构

(1) 栈的初始化

(2) 入栈

(3) 出栈

(4) 判空

(5) 取栈顶元素

(6)主函数及头文件声明 

3.栈的链式存储结构 

(1) 链栈的初始化

(2) 入栈

(3) 出栈

(4) 取栈顶元素 

(5)  判空

(6) 主函数及头文件声明 

4.C++库函数——栈的快捷使用



一、 栈的基本概念

1.栈的定义

        栈(Stack)是只允许在一端进行插入或者删除的线性表。首先,栈是一种线性表,限定这种线性表只能在某一端进行插入和删除操作。
        栈顶(Top),线性表只允许进行插入删除操作的那一端。
        栈底(Bottom),是栈的另一端,不允许进行插入删除操作的那一端。
        空栈,即为不含任何元素的空表。
 

1.1 栈的示意图

         如上图(1.1),a1为栈底元素,a7为栈顶元素。由于只能在栈顶进行插入和删除,所以入栈顺序依次为a1,a2,a3,a4,a5,a6,a7,而出栈顺序为a7,a6,a5,a4,a3,a2,a1。由此可见,栈的操作特性为后进先出

2.栈的顺序存储结构

        栈类似于线性表,也有对应的两种存储方式,即顺序存储和链式存储。

(1) 栈的初始化

        采用顺序存储的栈称为顺序栈,其利用一组地址连续的存储的单元(可理解为数组)存放自栈底到栈顶的数据元素,用一个标记top指向栈顶,栈的初始化即为空栈,栈中无任何元素,故初始化top为-1。

template<class DataType>
SeqStack<DataType>::SeqStack()
{
    top=-1;
}

(2) 入栈

        入栈 ,若栈未满,则将要插入的元素放入栈顶,此后再进入元素,栈顶标记加1后放入元素。

template<class DataType>
void SeqStack<DataType>::input(DataType x)
{
    if(top==StackSize) cout<<"Stack is full"<<endl; //StackSize为栈的最大长度
    else
    {
        top++;    
        data[top]=x;    //存放栈的数组,则入栈依次为data[0],data[1],...,data[StackSize]
    }
}

(3) 出栈

        若栈不为空则取栈顶元素值,然后将top-1。
        出栈是移动栈顶标记,并且输出,移动标记top后,栈顶元素相当于删除,故若想输出栈顶可用两种方法:
        * 调用取栈顶函数(见下文),输出栈顶元素,然后移动标记top。
        * 下面代码段实际包括了取栈顶函数,具体为
                - 定义一个变量暂存栈顶元素
                - 移动top(出栈需删除栈顶元素)
                - 返回栈顶元素

template<class DataType>
DataType SeqStack<DataType>::output()
{
    if(top==-1) cout<<"Stack is empty"<<endl;
    else
    {
        DataType temp; //暂存栈顶元素
        temp=top[top];
        top--;    //栈顶标记-1
        return temp;    //返回栈顶,即出栈
    }
}

(4) 判空

        此操作较简单,栈顶标记为-1则为空。 

template<class DataType>
bool SeqStack<DataType>::empty()
{
	if(top==-1) return true; //true是空
	else return false;	//非空
}

(5) 取栈顶元素

        栈不为空则直接返回栈顶元素,标记top不需要移动

template <class DataType>
DataType SeqStack<DataType>::getpop()
{
    return data[top];
}

(6)主函数及头文件声明 

#include<iostream>   //本例采用C++模板机制
using namespace std;
#define StackSize 20
template <class DataType>
class SeqStack
{
    private:
        DataType data[StackSize];
        int top;
    public:
        SeqStack();
	    ~SeqStack(){};
        void input(DataType x);
        DataType output();
		bool empty();
        DataType getpop();
};
//主函数可根据需要自行修改,与其他代码段拼接即可运行
int main()
{
    SeqStack<int> l;
    int n,m;
    cin>>n;
	
    try{
		for(int i=0;i<n;i++)
		{
			cin>>m;
			l.input(m);
		}
		if(l.empty()==1) cout<<"Stack is empty;"<<endl;
		else
		{
			cout<<l.getpop()<<endl;
			cout<<l.output()<<endl;
			cout<<l.getpop()<<endl;
		}
    }
    catch(char *str){cout<<str<<endl;}
    return 0;
}

3.栈的链式存储结构 

        链栈与单链表类似,本例采用不带头结点的链表实现链栈。
        是否带头结点的链表在具体操作上会有不同,带有头结点的链表是初始化一个空结点,不带头结点的链表是通过一个指针指向第一个结点。
        栈采用链式存储,便于结点的插入与删除,且不存在栈满上溢的情况。

(1) 链栈的初始化

        建立一个头指针,将头指针指向空,此时栈顶为空值。

LinkStack() //构造函数,链栈的初始化
{
     head = NULL;    //头指针指向空,此时栈顶为空值
}	

(2) 入栈

1.2入栈示意图
template<class DataType>
void LinkStack<DataType>::push(DataType x)
{
	Node<DataType>* s;
	s = new Node<DataType>;
	s->data = x;
	s->next = head;
	head = s;	//头指针指向第一个结点,即栈顶,head始终指向栈顶
}

(3) 出栈

        出栈原理类似于上文顺序栈,这里就不多赘述了。代码如下:

template<class DataType>
void LinkStack<DataType>::pop()
{
	if (head == NULL) cout << "LinkStack is empty" << endl;
	else
	{
		Node<DataType>* temp;
		DataType topdata;
		temp = head;			//暂存要删除的栈顶
		topdata = temp->data;	//保存要出栈的元素值
		head = head->next;		//栈顶指针指向下一个结点
		delete temp;			//删除栈顶
	}
}

(4) 取栈顶元素 

template<class DataType>
DataType LinkStack<DataType>::Gettop()
{
	if (head == NULL) cout << "LinkStack is empty" << endl;
	else
	{
		return head->data;
	}
}

(5)  判空

        此操作较简单,栈顶==NULL则为空。

template<class DataType>
bool LinkStack<DataType>::empty()
{
	if (head == NULL) return true;
	else return false;
}

(6) 主函数及头文件声明 

#include<iostream>
using namespace std;

template<typename DataType>
struct Node
{
	DataType data;
	Node<DataType>* next;
};

template<class DataType>
class LinkStack
{
private:
	Node<DataType>* head;	//不带头结点的链栈
public:
	LinkStack() { head = NULL; }	//头指针指向空,此时栈顶为空值
	void push(DataType x);
	void pop();
	DataType Gettop();
	bool empty();
};
//以上各段操作放在类定义与主函数之间
#include<iostream>
#include"标头.h"
using namespace std;

int main()
{
	LinkStack<int> l;
	int data, n;
	cout << "输入入栈个数: ";
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cout << "输入第 " << i+1 << " 个数据: ";
		cin >> data;
		l.push(data);
	}
	cout << "栈是否为空: ";
	cout << l.empty() << endl;
	if (!l.empty())
	{
		cout << "输出栈顶数据:";
		cout << l.Gettop() << endl;
		cout << "输出出栈后的栈顶数据:";
		l.pop();
		cout << l.Gettop() << endl;
	}
	return 0;
}

4.C++库函数——栈的快捷使用

        库函数在使用时需声明头文件,栈的头文件是"#include<stack>",之后在定义栈时,与类模板相似,声明方式为"stack<DataType数据类型>+名称"。
        *调用函数进行栈的操作,具体如下:

//例如要定义的栈为:
stack<int> s;
int x;    //x为要入栈的数据

                -s.push(x);        //压栈函数" XXX.push(x); ",无返回值,可直接调用
                -s.pop(x);          //出栈函数" XXX.pop(x); ",无返回值,可直接调用
                -s.top(x);           //取栈顶函数" cout<<XXX.top(x); ",有返回值,为栈顶元素,得赋值给一个变量或直接输出     
                -s.empty();        //判断栈是否为空函数" cout<<XXX.empty();",不需要传参,但有返回值,返回值为1,表示该栈为空,为0表示该栈不为空
        以下为具体使用示例:
 

#include<iostream>
#include<stack>			//注意此处
using namespace std;
int main()
{
	stack<int> s;
	int n,i,x;
	cin>>n;				//要入栈的数据个数
	for(i=0;i<n;i++)
	{
		cin>>x;
		s.push(x);
	}
	if(s.empty()) cout<<"Stack is empty"<<endl;	//如果栈是空,输出提示信息
	else
	{
		cout<<s.top()<<endl;	//输出栈顶元素
		s.pop();				//进行出栈操作
		cout<<s.top()<<endl;	//之后查看栈顶
	}
	return 0;
}

 小伙伴们,因为我本身也在学习数据结构中,此系列文章也作为笔记记录分享给大家,如有错误希望各位指正,我会继续努力,提高自己水平。
注:
        参考书籍《2022年数据结构考研复习指导》,王道论坛组 编。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

悦享未来

你的鼓励必将成为我前进的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值