• 数据结构与算法-栈


    在这里插入图片描述

    栈和队列是两种常用的线性结构,属于特殊的线性表,是线性表相关运算的一个子集。一般来说,线性表上的插入和删除操作不受任何限制,但栈只能在表的一端进行插入和删除操作,而队列则只能在一端进行插入操作,在另一端进行删除操作。因此,栈和队列通常称为操作受限的线性表。

    🎈1.栈的定义

    栈是限定在表的一端进行插入和删除操作的线性表。表中允许插入和删除操作的一端称为栈顶,另一端叫做栈底。当栈中没有任何元素时称为空栈。栈顶位置是动态的,由一个栈顶的指针(top)指示其位置(具体实现时一般指向当前元素的下一个空位)。栈的插入操作通常称为压栈或进栈,删除操作通常称为退栈或出栈。栈具有“后进先出,先进后出”的特点,即后进栈的元素先出栈。
    栈操作示例图:
    在这里插入图片描述

    🔎假设这里有三个元素a、b、c,如果进栈顺序是abc,那么出栈的顺序有几种可能呢?
    5种:abc acb cba bac bca

    🎈2.栈的抽象数据类型

    在这里插入图片描述

    🎈3.顺序栈

    顺序栈是指用一组地址连续的存储空间依次存放栈中元素的存储结构,并用一个变量top指向当前栈顶元素的下一个空位来反映栈中元素的变化情况,另一个变量base指向栈底。顺序栈的存储结构如下图所示:
    在这里插入图片描述

    🔭3.1顺序栈的类定义

    #define InitStackSize 100
    #define StackIncrement 10
    typedef int SElemType;
    class Sqstack
    {
    private:
    	SElemType* base;//栈底指针,SElemType为栈中元素类型
    	SElemType* top;//栈顶指针
    	int stacksize;//栈容量
    public:
    	Sqstack();//构造函数,初始化建立一空栈
    	~Sqstack()//析构函数,销毁栈
    	{
    		delete[]base;
    		stacksize = 0;
    	}
    	SElemType GetTop();//取栈顶元素
    	void Push(SElemType e);//进栈
    	void Pop(SElemType& e);//退栈
    	int EmptyStack();//判断栈空否,若空返回1,否则返回0
    	void Print();//从栈底到栈顶输出栈中的元素
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    🔭3.2初始化建立空栈

    Sqstack::Sqstack()
    {
    	base = top = new SElemType[InitStackSize];
    	stacksize = InitStackSize;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    🔭3.3入栈操作

    void Sqstack::Push(SElemType e)
    {
    	if (top - base == stacksize)
    	{
    		SElemType* base1 = new SElemType[stacksize + StackIncrement];
    		int i = 0;
    		for (i = 0; i < InitStackSize; i++)
    		{
    			base1[i] = base[i];
    		}
    		delete[]base;//释放空间
    		base = base1;
    		top = base + stacksize;
    		stacksize += StackIncrement;
    	}
    	*top++ = e;//插入e
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    🔭3.4退栈操作

    void Sqstack::Pop(SElemType& e)
    {
    	if (top == base)//栈空,删除操作无法进行
    		return;
    	e = *top--;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    🔭3.5栈判空操作

    int Sqstack::EmptyStack()
    {
    	if (top == base)
    		return 1;
    	else
    		return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🔭3.6返回栈顶元素

    SElemType Sqstack::GetTop()//返回栈顶元素
    {
    	return *(top - 1);
    }
    
    • 1
    • 2
    • 3
    • 4

    🔭3.7打印栈

    void Sqstack::Print()//打印栈中元素
    {
    	int i = 0;
    	for (i = 0; i < *(top - 2); i++)
    	{
    		cout << base[i] << " ";
    	}
    	cout << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    🔭3.8全部代码

    #define _CRT_SECURE_NO_WARNINGS 1
    #include 
    using namespace std;
    #define InitStackSize 100
    #define StackIncrement 10
    typedef int SElemType;
    class Sqstack
    {
    private:
    	SElemType* base;//栈底指针,SElemType为栈中元素类型
    	SElemType* top;//栈顶指针
    	int stacksize;//栈容量
    public:
    	Sqstack();//构造函数,初始化建立一空栈
    	~Sqstack()//析构函数,销毁栈
    	{
    		delete[]base;
    		stacksize = 0;
    	}
    	SElemType GetTop();//取栈顶元素
    	void Push(SElemType e);//进栈
    	void Pop();//退栈
    	int EmptyStack();//判断栈空否,若空返回1,否则返回0
    	void Print();//从栈底到栈顶输出栈中的元素
    };
    Sqstack::Sqstack()
    {
    	base = top = new SElemType[InitStackSize];
    	stacksize = InitStackSize;
    }
    void Sqstack::Push(SElemType e)
    {
    	if (top - base == stacksize)
    	{
    		SElemType* base1 = new SElemType[stacksize + StackIncrement];
    		int i = 0;
    		for (i = 0; i < InitStackSize; i++)
    		{
    			base1[i] = base[i];
    		}
    		delete[]base;//释放空间
    		base = base1;
    		top = base + stacksize;
    		stacksize += StackIncrement;
    	}
    	*top++ = e;//插入e
    }
    void Sqstack::Pop()
    {
    	SElemType e;
    	if (top == base)//栈空,删除操作无法进行
    		return;
    	e = *top--;
    }
    int Sqstack::EmptyStack()//判空函数
    {
    	if (top == base)
    		return 1;
    	else
    		return 0;
    }
    SElemType Sqstack::GetTop()//返回栈顶元素
    {
    	cout << *(top - 1) << endl;
    	return 0;
    }
    void Sqstack::Print()//打印栈中元素
    {
    	int i = 0;
    	for (i = 0; i < *(top - 2); i++)
    	{
    		cout << base[i] << " ";
    	}
    	cout << endl;
    }
    int main()
    {
    	Sqstack l;
    	l.Push(3);
    	l.Push(5);
    	l.Push(6);
    	l.Pop();
    	l.GetTop();
    	l.Print();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    ✅调试运行:
    在这里插入图片描述

    🎈4.链栈

    链栈是指利用一组地址任意的存储空间存放栈中元素的存储结构,这里使用链表来实现链栈。链栈的存储结构如下图所示:
    在这里插入图片描述
    注:top指向头结点,a1为栈顶元素,an为栈底元素,栈的所有操作都在单链表的表头进行。

    🔭4.1链栈的类定义

    typedef int SElemType;
    typedef struct LinkNode
    {
    	SElemType data;
    	LinkNode* next;
    }LinkNode;
    class LinkStack
    {
    private:
    	LinkNode* top;//栈顶指针即链栈的头指针
    public:
    	LinkStack();//构造函数,置空链栈
    	~LinkStack();//析构函数,释放链栈中各结点的存储空间
    	SElemType GetTop();//获取栈顶元素
    	void Push(SElemType e);//将元素e入栈
    	void Pop(SElemType& e);//将栈顶元素出栈
    	int EmptyStack();//判断链栈是否为空栈
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    🔭4.2创建空栈

    LinkStack::LinkStack()
    {
    	top = new LinkNode;
    	top->next = NULL;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    🔭4.3销毁栈

    LinkStack::~LinkStack()//析构函数,释放链栈中各结点的存储空间
    {
    	LinkNode* p = top;
    	LinkNode* q = top->next;
    	while (q)
    	{
    		delete p;
    		p = q;
    		q = q->next;
    	}
    	delete p;//删除最后一个结点
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    🔭4.4入栈操作

    void LinkStack::Push(SElemType e)
    {
    	LinkNode* s = new LinkNode;//分配空间
    	s->data = e;
    	s->next = top->next;//插入元素e
    	top->next = s;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🔭4.5退栈操作

    void LinkStack::Pop(SElemType& e)
    {
    	if (top->next == NULL)
    		return;
    	LinkNode* p = top->next;//p指向首元结点
    	e = p->data;
    	top->next = p->next;//删除首元结点
    	delete p;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    🔭4.6判空操作

    int LinkStack::EmptyStack()
    {
    	if (top->next == NULL)
    		return 1;
    	else 
    		return 0;//栈非空返回0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    🔭4.7返回栈顶元素

    SElemType LinkStack::GetTop()
    {
    	return top->next->data;
    }
    
    • 1
    • 2
    • 3
    • 4

    🔭4.8打印栈

    void LinkStack::print()
    {
    	LinkNode* p = top->next;
    	while (p)
    	{
    		cout << p->data << " ";
    		p = p->next;
    	}
    	cout << endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    🔭4.9全部代码

    #define _CRT_SECURE_NO_WARNINGS 1
    #include 
    using namespace std;
    typedef int SElemType;
    typedef struct LinkNode
    {
    	SElemType data;
    	LinkNode* next;
    }LinkNode;
    class LinkStack
    {
    private:
    	LinkNode* top;//栈顶指针即链栈的头指针
    public:
    	LinkStack();//构造函数,置空链栈
    	~LinkStack();//析构函数,释放链栈中各结点的存储空间
    	SElemType GetTop();//获取栈顶元素
    	void Push(SElemType e);//将元素e入栈
    	void Pop();//将栈顶元素出栈
    	int EmptyStack();//判断链栈是否为空栈
    	void print();//打印栈
    };
    LinkStack::LinkStack()//构造函数,置空链栈
    {
    	top = new LinkNode;
    	top->next = NULL;
    }
    LinkStack::~LinkStack()//析构函数,释放链栈中各结点的存储空间
    {
    	LinkNode* p = top;
    	LinkNode* q = top->next;
    	while (q)
    	{
    		delete p;
    		p = q;
    		q = q->next;
    	}
    	delete p;//删除最后一个结点
    }
    void LinkStack::Push(SElemType e)
    {
    	LinkNode* s = new LinkNode;//分配空间
    	s->data = e;
    	s->next = top->next;//插入元素e
    	top->next = s;
    }
    void LinkStack::Pop()
    {
    	SElemType e;
    	if (top->next == NULL)
    		return;
    	LinkNode* p = top->next;//p指向首元结点
    	e = p->data;
    	top->next = p->next;//删除首元结点
    	delete p;
    }
    int LinkStack::EmptyStack()
    {
    	if (top->next == NULL)
    		return 1;
    	else 
    		return 0;//栈非空返回0
    }
    SElemType LinkStack::GetTop()
    {
    	cout << top->next->data << endl;
    	return 0;
    }
    void LinkStack::print()
    {
    	LinkNode* p = top->next;
    	while (p)
    	{
    		cout << p->data << " ";
    		p = p->next;
    	}
    	cout << endl;
    }
    int main()
    {
    	LinkStack l;
    	l.Push(1);
    	l.Push(2);
    	l.Push(3);
    	l.Push(4);
    	l.Push(5);
    	l.GetTop();
    	l.Pop();
    	l.print();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    ✅运行示例:
    在这里插入图片描述

    好啦,关于栈的知识到这里就结束啦,后期会继续更新数据结构与算法的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️

  • 相关阅读:
    如何优化前端性能:提高网页加载速度的实用技巧
    SpringBoot集成Mybatis-Plus
    嵌入式鸿蒙系统开发语言与开发方法分析
    【Python】代码风格约定_摘自开源项目FreeCAD
    Kotlin(十一)Kotlin中的Object关键字
    C++ Qt开发:标准Dialog对话框组件
    java:内部类
    神经系统肿瘤治疗包括,神经系统肿瘤治疗费用
    JAVA面试题多线程&并发篇(二)
    数学建模学习笔记(9):主成分分析法
  • 原文地址:https://blog.csdn.net/qq_73121173/article/details/133833925