目录
1 栈
栈(stack)是只允许在一端进行插入或删除操作的线性表。后进先出(Last in First Out,LIFO)
n个元素进栈,出栈元素不同排列的个数为(卡特兰数)。
1.1 顺序栈:用顺序存储方式实现的栈
top指针指向栈顶元素
typedef struct{
ElemType data[MaxSize];//静态数组
int top;//栈顶指针,指向栈顶元素 (不空,等于栈顶元素的下标)
}SqStack;
初始化
//初始化
void InitStack(SqStack &S){
S.top=-1;
}
具体实现
#include<iostream>
using namespace std;
#define MaxSize 10
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];//静态数组
int top;//栈顶指针,指向栈顶元素 (不空,等于栈顶元素的下标)
}SqStack;
//初始化
void InitStack(SqStack &S){
S.top=-1;
}
//判断栈空
bool StackEmpty(SqStack S){
if(S.top==-1) return true;
else return false;
}
//新元素入栈
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-1){
return false;
}
S.top++;//栈顶指针先加1
S.data[S.top]=x;
return true;
}
//出栈
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1) return false;
x=S.data[S.top];
S.top--;
}
//读栈顶元素
bool GetTop(SqStack S,ElemType &x){
if(S.top==-1){
return false;
}
x=S.data[S.top];
return true;
}
//打印输出
void Print(SqStack S){
for(int i=0;i<=S.top;i++){
cout<<S.data[i]<<" ";
}
cout<<endl;
}
int main(){
SqStack S;
InitStack(S);
cout<<"------------------入栈--------------------"<<endl;
for(int i=0;i<10;i++){
Push(S,i);
}
Print(S);
cout<<"------------------出栈--------------------"<<endl;
int x;
Pop(S,x);
Print(S);
cout<<"出栈的元素为:"<<x<<endl;
cout<<"------------------读栈顶元素--------------------"<<endl;
int y=0;
GetTop(S,y);
cout<<"栈顶元素为:"<<y<<endl;
return 0;
}
1.2 链栈:用链式存储方式实现的栈
和单链表类似,链栈的入栈即对头结点的后插操作,链栈的出栈即对头结点的后删操作。
链头=栈顶
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}*LiStack;
1.3 栈的应用
1.3.1 栈在括号匹配中的应用
以下链接的文章提供了具体代码,可直接运行。
1.3.2 栈在表达式求值中的应用
1.3.3 栈在递归中的应用
2 队列
队列(queue)是只允许在一端进行插入,另一端进行删除的线性表。先进先出(First in First Out,FIFO)
2.1 队列的顺序实现
typedef struct{
ElemType data[MaxSize];
int front,rear;//队头指针和队尾指针,队尾指针指向当前元素的下一个元素
}SqQueue;
初始化
//初始化
void InitQueue(SqQueue &Q){
Q.rear=Q.front=0;
}
具体实现
#include<iostream>
using namespace std;
#define MaxSize 10
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];
int front,rear;//队头指针和队尾指针,队尾指针指向当前元素的下一个元素
}SqQueue;
//初始化
void InitQueue(SqQueue &Q){
Q.rear=Q.front=0;
}
//判断队列是否为空
bool QueueEmpty(SqQueue Q){
if(Q.front==Q.rear){
return true;
}else{
return false;
}
}
//入队
bool EnQueue(SqQueue &Q,ElemType x){
if((Q.rear+1)%MaxSize==Q.front) return false;//队列已满 (浪费一个空间,防止和队列为空一样的判断情况)
Q.data[Q.rear]=x;
Q.rear=(Q.rear+1)%MaxSize;
return true;
}
//出队
bool OutQueue(SqQueue &Q,ElemType &x){
if(Q.rear==Q.front) return false;//队列为空
x=Q.data[Q.front];
Q.front=(Q.front+1)%MaxSize;
return true;
}
//获得队头元素的值,用x返回
bool GetHead(SqQueue Q,ElemType &x){
if(Q.front==Q.rear) return false;
x=Q.data[Q.front];
return true;
}
//返回队列元素个数
int Length(SqQueue Q){
return (Q.rear-Q.front+MaxSize)%MaxSize;
}
//输出
void Print(SqQueue Q){
int end=Q.rear;
if(Q.rear<Q.front) end+=MaxSize;
for(int i=Q.front;i<end;i++){
cout<<Q.data[i%MaxSize]<<" ";
}
cout<<endl;
}
int main(){
SqQueue Q;
InitQueue(Q);
cout<<"------------------入队----------------------"<<endl;
for(int i=0;i<10;i++){
EnQueue(Q,i);
}
Print(Q);
cout<<"------------------出队----------------------"<<endl;
int x=0;
OutQueue(Q,x);
Print(Q);
cout<<"出队的元素为:"<<x<<endl;
cout<<"------------------队头元素----------------------"<<endl;
int y=0;
cout<<"队头元素是:"<<GetHead(Q,y)<<endl;
cout<<"------------------队列元素个数----------------------"<<endl;
cout<<"个数为:"<<Length(Q)<<endl;
return 0;
}
2.2 队列的链式实现
带头结点
typedef struct LinkNode{//链式队列结点
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{//链式队列
LinkNode *front,*rear;
}LinkQueue;
初始化
//初始化(带头结点)
void InitQueue(LinkQueue &Q){
Q.front=Q.rear=new LinkNode;//Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
具体实现
#include<iostream>
using namespace std;
typedef int ElemType;
typedef struct LinkNode{//链式队列结点
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{//链式队列
LinkNode *front,*rear;
}LinkQueue;
//初始化(带头结点)
void InitQueue(LinkQueue &Q){
Q.front=Q.rear=new LinkNode;//Q.front=Q.rear=(LinkNode *)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
//判断队列是否为空
bool IsEmpty(LinkQueue Q){
if(Q.front==Q.rear) return true;
else return false;
}
//入队(带头结点)
void EnQueue(LinkQueue &Q,ElemType x){
LinkNode *s=new LinkNode;//LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;
s->next=NULL;
Q.rear->next=s;
Q.rear=s;//修改表尾指针
}
//出队(带头结点)
bool DeQueue(LinkQueue &Q,ElemType &x){
if(Q.front==Q.rear) return false;//队空
LinkNode *p=Q.front->next;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front;//如果是最后一个结点出队
delete p;
return true;
}
//输出
void Print(LinkQueue Q){
LinkNode *p=Q.front->next;
while(p){
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
int main(){
LinkQueue Q;
InitQueue(Q);
cout<<"----------------入队------------------"<<endl;
for(int i=0;i<10;i++){
EnQueue(Q,i);
}
Print(Q);
cout<<"----------------出队------------------"<<endl;
int x=0;
DeQueue(Q,x);
Print(Q);
cout<<"出队的元素为:"<<x<<endl;
return 0;
}
2.3 队列的应用
2.3.1 树的层次遍历
bfs广度优先
2.3.2 图的广度优先遍历
2.3.3 队列在操作系统中的应用
多个进程争抢这使用有限的系统资源时,FCFS(First Come First Service,先来先服务)是一种常用策略。(队列实现)
电脑只有一个CPU,而为什么有那么多的应用可以同时进行呢?通过队列实现,一个应用先出队,CPU运行其一段时间,再入队,然后运行下一个出队的应用。
3 双端队列
主要考察对输出序列合法性的判断