栈与队列(数据结构笔记)
3.栈与队列
3.1栈
限定仅在表尾进行插入和删除操作的线性表。
允许插入和删除的一端称为栈顶,另一端称为栈底。
后进先出的线性表。
栈的抽象数据类型
Data
同线性表。
Operation
InitStack(*S):初始化操作,建立一个空栈S。
DestroyStack(*S):销毁栈。
ClearStack(*S):清空栈。
StackEmpty(S):若栈为空,返回true,否则返回false。
GetTop(S,*e):返回栈顶元素。
Push(*S,e):插入元素。
Pop(*S,e):删除元素。
StackLength(S):返回栈的元素个数。
3.3.1栈的顺序实现
//栈的结构定义
typedef int SElemType;
typedef struct
{
SElemType data[MAXSIZE];
int top;//用于栈底指针
}SqStack;
3.3.2进栈
Status Push(SqStack *S,SEleType e)
{
if(S->top == MAXSIZE-1)//栈满
{
return ERROR;
}
S->top++;
S->data[S->top]=e;
return OK;
}
3.3.3出栈
Status Pop(SqStack *S,SElemType *e)
{
if(S->top==-1)
{
return ERROR;
}
*e=S->data[S->top];
S->top--;
return OK;
}
3.4 两栈共享空间
//结构
typedef struct
{
SElemType data;
int top1;
int top2;
}SqDoubleStack;
//入栈
Status Push(SqDoubleStack *S,SElemType e,int stackNumber)
{
if(S->top1+1==S->top2)
{
return ERROR;
}
if(stackNumber==1)
S->data[++S->top1]=e;
if(stacNumber==2)
S->data[--S->top2]=e;
return OK;
}
//出栈
Status Pop(SqDoubleStack *S,SElemType *e,int stackNumber)
{
if(stackNumber==1)
{
if(S->top1==-1)
return REEOR;
*e=S->data[S->top1--];
}
if(stackNumber==2)
{
if(S->top2==MAXSIZE)
return REEOR;
*e=S->data[S->top1++];
}
return OK;
}
3.5栈的链式存储结构即实现
通常链栈是不需要头结点的。
//链栈的存储结构
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode,*LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}
//进栈
Status Push(LinkStack *S,SElemType e)
{
LinkStackPtr s=new StackNode;
s->data=e;
s->next=S->top;
S->top=s;
S->count++;
return OK;
}
//出栈
Staus Pop(LinkStack *S,SElemType *e)
{
LinkStackPtr p;
if(StackEmpty(S))
return ERROR;
e=S->top->data;
p=S->top;
S->top=S->top->next;
free(p);
S->count--;
return OK;
}
3.6栈的应用——递归
直接调用自己或同一系列调用语句间接调用自己的函数,称为递归函数。
每个递归至少有一个条件,满足递归时不再进行,即不在引用自身而是返回值退出。
3.7四则表达式的运算
3.7.1后缀(逆波兰)表示法定义
举例:9 3 1 - 3 * + 10 2 / +
9,3,1先进栈,减号也进栈,然后计算3-1=2,2进栈,3进栈,*进栈,2 *3=6,6进栈,+进栈,9+6=15,15进栈,10进栈,2进栈,/进栈,10/2=5,5进栈,+进栈,15+5=20,20进栈,20出栈,栈为空。
3.7.2中缀表达式转后缀表达式
标重的四则运算表达式为中缀表达式。
规则,参考书p109。
3.8 队列
ADT 队列(Queue)
Data
同线性表
Operation
InitQueue(*Q):初始化
DestroyQueue(*Q):销毁
ClearQueue(*Q):清空
QueueEmpty(Q):判断是否为空
GetHead(Q,*e):用e返回队头元素
EnQueue(Q,*e):插入
DeQueue(Q,*e):删除
QueueLenght(Q):返回队列元素个数
endADT
3.8.1循环队列
队列的头尾相接的顺序存储结构称为循环队列。
顺序存储结构
#include<iostream>
using namespace std;
typedef int Status;
const int MAXSIZE = 100;
const int OK = 1;
const int ERROR = -1;
template<typename QElemType>
class SqQueue
{
public:
SqQueue() // 初始化
{
this->front = 0;
this->rear = 0;
}
Status QueueEmpty(); // 判断是否为空
Status GetHead(QElemType *e); // 用e返回队头元素
Status EnQueue(QElemType e); // 入队
Status DeQueue(QElemType* e); // 出队
Status QueueLenght(); // 返回队列元素个数
private:
QElemType data[MAXSIZE];
int front;
int rear;
};
#include"Queue.h"
using namespace std;
template<typename QElemtype>
Status SqQueue<QElemtype>::QueueEmpty()
{
if (this->front == this->rear)
return OK;
}
template<typename QElemType>
Status SqQueue<QElemType>::GetHead(QElemType* e)// 用e返回队头元素
{
if (this->QueueEmpty())
return ERROR;
*e = this->data[this->front];
}
template<typename QElemType>
Status SqQueue<QElemType>:: EnQueue(QElemType e)
{
if ((this->rear + 1) % MAXSIZE == this->front)
return ERROR;
this->data[this->rear] = e;
this->rear = (this->rear + 1) % MAXSIZE;
return OK;
}
template<typename QElemType>
Status SqQueue<QElemType>::DeQueue(QElemType* e)
{
if (this->QueueEmpty())
return ERROR;
*e = this->data[this->front];
this->front = (this->front + 1) % MAXSIZE;
return OK;
}
template<typename QElemType>
Status SqQueue<QElemType>::QueueLenght()
{
return(this->rear - this->front + MAXSIZE) % MAXSIZE;
}
队列的链式存储
#include<iostream>
using namespace std;
typedef int Status;
const int OK = 1;
const int ERROR = -1;
template<typename QElemType>
class QNode//结点
{
public:
QElemType data;
QNode* next;
};
template<typename QElemType>
class LinkQueue//链队结构
{
public:
Status EnQueue(QElemType e);
Status DeQueue(QElemType *e);
private:
QNode<QElemType>* front, rear;
};
#include"QNode.h"
template<typename QElemType>
Status LinkQueue<QElemType>::EnQueue(QElemType e)
{
QNode<QElemType>* p = new QNode;
if (!p) // 存储空间分配失败
exit(OVERFLOW);
p->data = e;
p->next = NULL;
this->rear->next = p;
this->rear = p;
return OK;
}
template<typename QElemType>
Status LinkQueue<QElemType>::DeQueue(QElemType *e)
{
if (this->front == this->rear)
return ERROR;
QNode<QElemType>* p;
p = this->front->next;
*e = p->data;
this->front->next = p->next;
if (this->rear = p)
this->rear = this->front;
delete p;
return OK;
}
3.9栈与队列练习题
3.9.1括号匹配问题
class Solution {
public:
bool isValid(string s) {
stack<char> s1;
if(s.size()%2!=0)
return false;
for (int i = 0; i < s.size(); ++i)
{
if (s[i] == '(' || s[i] == '[' || s[i] == '{')
s1.push(s[i]);
else
{
if(s1.empty())
return false;
char top = s1.top();
if ((top == '(' && s[i] == ')') || (top == '[' && s[i] == ']') || (top == '{' && s[i] == '}'))
s1.pop();
else
return false;
}
}
return s1.empty();
}
};
3.9.2用队列实现栈
class MyStack {
public:
MyStack() {
}
void push(int x) {
//先判断栈是否为空
if(empty())
{
q1.push(x);
return;
}
//如果不为空,在有数据的那个队列里入队元素
if(!q1.empty())
q1.push(x);
else
q2.push(x);
}
int pop() {
//将有数据的队列中的数据放入另一个队列中,只留最后一个输出
if(!q1.empty())
{
int n = q1.size();
for(int i=0;i<n-1;++i)
{
q2.push(q1.front());
q1.pop();
}
int num=q1.front();
q1.pop();
return num;
}
else
{
int n = q2.size();
for(int i=0;i<n-1;++i)
{
q1.push(q2.front());
q2.pop();
}
int num=q2.front();
q2.pop();
return num;
}
}
int top() {
if(!q1.empty())
return q1.back();
return q2.back();
}
bool empty() {
if(q1.empty()&&q2.empty())
return true;
return false;
}
private:
queue<int> q1;
queue<int> q2;
};
3.9.3用栈实现队列
class MyQueue {
public:
MyQueue() {
}
void push(int x) {
stk1.push(x);
}
int pop() {
if(empty())
return 0;
if(stk2.empty())
{
while(!stk1.empty())
{
stk2.push(stk1.top());
stk1.pop();
}
}
int num=stk2.top();
stk2.pop();
return num;
}
int peek() {
if(empty())
return 0;
if(stk2.empty())
{
while(!stk1.empty())
{
stk2.push(stk1.top());
stk1.pop();
}
}
return stk2.top();
}
bool empty() {
return stk1.empty()&&stk2.empty();
}
private:
stack<int> stk1;
stack<int> stk2;
};