数据结构——栈和队列

数据结构的三要素:

  • 逻辑结构;
  • 元素的运算;
  • 存储结构;

栈 (stack)

定义:

线性表分为两种,一种是顺序表,一种是链表。而栈也可以理解为一种特殊的线性表;


栈只允许在一段进行数据的插入或者删除操作,也就是数据是后进先出;

基本操作

  • InitStack(); 初始化一个栈,分配内存空间;
  • DestoryStack(&S); 销毁一个栈,释放内存空间;
  • Push(&s, value); 若栈未满则向栈顶压入元素value;
  • Pop(&s, output); 若栈非空,则弹出栈顶元素并用output接收;
  • GetTop(&s, output); 若栈非空,则读取栈顶元素并用output接收;
  • bool StackEmpty(s); 判断栈是否为空;

顺序栈的实现与操作

cpp 复制代码
#include <iostream>
using namespace std;

template <class T>
struct Node
{
	//记录栈底的地址
	T* pos;
	//记录栈顶元素的相对位置
	int top;
};

template<class T>
class MyStack
{
private:
	Node<T> d;
	//记录栈的最大容量
	int capacity;
public:
	MyStack()
	{
		capacity = 10;
		d.top = -1;
		d.pos = new T[capacity];
	}

	MyStack(int n)
	{
		capacity = n;
		d.top = -1;
		d.pos = new T[capacity];
	}

	bool StackEmpty()
	{
		return d.top == -1;
	}

	void Push(T value)
	{
		if (d.top != capacity - 1)
		{
			d.pos[++d.top] = value;
		}
		else
		{
			cout << "栈已满" << endl;
			exit(0);
		}
	}

	void Pop(T &output)
	{
		if (!StackEmpty())
		{
			output = d.pos[d.top--];
		}
		else
		{
			cout << "栈已空" << endl;
		}
	}

	void GetTop(T &output)
	{
		if (!StackEmpty())
		{
			output = d.pos[d.top];
		}
		else
		{
			cout << "栈已空" << endl;
		}
	}

	~MyStack()
	{
		delete[] d.pos;
		d.pos = NULL;
	}
};

void test()
{
	MyStack<int> s;
	int n = 0;
	s.Push(10);
	if (!s.StackEmpty())
	{
		cout << "栈非空" << endl;
	}
	s.GetTop(n);
	cout << n << endl;
	s.Pop(n);
	if (s.StackEmpty())
	{
		cout << "成功弹出" << endl;
	}
}

int main()
{
	test();
	return 0;
}

共享栈

由于顺序栈的存储空间相对固定,所以在使用时会有一定的不便:如果开始分配的内存小了可能会出现内存不够用的问题,如果一开始就分配很大的内存又会有空间浪费的问题,这时候用共享栈就可以很好的解决这个问题;


顾名思义,共享栈就是两个栈公用一块内存,但是两个栈的top在最开始分别指向这块内存的两端,并以此为起点压入数据。


需要注意的是 使用共享栈时一定要注意内存是否用完,否则可能出现越界访问的问题;

链式栈的实现

链式栈本质可以看作是一个单链表,只是限制了结点的增删操作只能在链表的一端进行;

队列

定义

队列同样是一个操作受限的线性表,队列只允许在一段进行插入,在另一端进行删除;


允许插入的一段叫做队尾,允许删除的一段叫做对头;

基本操作

队列的基本操作同样是创 销 增 删 查;

  • Init()
  • Destory()
  • Push()
  • Pop()
  • GetHead()
  • Empty()

队列的实现与操作

cpp 复制代码
#include <iostream>
using namespace std;

template<class T>
struct Node
{
	T data;
	Node* next;
	Node(T value)
	{
		data = value;
		next = NULL;
	}
	~Node()
	{
		next = NULL;
	}
};

template <class T>
class MyQueue
{
private:
	Node<T>* n;
	Node<T>* Head;
	Node<T>* Tail;
public:
	MyQueue()
	{
		Head = NULL;
		Tail = NULL;
	}
	MyQueue(T value)
	{
		n = new Node(value);
		n->data = value;
		n->next = NULL;
		Head = &n;
		Tail = &n;
	}
	~MyQueue()
	{
		Node<T>* temp = Head;
		while (Head)
		{
			Head = Head->next;
			delete temp;
			temp = Head;
		}
	}
	bool Empty()
	{
		return Tail == NULL && Head == NULL;
	}
	void Push(T value)
	{
		if (Empty())
		{
			n = new Node<T>(value);
			Head = n;
			Tail = n;
		}
		else
		{
			Tail->next = new Node<T>(value);
			Tail = Tail->next;
			Tail->next = NULL;
		}
	}
	void Pop()
	{
		if (Empty())
		{
			cout << "队列已空" << endl;
			exit(0);
		}
		else if (Tail == Head)
		{
			delete Tail;
			Tail = NULL;
			Head = NULL;
		}
		else
		{
			Node<T>* temp = Head;
			Head = Head->next;
			delete temp;
			temp = NULL;
		}
	}
	T GetTop()
	{
		if (Empty())
		{
			cout << "队列已空" << endl;
			exit(0);
		}
		else
		{
			return Head->data;
		}
	}
};

void test()
{
	MyQueue<int> q;
	q.Push(1);
	q.Push(2);
	q.Push(3);
	while (!q.Empty())
	{
		cout << q.GetTop() << endl;
		q.Pop();
	}
}

int main()
{
	test();
	return 0;
}

总结

  • 栈和队列都是增删操作受限制的特殊线性表;
  • 栈和队列的物理结构可以是连续的也可以是不连续的;
  • 另外,栈和队列的元素都是不能自由访问的。栈只能访问栈顶的元素,队列只能访问对头的元素;
相关推荐
ohyeah4 小时前
栈:那个“先进后出”的小可爱,其实超好用!
前端·数据结构
散峰而望4 小时前
C++数组(三)(算法竞赛)
开发语言·c++·算法·github
q***95224 小时前
SpringMVC 请求参数接收
前端·javascript·算法
初级炼丹师(爱说实话版)5 小时前
多进程与多线程的优缺点及适用场景总结
算法
hetao17338375 小时前
2025-11-25~26 hetao1733837的刷题记录
c++·算法
历程里程碑5 小时前
各种排序法大全
c语言·数据结构·笔记·算法·排序算法
少许极端5 小时前
算法奇妙屋(十四)-简单多状态dp问题
算法·动态规划·图解算法·简单多状态dp·打家劫舍问题·买卖股票问题全解
2301_823438026 小时前
解析论文《复杂海上救援环境中无人机群的双阶段协作路径规划与任务分配》
人工智能·算法·无人机
embrace996 小时前
【C语言学习】结构体详解
android·c语言·开发语言·数据结构·学习·算法·青少年编程
Ayanami_Reii7 小时前
基础数学算法-开关问题
数学·算法·高斯消元