数据结构之栈和队列
Posted TangguTae
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之栈和队列相关的知识,希望对你有一定的参考价值。
栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
数据从栈顶压入栈中,从栈顶出栈。
具体的实现可以采用之前所说的两种基本的数据结构数组和链表,这两种结构都可以实现栈。
数组:
链表:
在这二者之间,很显然采用数组来实现栈的结构更优,很重要的原因是内存连续,虽然存在内存浪费,但是加载数据的速度更快,牺牲内存换取速度。
队列只允许在一端进行插入数据的操作,在另一端进行删除数据的特殊线性表,队列具有先进先出(FIFO)的性质,进行插入操作的一端称为队尾,进行删除操作的一端操作为队头。
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,会发生频繁的挪动数据,效率会比较低。
常见的面试题
这个题目是非常经典的一道题,用两个栈来实现一个队列,问题的关键就在于如何把栈的后进先出通过另外一个栈变成先进先出的逻辑。
基本思想:
用一个栈作为入队列的操作,另一个栈作为出队列的操作。
当需要出队列时,将栈1的数据全部转移到栈2,这样栈低的数据回到栈顶。
可能到这里,有些人把数据从栈2出栈以后,又把栈2的数据回到栈1,其实这个过程是没有必要的,只要栈2不为空,队列每次需要出队列的时候,从栈2直接出栈就行,当栈2为空的时候,在把栈1的数据重新搬移到栈2,当这两个栈都为空的时候,说明队列为空。
具体的实现的代码
class MyQueue
public:
/** Initialize your data structure here. */
MyQueue()
/** Push element x to the back of queue. */
//栈1作为入队列的容器
void push(int x)
st1.push(x);
/** Removes the element from in front of queue and returns that element. */
//栈2作为出队列的容器
int pop()
if(st2.empty())
while(!st1.empty())
st2.push(st1.top());
st1.pop();
int tmp = st2.top();
st2.pop();
return tmp;
/** Get the front element. */
int peek()
if(st2.empty())
while(!st1.empty())
st2.push(st1.top());
st1.pop();
return st2.top();
/** Returns whether the queue is empty. */
//如果栈1栈2都为空,则队列为空
bool empty()
return st1.empty()&&st2.empty();
stack<int> st1;//入
stack<int> st2;//出
;
这也是一道很经典算法题,采用栈这种数据结构。
class Solution
public:
bool isValid(string s)
if(s.size()%2 !=0)//如果不是偶数个符号,则一定不匹配,提前结束迭代
return false;
stack<char> s1;
for(size_t i=0;i<s.size();i++)
if(s1.empty())
s1.push(s[i]);
else if((s1.top()-s[i]<0)&&(s1.top()-s[i]>=(-2)))//利用相邻括号ASCII码差值不超过2
s1.pop();//遇到匹配的括号就出栈
else
s1.push(s[i]);//暂时没有匹配的括号就入栈
if(!s1.empty())//如果栈为空说明括号是匹配的
return false;
else
return true;
;
循环队列是队列的一种延伸,常用在消费者生产者模型
循环队列_smile_zhangw的博客-CSDN博客_循环队列,可以参考这篇文章。
以上是关于数据结构之栈和队列的主要内容,如果未能解决你的问题,请参考以下文章