数据结构——栈和队列

数据结构的三要素:

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

栈 (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;
}

总结

  • 栈和队列都是增删操作受限制的特殊线性表;
  • 栈和队列的物理结构可以是连续的也可以是不连续的;
  • 另外,栈和队列的元素都是不能自由访问的。栈只能访问栈顶的元素,队列只能访问对头的元素;
相关推荐
白狐_7988 分钟前
408 数据结构|线索二叉树两题详解:先序线索化后的空链域 + 中序前驱/后继判断
c语言·数据结构·链表
GeekZHR20 分钟前
C语言指针进阶补充6:动态内存管理、mem系列内存函数、复杂指针声明,一次补齐指针的“三大盲区“
java·c语言·算法·指针
.道阻且长.36 分钟前
8.LeetCode算法习题讲解--滑动窗口--长度最小的子数组
算法·leetcode·职场和发展
(❁´◡`❁)Jimmy(❁´◡`❁)44 分钟前
P1156 [USACO01OPEN] 垃圾陷阱
算法·动态规划
疯狂打码的少年1 小时前
【数据结构】二叉排序树(BST)的定义与操作
数据结构·笔记·算法
lally.1 小时前
整数等差数列超图中的三个非微扰现象
算法
wabs6661 小时前
关于字符串【力扣541.反转字符串II的思考】
数据结构·算法·leetcode·字符串
土司大王1 小时前
LeetCode hot100——移动零
java·算法·leetcode
Tyler_TXZ3 小时前
C++C语言之——树
c语言·c++·算法·
hansang_IR3 小时前
【记录】「COCI 2024/2025」四道模拟赛/8.13
c++·算法