栈和队列的知识点以及代码详解

栈和队列是线性表的子集(是插入和删除位置受限的线性表)。

简单点说,栈和队列是限定插入和删除只能在表的“端点”进行的线性表。

再简单形象点来说:

普通线性表

Insert(L,i,x)   //可以插入在表的任意位置(表头,表尾,表中间)

1<=i<=n+1

Delete(L,i)   //可以删除表中的任意元素

1<=i<=n

特殊线性表

栈:

Insert(S,n+1,x)  //只能在表尾插入,即第n+1个位置 

Delete(S,n)  //只能删除表尾的元素,即第n个元素

队列:

Insert(Q,n+1,x)  //只能在表尾(即队尾)插入,即第n+1个位置

Delete(Q,1)  //只能删除表头(即队头)的元素,即第1个元素

目录

(一)栈(stack)

定义

示意图

下面我们用一道题来帮助理解的更深刻,更透彻

特点

顺序栈(用顺序存储结构来存储栈)的基本操作以及代码实现

基本操作

代码

 链栈(用链式存储结构来存储栈)的代码实现

代码:

栈与递归

 以下三种情况常常用到递归方法

 递归的求解

递归的优缺点

 递归-->非递归

(二)队列

定义

特点

在循环队列中我们经常会遇到的问题以及解决方法

1.假上溢

2.判断队空与队满

 另外在求队列长度时

循环队列的顺序实现代码实现

代码

链队的基本操作以及代码实现

基本操作

代码


(一)栈(stack)

定义

示意图:

下面我们用一道题来帮助理解的更深刻,更透彻:

问题:假设有3个元素a,b,c,其入栈顺序为a,b,c,则其出栈顺序可以有:

 c,b,a

让a,b,c依次入栈,再依次出栈。

a,b,c

让a入栈再出栈,b入栈再出栈,c入栈再出栈。

a,c,b

先让a进栈再出栈,然后b,c依次进栈再出栈。

b,a,c

先让a,b依次进栈再出栈,然后再让c进栈再出栈。

b,c,a

先让a,b进栈,然后b出栈,再让c进栈,最后让a,c依次出栈。

就以上5种情况,不能再多了。

特点:

后进先出(Last In First Out)或先进后出(First In Last Out)

顺序栈(用顺序存储结构来存储栈)的基本操作以及代码实现:

基本操作

上溢:栈已满,仍继续压入元素。

下溢:栈已空,仍继续弹出元素。

上溢是一种错误,使问题的处理无法进行;而下溢一般认为是一种结束条件,即问题处理结束。

栈满时分配更大空间:先分配一个空间更大的栈,将原栈中的元素全都移入,然后将原栈所占空间释放掉。因其操作太复杂,所以一般不采用这种方式

代码:

#include<iostream>
using namespace std;
//函数结果状态代码
#define OK     1
#define ERROR  0
#define OVERFLOW   -2
#define TRUE   1
#define FALSE  0
typedef char SElemType; //SElemtype 相当于 char 
typedef int Status;    // Status 相当于 int 
#define  MAXSIZE  100    
//定义 
typedef struct{
	SElemType *base; 
	SElemType *top;
	int stacksize;
}SqStack;
Status InitStack(SqStack &S);//初始化操作,建立一个空的顺序栈 
Status Push(SqStack &S,SElemType e);//顺序栈入栈 
SElemType Pop(SqStack &S,SElemType &e);//顺序栈出栈 ,若栈不空,则删除S的栈顶元素,用e返回,并返回OK,否则返回ERROR 
Status StackEmpty(SqStack S);//判断顺序栈是否为空 ,若为空,返回TRUE;否则返回FALSE 
int StackLength(SqStack S);  //求顺序栈长度  
void ClearStack(SqStack &S);  //清空顺序栈 
void DestroyStack(SqStack &S);//销毁顺序栈 
int main()
{
	SqStack S;
	if(InitStack(S)) 
	cout<<"成功创建顺序栈"<<endl;
	if(Push(S,'a'))
	cout<<"元素a入栈成功"<<endl;
	if(Push(S,'b'))
	cout<<"元素b入栈成功"<<endl;
	if(Push(S,'c'))
	cout<<"元素c入栈成功"<<endl;
	char e;
	if(Pop(S,e))
	cout<<"元素"<<e<<"出栈成功"<<endl;
	if(StackEmpty(S))
	   cout<<"顺序栈为空"<<endl;
	else
	   cout<<"顺序栈不为空"<<endl;   
	cout<<"此时顺序栈的长度为:"<<StackLength(S)<<endl;   
	ClearStack(S);
	cout<<"顺序栈已清空"<<endl;
	DestroyStack(S);
	cout<<"顺序栈已销毁"<<endl; 
}
//顺序栈的初始化
Status InitStack(SqStack &S)
{
	S.base=new SElemType[MAXSIZE];//或S.base=(SElemType*)malloc(sizeof(SElemType)*MAXSIZE); 
	if(!S.base) exit(OVERFLOW);//存储分配失败
	S.top=S.base;
	S.stacksize =MAXSIZE;
	return OK;
}
//顺序栈入栈
Status Push(SqStack &S,SElemType e)
{
	if(S.top-S.base==S.stacksize)//栈满 
	return ERROR;
	*S.top=e;//这两步等价于*S.top++=e;
	S.top++;
	return OK;
} 
//顺序栈出栈 
SElemType Pop(SqStack &S,SElemType &e)
{
    if(S.top==S.base)//等价于if(StackEmpty(S)),即栈空 
	return ERROR;
	--S.top;//这两步等价于 e=*--S.top;
	e=*S.top;
	return OK;	
} 
//判断顺序栈是否为空 
Status StackEmpty(SqStack S)
{
	if(S.base==S.top)
	   return TRUE;
	else
	   return FALSE;
} 
//求顺序栈长度  
int StackLength(SqStack S)
{
	return S.top-S.base;
}
//清空顺序栈 
void ClearStack(SqStack &S)
{
	if(S.base) S.top=S.base;
} 
//销毁顺序栈 
void DestroyStack(SqStack &S)
{
	if(S.base)
	{
		delete S.base;
		S.stacksize=0;
		S.base=S.top=NULL;
	}
} 

运行结果:

 

 链栈(用链式存储结构来存储栈)的代码实现:

代码:

#include<iostream>
using namespace std;
//函数结果状态代码
#define OK     1
#define ERROR  0
#define OVERFLOW   -2
#define TRUE   1
#define FALSE  0
typedef char SElemType; //SElemtype 相当于 char 
typedef int Status;    // Status 相当于 int 
#define  MAXSIZE  100    
//定义 
typedef struct StackNode{
	SElemType data; 
    struct StackNode *next;
}StackNode,*LinkStack;
Status InitStack(LinkStack &S);//初始化操作,建立一个空的链栈 
Status Push(LinkStack &S,SElemType e);//链栈入栈 
SElemType Pop(LinkStack &S,SElemType &e);//链栈出栈 ,若栈不空,则删除S的栈顶元素,用e返回,并返回OK,否则返回ERROR
SElemType GetTop(LinkStack S);//取栈顶元素 
Status StackEmpty(LinkStack S);//判断链栈是否为空 ,若为空,返回TRUE;否则返回FALSE 
void ClearStack(LinkStack  &S);  //清空链栈 
void DestroyStack(LinkStack &S);//销毁链栈 
int main()
{
	LinkStack S;
	if(InitStack(S)) 
	cout<<"成功创建链栈"<<endl;
	if(Push(S,'a'))
	cout<<"元素a入栈成功"<<endl;
	if(Push(S,'b'))
	cout<<"元素b入栈成功"<<endl;
	if(Push(S,'c'))
	cout<<"元素c入栈成功"<<endl;
	char e;
	if(Pop(S,e))
	cout<<"元素"<<e<<"出栈成功"<<endl; 
	cout<<"取栈顶元素:"<<GetTop(S)<<endl; 
	if(StackEmpty(S))
	   cout<<"链栈为空"<<endl;
	else
	   cout<<"链栈不为空"<<endl;   
	ClearStack(S);
	cout<<"链栈已清空"<<endl;
	DestroyStack(S);
	cout<<"链栈已销毁"<<endl; 
}
//链栈的初始化
Status InitStack(LinkStack  &S)
{
	S=NULL;//构造一个空栈,栈顶指针置为空 
	return OK;
}
//链栈入栈
Status Push(LinkStack  &S,SElemType e)
{
	LinkStack p;
	p=new StackNode;//生成新结点p
	p->data=e;//将新结点数据域置为e 
	p->next=S;//将新结点插入栈顶 
	S=p;//修改栈顶指针 
	return OK; 
} 
//链栈出栈 
SElemType Pop(LinkStack  &S,SElemType &e)
{
	LinkStack p;
    if(S==NULL) return ERROR;
	e=S->data;
	p=S;
	S=S->next;
	delete p;
	return OK; 
} 
//取栈顶元素
SElemType GetTop(LinkStack S)
{
	if(S!=NULL)
	return S->data;
} 
//判断链栈是否为空 
Status StackEmpty(LinkStack  S)
{
	if(S==NULL)
	   return TRUE;
	else
	   return FALSE;
} 
//清空链栈 
void ClearStack(LinkStack  &S)
{
	if(S) S=NULL;
} 
//销毁链栈 
void DestroyStack(LinkStack  &S)
{
	if(S)
	{
		delete S;
	}
} 

运行结果:

 

栈与递归:

 以下三种情况常常用到递归方法:

1.递归定义的数学函数:

2.具有递归特性的数据结构:

3.可递归求解的问题:

 递归的求解:

 ----分治法:

递归的优缺点: 

 递归-->非递归:

1.递归:

2.非递归:

1》尾递归,单向递归-->循环结构

2》 借助栈来改写递归:

由上可见,一般情况下,我们还是采用递归的方法,但如果时间效率要求比较高, 那我们再考虑将其转化为非递归的程序。

(二)队列

定义

特点:

先进先出(First In First Out)

在循环队列中我们经常会遇到的问题以及解决方法

1.假上溢:

就是尾指针已经指到了队尾,且头指针与尾指针之间都有元素(元素已满),但头指针与队头之间仍有空着。

具体如下图所示:

 解决方法:

2.判断队空与队满:

队空与队满时条件一样,如下图所示:

解决方法:

 

 另外在求队列长度时:

循环队列的顺序实现代码实现:

代码:

#include<iostream>
using namespace std;
//函数结果状态代码
#define OK     1
#define ERROR  0
#define OVERFLOW   -2
#define TRUE   1
#define FALSE  0
typedef char QElemType; //SElemtype 相当于 char 
typedef int Status;    // Status 相当于 int 
#define  MAXQSIZE  100    
//定义 
typedef struct{
	QElemType *base; 
	int frort;//头指针 
	int rear;//尾指针 
}SqQueue;
Status InitQueue(SqQueue &Q);//初始化操作,建立一个空的队列 
Status EnQueue(SqQueue &Q,QElemType e);//循环队列入队
QElemType DeQueue(SqQueue &Q,QElemType &e);//循环队列出队,若队不为空,则删除S的队顶元素,用e返回,并返回OK,否则返回ERROR 
QElemType GetHead(SqQueue Q);//取队头元素 
Status QueueEmpty(SqQueue Q);//判断循环队列是否为空 ,若为空,返回TRUE;否则返回FALSE 
int QueueLength(SqQueue Q);  //求队列的 长度  
void ClearQueue(SqQueue &Q);  //清空循环队列 
void DestroyQueue(SqQueue &Q);//销毁循环队列 
int main()
{
	SqQueue Q;
	if(InitQueue(Q)) 
	cout<<"成功创建队列"<<endl;
	if(EnQueue(Q,'a'))
	cout<<"元素a入队成功"<<endl;
	if(EnQueue(Q,'b'))
	cout<<"元素b入队成功"<<endl;
	if(EnQueue(Q,'c'))
	cout<<"元素c入队成功"<<endl;
	char e;
	if(DeQueue(Q,e))
	cout<<"元素"<<e<<"出队成功"<<endl; 
	if(QueueEmpty(Q))
	   cout<<"循环队列为空"<<endl;
	else
	   cout<<"循环队列不为空"<<endl;   
	cout<<"该循环队列的长度为:"<<QueueLength(Q)<<endl;   
	ClearQueue(Q);
	cout<<"循环队列已清空"<<endl;
	DestroyQueue(Q);
	cout<<"循环队列已销毁"<<endl; 
}
//初始化 
Status InitQueue(SqQueue &Q)
{
	Q.base=new QElemType[MAXQSIZE];//或Q.base=(QElemType*)malloc(sizeof(QElemType)*MAXQSIZE); 
	if(!Q.base) exit(OVERFLOW);//存储分配失败
	Q.frort=Q.rear=0;//头指针尾指针置为0,队列为空 
	return OK;
}
//循环队列入队 
Status EnQueue(SqQueue &Q,QElemType e)
{
	if((Q.rear+1)%MAXQSIZE==Q.frort) return ERROR;//队满
	Q.base[Q.rear]=e;          //新元素加入队尾 
	Q.rear=(Q.rear+1)%MAXQSIZE;//队尾指针+1 
	return OK;
} 
//循环队列出队 
QElemType DeQueue(SqQueue &Q,QElemType &e)
{
    if(Q.frort==Q.rear)	return ERROR;//队空 
    e=Q.base[Q.frort];               //保存队头元素 
    Q.frort=(Q.frort+1)%MAXQSIZE;    //队头指针+1 
    return OK;
} 
//取队头元素
QElemType GetHead(SqQueue Q)
{
	if(Q.frort!=Q.rear) //队列不为空
	return Q.base[Q.frort];//返回队头指针元素的值,队头指针不变 
} 
//判断循环队列是否为空 
Status QueueEmpty(SqQueue Q)
{
	if(Q.frort==Q.rear)
	   return TRUE;
	else
	   return FALSE;
} 
//求循环队列长度  
int QueueLength(SqQueue Q)
{
	return((Q.rear-Q.frort+MAXQSIZE)%MAXQSIZE);
}
//清空循环队列 
void ClearQueue(SqQueue &Q)
{
	if(Q.base) Q.frort==Q.rear;
} 
//销毁循环队列 
void DestroyQueue(SqQueue &Q)
{
	if(Q.base)
	{
		delete Q.base;
		Q.frort==Q.rear;
	}
} 

运行结果:

链队的基本操作以及代码实现:

基本操作

代码:

#include<iostream>
using namespace std;
//函数结果状态代码
#define OK     1
#define ERROR  0
#define OVERFLOW   -2
#define TRUE   1
#define FALSE  0
typedef char QElemType; //SElemtype 相当于 char 
typedef int Status;    // Status 相当于 int 
#define  MAXQSIZE  100    
//定义 
typedef struct QNode{
	QElemType data; 
	struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
	QueuePtr front;
	QueuePtr rear;
}LinkQueue;
Status InitQueue(LinkQueue &Q);//初始化操作,建立一个空的链队列 
Status EnQueue(LinkQueue &Q,QElemType e);//链队列入队
QElemType DeQueue(LinkQueue &Q,QElemType &x);//链队列出队,若队不为空,则删除S的队顶元素,用e返回,并返回OK,否则返回ERROR 
QElemType GetHead(LinkQueue Q);//取链队头元素 
Status QueueEmpty(LinkQueue Q);//判断链队列是否为空 ,若为空,返回TRUE;否则返回FALSE
void ClearQueue(LinkQueue &Q);  //清空链队列 
void DestroyQueue(LinkQueue &Q);//销毁链队列 
int main()
{
	LinkQueue Q;
	if(InitQueue(Q)) 
	cout<<"成功创建链队列"<<endl;
	if(EnQueue(Q,'a'))
	cout<<"元素a入队成功"<<endl;
	if(EnQueue(Q,'b'))
	cout<<"元素b入队成功"<<endl;
	if(EnQueue(Q,'c'))
	cout<<"元素c入队成功"<<endl;
	char e;
	if(DeQueue(Q,e))
	cout<<"元素"<<e<<"出队成功"<<endl; 
	cout<<"取链队头元素:"<<GetHead(Q)<<endl; 
	if(QueueEmpty(Q))
	   cout<<"链队列为空"<<endl;
	else
	   cout<<"链队列不为空"<<endl;   
	ClearQueue(Q);
	cout<<"链队列已清空"<<endl;
	DestroyQueue(Q);
	cout<<"链队列已销毁"<<endl; 
}
//初始化 
Status InitQueue(LinkQueue &Q)
{
	Q.front=Q.rear=new QNode;//或Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode)); 
	if(!Q.front) exit(OVERFLOW);//存储分配失败
	Q.front->next=NULL;
	return OK;
}
//链队列入队 
Status EnQueue(LinkQueue &Q,QElemType e)
{
	QueuePtr p;
	p=new QNode;
	if(!p) exit(OVERFLOW);
	p->data=e;
	p->next=NULL;
	Q.rear->next=p;
	Q.rear=p;
	return OK;
} 
//链队列出队 
QElemType DeQueue(LinkQueue &Q,QElemType &e)
{
	if(Q.front==Q.rear) return ERROR;
    QueuePtr p;
    p=Q.front->next;
    e=p->data;
    Q.front->next=p->next;
    if(Q.rear==p) Q.rear=Q.front;
    delete p;
    return OK;
} 
//取链队头元素
QElemType GetHead(LinkQueue Q)
{
	if(Q.front!=Q.rear) 
	return Q.front->next->data;
}
//判断链队列是否为空 
Status QueueEmpty(LinkQueue Q)
{
	if(Q.front->next==NULL)
	   return TRUE;
	else
	   return FALSE;
} 
//清空链队列 
void ClearQueue(LinkQueue &Q)
{
	if(Q.front) Q.front->next=NULL;
} 
//销毁链队列 
void DestroyQueue(LinkQueue &Q)
{
	while(Q.front)
	{
		QueuePtr p;
		p=Q.front->next;
		delete(Q.front);
		Q.front=p;
	}
} 

 运行结果:

以上就是栈和队列的全部知识点以及代码实现了,怪不容易的嘿嘿,请打开的小伙伴一定要好好看哦!

发布了23 篇原创文章 · 获赞 30 · 访问量 8683

猜你喜欢

转载自blog.csdn.net/l218623/article/details/104101605