概要
因为操作的需要现在重新学习了数据结构相关知识,故以此文来总结一下栈和队列的操作和基本知识
声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出
栈和队列的基本概念和实现
1.栈的基本概念
- 栈的定义:栈是一种只能在一端进行插入和删除的线性表。其中允许进行插入和删除的一端称为栈顶
- 栈的特点:先进后出(FILO)
- 栈的存储结构:顺序栈和链式栈,实际上栈的本质是线性表,不过是加了操作限制
2.队列的基本概念
- 队列的定义:和栈类似都是操作受限制的线性表,只允许在一端进行插入(队尾:rear),在一端进行删除(队头:front);
- 队列的特点:先进先出(FIFO)
- 栈的存储结构:顺序队和链式队
栈和队列的存储结构和算法应用
1.顺序栈的定义
typedef struct {
int data[MAXSIZE]; //存放的数据
int top; //栈顶指针
}SqStack;
2.链栈结点定义
typedef struct LNode{
int data;
struct LNode *next;
}LNode;
3.顺序队列的定义
typedef struct {
int data; //数据域
int front; //队头指针
int rear; //队尾指针
}SqQueue;
4.链队的定义
//队结点的定义
typedef struct QNode{
int data; //数据域
struct QNode *next;
}QNode;
//链队类型的定义
typedef struct QNode{
QNode *rear; //队尾指针
QNode *front; //队头指针
}LiQueue;
5.顺序栈的基本操作
顺序栈有四要素:两个特殊状态(栈满\栈空),两个操作(入栈\出栈)
- 栈空的状态:
st.top == -1
- 栈满的状态:
//因为栈是特殊数组,元素下标从0开始
st.top == MAXSIZE-1
- 入栈操作:
//要先操作栈顶指针,再赋值
++(st.top);
st.data[st.top]=x;
//或者
st[++top]=x;
- 出栈操作:
//先读取数据再操作栈顶指针
x=st.data[st.top];
--(st.top);
//或者
x=st[top--];
- 初始化栈
void InitStack(SqStack &st){
st.top==-1;
}
- 判断栈为空
bool IsEmpty(const SqStack st){
if(st.top == -1)
return ture;
return false;
}
- 进栈
bool push( SqStack &st,int x){
//判断栈是否未满
if(st.top == MAXSIZE-1)
return false;
else{
++(st.top);
st.data[st.top]=x;
return true;
}
}
- 出栈
//对数据进行改变的要传入地址
bool pop( SqStack &st,int &x){
//判断栈是否为空
if(st.top == -1)
return false;
else{
x=st[top];
--(st.top);
return true;
}
}
6.链栈的基本操作
链表栈有四要素:两个特殊状态(栈满\栈空),两个操作(入栈\出栈)
- 初始化链栈
void InitStack(Lnode *lst){
lst=(Lnode *)malloc(sizeof(Lnode));
lst->next=NULL;
}
- 判断链栈为空
bool IsEmpty(const LNode *st){
if(lst->next==NULL)
return ture;
return false;
}
- 进栈
void push( LNode *st,int x){
LNode *p; //新建结点
p=(LNode)malloc(sizeof(LNode));
p->next=NULL;
//头插法插入
p->data=x;
p->next=st->next;
st->next=p;
}
- 出栈
//对数据进行改变的要传入地址
bool pop( LNode *st,int &x){
//栈空不能出栈
if(st->next ==NULL)
return fasle;
else{
Lnode *p;
p=st->next;
x=p->data;
st->next=p->next;
free(p);
return true;
}
}
- 顺序栈的应用
//利用顺序栈来判断字符数组exp中的()是否成对,其中字符个数为n
bool IsMatch(char exp[],int n){
//初始化链表
char statck[maxsize];
int i,top = -1;
//遍历寻找(
for(i=0;i<n;i++){
if(exp[i]=='(') //入栈
statck[++top]='(';
if(exp[i]==')'){
//栈空不匹配
if(top == -1)
return false;
else //出栈
--top;
}
}
//最后判断,如果栈空,则成对
if(top == -1)
return ture;
else
return false;
}
7.顺序队的基本操作
顺序队有四要素:两个特殊状态(队满\队空),两个操作(入队\出队)
- 初始化顺序队
void initqueue(Squeue &qu){
qu.rear=qu.rear=0; //队首和队尾指针重合,指向0
}
- 判断顺序队为满
void queueisFull(Squeue qu){
if((qu.rear+1)%maxsize==qu.front)
return ture;
else
return false;
}
- 进队
int enQueue(Squeue &qu,int x){
if((qu.rear+1)%maxsize==qu.front) //如果队列为满则不能入队
return 0;
qu.rear=(qu.rear+1)%maxsize; //如果队列未满,则先移动指针
qu.data[qu.rear]=x;
return 1;
}
- 出队
int deQueue(Squeue &qu,int &x){
if(qu.rear==qu.front) //如果队列为空则不能出
return 0;
qu.front=(qu.front+1)%maxsize; //如果队列非空,则先移动指针
x=qu.data[qu.front];
return 1;
}
7.链队的基本操作
顺序队有四要素:两个特殊状态(队满\队空),两个操作(入队\出队)
- 初始化链队
void initQueue(LiQueue *qu){
qu=(LiQueue*)malloc(sizeof(LiQueue));
qu->rear=qu->rear=NULL;
}
- 判断链队为空
bool QueueIsEmpty(LiQueue *qu){
if((qu->rear==NULL)||qu->rear=NULL)
return true;
else
return false;
}
- 入队算法
void EnQueue(LiQueue *qu,int x){
LiQueue *p;
p=(LiQueue *)malloc(sizeof(LiQueue));
p->data = x;
p->next=NULL;
//如果链表为空则新节点为队首结点(也是队尾结点)
if(qu.rear==qu.front=NULL)
qu->front=qu->rear=p;
else{
qu->rear->next=p;
qu->rear=p;
}
}
- 出队算法
int EnQueue(LiQueue *qu,int &x){
LiQueue *p; //删除的结点,要释放内存
//如果链表为空不能出队
if(qu.rear==qu.front=NULL)
return 0;
else
p=qu->front;
//队列中只有一个结点的时候
if(qu->rear=qu->front)
qu.rear==qu.front=NULL;
else
qu->front=qu->front->next;
x=p->data;
free(p);
return 1;
}
应用案例
1.利用两个栈来实现队列的功能
栈的特点是先进后出,队列的特点是先进先出。故当有两个栈S1,S2来模拟队列的时候,可以将S1用作数据的输入,入栈操作,要将数据输出的时候将S1的数据入栈到S2,故栈底元素变成栈顶元素,所以先进先出也就实现了。
具体实现
#define MaxSize 100
//栈定义
typedef struct {
int top;
int data[MaxSize];
}stack;
//判断栈是否为空
int isEmpty(stack s){
if(s.top == -1)
return 1
else
return 0
}
//入栈
int push(stack s,int x){
if(s.top == MaxSize -1)
return 0
else{
s.data[++s.top]=x;
}
return 1;
}
//出栈
int pop(stack s,int &x){
if(isEmpty(s))
return 0
else{
x=s.data[s.top--];
return 1;
}
}
//判断队列是否为空
//两个栈都为空:队列为空
int IsQueueEmpty(stack s1,stack s2){
if(s1.top != -1 && s2.top != -1)
return 0
else
return 1
}
//入队操作
int enQueue(stack s1,stack s2,int x){
int temp;
//s1负责入队操作,故先判断s1里面的数据是否为满
if(s1.top == MaxSize -1){
if(!isEmpty(s2))
return 0; //s1满s2非空,不能入栈
else if(isEmpty(s2)){
while(!isEmpty(s1)){ //循环将s1数据放入s2
pop(s1,temp);
push(s2,temp);
}
push(s1,x); //x入栈实现了元素入队
return 1;
}
}
else{
push(s1,x); //s1未满直接入s1
return 1;
}
}
//出队操作
int deQueue(stack s1,stack s2,int &x){
//s2栈顶元素退栈,实现出队操作,x接收出队元素
int temp;
//s2不为空直接出队
if(!isEmpty(s2)){
push(s2,x);
}else{
if(isEmpty(s1)){ //输入栈也为空
return 0;
}
else{
while(isEmpty(s1)){
pop(s1,y);
push(s2,y);
}
pop(s2,x);
return 1;
}
}
}
而塞过 2021-3-26
关于我:一个就要进入互联网,经历社会毒打的99小伙